app.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // @ts-check
  2. class EventEmitter {
  3. constructor() {
  4. this.listeners = {};
  5. }
  6. on(message, listener) {
  7. if (!this.listeners[message]) {
  8. this.listeners[message] = [];
  9. }
  10. this.listeners[message].push(listener);
  11. }
  12. emit(message, payload = null) {
  13. if (this.listeners[message]) {
  14. this.listeners[message].forEach((l) => l(message, payload));
  15. }
  16. }
  17. }
  18. class GameObject {
  19. constructor(x, y) {
  20. this.x = x;
  21. this.y = y;
  22. this.dead = false;
  23. this.type = '';
  24. this.width = 0;
  25. this.height = 0;
  26. this.img = undefined;
  27. }
  28. draw(ctx) {
  29. ctx.drawImage(this.img, this.x, this.y, this.width, this.height);
  30. }
  31. }
  32. class Hero extends GameObject {
  33. constructor(x, y) {
  34. super(x, y);
  35. (this.width = 99), (this.height = 75);
  36. this.type = 'Hero';
  37. this.speed = { x: 0, y: 0 };
  38. }
  39. }
  40. class Enemy extends GameObject {
  41. constructor(x, y) {
  42. super(x, y);
  43. (this.width = 98), (this.height = 50);
  44. this.type = 'Enemy';
  45. let id = setInterval(() => {
  46. if (this.y < canvas.height - this.height) {
  47. this.y += 5;
  48. } else {
  49. console.log('Stopped at', this.y);
  50. clearInterval(id);
  51. }
  52. }, 300);
  53. }
  54. }
  55. function loadTexture(path) {
  56. return new Promise((resolve) => {
  57. const img = new Image();
  58. img.src = path;
  59. img.onload = () => {
  60. resolve(img);
  61. };
  62. });
  63. }
  64. const Messages = {
  65. KEY_EVENT_UP: 'KEY_EVENT_UP',
  66. KEY_EVENT_DOWN: 'KEY_EVENT_DOWN',
  67. KEY_EVENT_LEFT: 'KEY_EVENT_LEFT',
  68. KEY_EVENT_RIGHT: 'KEY_EVENT_RIGHT',
  69. };
  70. let heroImg,
  71. enemyImg,
  72. laserImg,
  73. canvas,
  74. ctx,
  75. gameObjects = [],
  76. hero,
  77. eventEmitter = new EventEmitter();
  78. // EVENTS
  79. let onKeyDown = function (e) {
  80. console.log(e.keyCode);
  81. switch (e.keyCode) {
  82. case 37:
  83. case 39:
  84. case 38:
  85. case 40: // Arrow keys
  86. case 32:
  87. e.preventDefault();
  88. break; // Space
  89. default:
  90. break; // do not block other keys
  91. }
  92. };
  93. window.addEventListener('keydown', onKeyDown);
  94. // TODO make message driven
  95. window.addEventListener('keyup', (evt) => {
  96. if (evt.key === 'ArrowUp') {
  97. eventEmitter.emit(Messages.KEY_EVENT_UP);
  98. } else if (evt.key === 'ArrowDown') {
  99. eventEmitter.emit(Messages.KEY_EVENT_DOWN);
  100. } else if (evt.key === 'ArrowLeft') {
  101. eventEmitter.emit(Messages.KEY_EVENT_LEFT);
  102. } else if (evt.key === 'ArrowRight') {
  103. eventEmitter.emit(Messages.KEY_EVENT_RIGHT);
  104. }
  105. });
  106. function createEnemies() {
  107. const MONSTER_TOTAL = 5;
  108. const MONSTER_WIDTH = MONSTER_TOTAL * 98;
  109. const START_X = (canvas.width - MONSTER_WIDTH) / 2;
  110. const STOP_X = START_X + MONSTER_WIDTH;
  111. for (let x = START_X; x < STOP_X; x += 98) {
  112. for (let y = 0; y < 50 * 5; y += 50) {
  113. const enemy = new Enemy(x, y);
  114. enemy.img = enemyImg;
  115. gameObjects.push(enemy);
  116. }
  117. }
  118. }
  119. function createHero() {
  120. hero = new Hero(canvas.width / 2 - 45, canvas.height - canvas.height / 4);
  121. hero.img = heroImg;
  122. gameObjects.push(hero);
  123. }
  124. function drawGameObjects(ctx) {
  125. gameObjects.forEach((go) => go.draw(ctx));
  126. }
  127. function initGame() {
  128. gameObjects = [];
  129. createEnemies();
  130. createHero();
  131. eventEmitter.on(Messages.KEY_EVENT_UP, () => {
  132. hero.y -= 5;
  133. });
  134. eventEmitter.on(Messages.KEY_EVENT_DOWN, () => {
  135. hero.y += 5;
  136. });
  137. eventEmitter.on(Messages.KEY_EVENT_LEFT, () => {
  138. hero.x -= 5;
  139. });
  140. eventEmitter.on(Messages.KEY_EVENT_RIGHT, () => {
  141. hero.x += 5;
  142. });
  143. }
  144. window.onload = async () => {
  145. canvas = document.getElementById('canvas');
  146. ctx = canvas.getContext('2d');
  147. heroImg = await loadTexture('assets/player.png');
  148. enemyImg = await loadTexture('assets/enemyShip.png');
  149. laserImg = await loadTexture('assets/laserRed.png');
  150. initGame();
  151. let gameLoopId = setInterval(() => {
  152. ctx.clearRect(0, 0, canvas.width, canvas.height);
  153. ctx.fillStyle = 'black';
  154. ctx.fillRect(0, 0, canvas.width, canvas.height);
  155. drawGameObjects(ctx);
  156. }, 100);
  157. };