dialog.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. class Dialog {
  2. constructor() {
  3. this.height = 150;
  4. this.margin = { left: 16, bottom: 16, right: 16 };
  5. this.padding = { left: 8, top: 8, right: 8 };
  6. this.width = canvas.width;
  7. this.fontSize = 32;
  8. this.fontSize = this.width / 25;
  9. this.portrait = { width: 100, height: 128 };
  10. this.portraitFloat = 16;
  11. this.side = 0;
  12. this.text = "";
  13. this.characters = [];
  14. this.characters.push(new HeroCharacter());
  15. this.characters.push(new VillainCharacter());
  16. this.characters.push(new EmptyCharacter());
  17. this.character = this.characters[this.side];
  18. this.isDisplaying = false;
  19. }
  20. display(character, side, text) {
  21. this.character = this.characters[character];
  22. this.side = side;
  23. this.text = text;
  24. this.isDisplaying = true;
  25. }
  26. hide() {
  27. this.isDisplaying = false;
  28. }
  29. update(delta) {
  30. this.portraitFloat = 16 + (4 * Math.sin(new Date().getTime() / 100));
  31. }
  32. draw(context) {
  33. if (!this.isDisplaying) {
  34. return;
  35. }
  36. context.save();
  37. context.translate(this.margin.left, canvas.height - this.height);
  38. if (this.side == 0) {
  39. context.save();
  40. context.translate(0, -this.portrait.height - this.portraitFloat);
  41. context.fillStyle = "rgba(0, 0, 0, 0.5)";
  42. context.beginPath();
  43. context.rect(0, 0, this.portrait.width, this.portrait.height);
  44. context.fill();
  45. this.character.draw(context);
  46. context.restore();
  47. }
  48. if (this.side == 1) {
  49. context.save();
  50. context.translate(this.width - (this.margin.left + this.margin.right + this.portrait.width), - this.portrait.height - this.portraitFloat);
  51. context.fillStyle = Color.TransparentBlack;
  52. context.beginPath();
  53. context.rect(0, 0, this.portrait.width, this.portrait.height);
  54. context.fill();
  55. this.character.draw(context);
  56. context.restore();
  57. }
  58. context.fillStyle = Color.TransparentBlack;
  59. context.beginPath();
  60. context.rect(0, 0, this.width - (this.margin.left + this.margin.right), this.height - this.margin.bottom);
  61. context.fill();
  62. context.fillStyle = Color.White;
  63. context.textAlign = "left";
  64. context.font = `${this.fontSize}px Arial`;
  65. let line = 1;
  66. let text = this.text;
  67. while (this.textIsTooLong(text, context)) {
  68. let shortTextIndex = this.getShortTextIndex(text, context);
  69. let shortText = text.substr(0, shortTextIndex);
  70. text = text.substr(shortTextIndex);
  71. this.drawTextLine(shortText, context, line);
  72. line++;
  73. }
  74. this.drawTextLine(text, context, line);
  75. context.restore();
  76. }
  77. drawTextLine(text, context, line) {
  78. let bounds = context.measureText(text);
  79. let textHeight = Math.max(Math.ceil(this.fontSize), bounds.actualBoundingBoxAscent + bounds.actualBoundingBoxDescent);
  80. context.fillText(text, this.padding.left, this.padding.top + (line * textHeight));
  81. }
  82. getShortTextIndex(text, context) {
  83. while (this.textIsTooLong(text, context)) {
  84. let words = text.split(" ");
  85. words.pop();
  86. text = words.join(" ");
  87. }
  88. return text.length;
  89. }
  90. textIsTooLong(text, context) {
  91. let bounds = context.measureText(text);
  92. return bounds.width > this.width - (this.padding.left + this.padding.right + this.margin.left + this.margin.right);
  93. }
  94. onResize() {
  95. this.width = canvas.width;
  96. this.fontSize = Math.min(32, this.width / 25);
  97. }
  98. }
  99. class HeroCharacter {
  100. constructor() {
  101. this.currentMood = 0;
  102. }
  103. setMood(newMood) {
  104. this.currentMood = newMood;
  105. }
  106. draw(context) {
  107. switch (this.currentMood) {
  108. case 0:
  109. default:
  110. context.fillStyle = Color.LightBlue;
  111. context.beginPath();
  112. context.rect(10, 20, 80, 80);
  113. context.fill();
  114. context.strokeStyle = Color.Black;
  115. context.fillStyle = Color.Black;
  116. context.lineWidth = 6;
  117. context.beginPath();
  118. context.arc(25, 50, 10, Math.PI, 2 * Math.PI);
  119. context.stroke();
  120. context.beginPath();
  121. context.arc(75, 50, 10, Math.PI, 2 * Math.PI);
  122. context.stroke();
  123. context.beginPath();
  124. context.arc(50, 65, 10, 0, Math.PI);
  125. context.fill();
  126. break;
  127. }
  128. }
  129. speak() {
  130. sound.playPingSequence(["C6", "C7", "E6", "E7"], 100, 1);
  131. }
  132. }
  133. class VillainCharacter {
  134. constructor() {
  135. this.currentMood = 1;
  136. }
  137. setMood(newMood) {
  138. this.currentMood = newMood;
  139. }
  140. draw(context) {
  141. switch (this.currentMood) {
  142. case 1:
  143. default:
  144. context.fillStyle = Color.Gray;
  145. context.beginPath();
  146. context.arc(20, 35, 10, Math.PI / 2, 3 * Math.PI / 2);
  147. context.rect(20, 25, 60, 20);
  148. context.arc(80, 35, 10, 3 * Math.PI / 2, Math.PI / 2);
  149. context.fill();
  150. context.beginPath();
  151. context.arc(20, 55, 10, Math.PI / 2, 3 * Math.PI / 2);
  152. context.rect(20, 45, 60, 20);
  153. context.arc(80, 55, 10, 3 * Math.PI / 2, Math.PI / 2);
  154. context.fill();
  155. context.beginPath();
  156. context.arc(20, 75, 10, Math.PI / 2, 3 * Math.PI / 2);
  157. context.rect(20, 65, 60, 20);
  158. context.arc(80, 75, 10, 3 * Math.PI / 2, Math.PI / 2);
  159. context.fill();
  160. context.beginPath();
  161. context.arc(20, 95, 10, Math.PI / 2, 3 * Math.PI / 2);
  162. context.rect(20, 85, 60, 20);
  163. context.arc(80, 95, 10, 3 * Math.PI / 2, Math.PI / 2);
  164. context.fill();
  165. context.fillStyle = Color.Black;
  166. context.beginPath();
  167. context.moveTo(30, 40);
  168. context.lineTo(45, 50);
  169. context.lineTo(25, 50);
  170. context.lineTo(30, 40);
  171. context.fill();
  172. context.beginPath();
  173. context.moveTo(70, 40);
  174. context.lineTo(55, 50);
  175. context.lineTo(75, 50);
  176. context.lineTo(70, 40);
  177. context.fill();
  178. context.lineWidth = 6;
  179. context.beginPath();
  180. context.moveTo(40, 65);
  181. context.lineTo(60, 65);
  182. context.stroke();
  183. break;
  184. }
  185. }
  186. speak() {
  187. sound.playPingSequence(["C4", "F3", "A3", "D3"], 100, 1);
  188. }
  189. }
  190. class EmptyCharacter {
  191. constructor() {
  192. }
  193. draw(context) {
  194. }
  195. speak() {
  196. }
  197. }
  198. class SplashText {
  199. constructor(text, x, y, size) {
  200. this.backgroundColor = Color.DarkGray;
  201. this.textColor = Color.LightBlue;
  202. this.x = x;
  203. this.y = y;
  204. this.width = size && size.width ? size.width : 400;
  205. this.height = size && size.height ? size.height : 100;
  206. this.center = { x: this.width / 2, y: this.height / 2 };
  207. this.text = text;
  208. this.fontSize = 48;
  209. this.skew = 50;
  210. }
  211. update(delta) {
  212. }
  213. draw(context) {
  214. context.save();
  215. context.translate(this.x, this.y);
  216. context.textAlign = "center";
  217. context.font = `${this.fontSize}px Arial`;
  218. let textBounds = context.measureText(this.text);
  219. this.width = Math.min(canvas.width - 100, Math.max(this.width, textBounds.width));
  220. this.center.x = this.width / 2;
  221. context.fillStyle = Color.Black;
  222. context.beginPath();
  223. context.moveTo(- this.center.x - this.skew + 5, - this.center.y + 5);
  224. context.lineTo(+ this.center.x + 5, - this.center.y + 5);
  225. context.lineTo(+ this.center.x + this.skew + 5, + this.center.y + 5);
  226. context.lineTo(- this.center.x + 5, + this.center.y + 5);
  227. context.lineTo(- this.center.x - this.skew + 5, - this.center.y + 5);
  228. context.fill();
  229. context.fillStyle = this.backgroundColor;
  230. context.beginPath();
  231. context.moveTo(- this.center.x - this.skew, - this.center.y);
  232. context.lineTo(+ this.center.x, - this.center.y);
  233. context.lineTo(+ this.center.x + this.skew, + this.center.y);
  234. context.lineTo(- this.center.x, + this.center.y);
  235. context.lineTo(- this.center.x - this.skew, - this.center.y);
  236. context.fill();
  237. context.fillStyle = this.textColor;
  238. context.fillText(this.text, 0, this.fontSize / 3);
  239. context.restore();
  240. }
  241. }
  242. class FadingHelp {
  243. constructor() {
  244. this.delay = new Date().getTime() + 5000;
  245. }
  246. update(delta) {
  247. }
  248. draw(context) {
  249. }
  250. mouseHelp(context) {
  251. }
  252. }