Не работает скрипт по стрельбе в canvas

var game = {
  sprites: {
    battleship: undefined,
    enemyShip: undefined,
    //Пуля
    bullet: undefined
  },

  init: function() {
    var canvas = document.getElementById('myCanvas');
    this.ctx = canvas.getContext("2d");

    this.width = canvas.width;
    this.height = canvas.height;

    window.addEventListener('keydown', (event) => {
      if (event.keyCode == 37 && game.battleship.x > 0) {
        game.battleship.x -= 8
      } else if (event.keyCode == 39 && game.battleship.x < 710) {
        game.battleship.x += 8
      }
    });
  },

  load: function() {
    for (var key in this.sprites) {
      this.sprites[key] = new Image();
      this.sprites[key].src = "sprites/" + key + ".png";
    }
  },

  start: function() {
    this.init();
    this.load();
    this.run();
  },

  render: function() {
    this.ctx.clearRect(0, 0, this.width, this.height);
    this.ctx.drawImage(this.sprites.battleship, battleship.x, battleship.y, 68, 68);

    for (var i = 0; i < this.enemyShipes.length; i++) {
      let enemyShip = this.enemyShipes[i];
      this.ctx.drawImage(this.sprites.enemyShip, enemyShip.x, enemyShip.y, 60, 60);

      if (enemyShip.y !== battleship.y - 61) {
        enemyShip.y += enemyShip.grav;
      }

      if (enemyShip.y == 60) {
        this.enemyShipes.push({
          x: Math.floor(Math.random() * 710),
          y: 0,
          grav: 0
        });
      };
    }

    //Вот я повесил событие в котором условие которое проверяет, если нажата кнопка пробел то этот 
    //элемент должен появляться на холсте, но пуля не появляется
    window.addEventListener('keydown', (event) => {
      if (event.keyCode == 32) {
        this.ctx.drawImage(this.sprites.bullet, this.bullet.x, this.bullet.y, 18, 32);
      }
    })
  },

  run: function() {
    this.render();

    window.requestAnimationFrame(() => {
      game.run();
    });
  }
};

game.battleship = {
  x: 355,
  y: 520
}

let battleship = game.battleship;

game.enemyShipes = [];
game.enemyShipes[0] = {
  x: Math.floor(Math.random() * 710),
  y: 0,
  grav: 1
}

//Параметры пули
game.bullet = {
  x: battleship.x + 25,
  y: battleship.y
}

window.addEventListener('load', () => {
  game.start()
});
* {
  padding: 0;
  margin: 0;
}

@font-face {
  font-family: cosmoFont;
  src: url(fonts/CosmoShrift.otf);
}

body {
  background-image: url(sprites/background.jpg);
  background-repeat: no-repeat;
  font-family: cosmoFont;
}

canvas {
  background-color: #686868;
  opacity: 0.5;
  display: block;
  margin: 0 auto;
  margin-top: 40px;
}

.game-name {
  color: #ffffff;
  text-align: center;
  font-size: 40px;
  margin-top: 20px;
}
<p class="game-name">Cosmo War</p>
<canvas id="myCanvas" width="780" height="620"></canvas>


Ответы (1 шт):

Автор решения: Ein

Проблема заключается в том, что не сохраняется и не отрисовывается в новом кадре уже созданный снаряд, как это делается с кораблями. Т.е. если мы отключим очистку экрана, то увидим отрисованый снаряд:

var game = {
  sprites: {
    battleship: undefined,
    enemyShip: undefined,
    //Пуля
    bullet: undefined
  },

  init: function () {
    var canvas = document.getElementById("myCanvas");
    this.ctx = canvas.getContext("2d");

    this.width = canvas.width;
    this.height = canvas.height;

    window.addEventListener("keydown", (event) => {
      if (event.keyCode == 37 && game.battleship.x > 0) {
        game.battleship.x -= 8;
      } else if (event.keyCode == 39 && game.battleship.x < 710) {
        game.battleship.x += 8;
      }
    });
  },

  load: function () {
    for (var key in this.sprites) {
      this.sprites[key] = new Image();
      this.sprites[
        key
      ].src = `https://via.placeholder.com/50x50.png?text=${key}`; //"sprites/" + key + ".png";
    }
  },

  start: function () {
    this.init();
    this.load();
    this.run();
  },

  render: function () {
    //this.ctx.clearRect(0, 0, this.width, this.height);
    this.ctx.drawImage(
      this.sprites.battleship,
      battleship.x,
      battleship.y,
      68,
      68
    );

    for (var i = 0; i < this.enemyShipes.length; i++) {
      let enemyShip = this.enemyShipes[i];
      this.ctx.drawImage(
        this.sprites.enemyShip,
        enemyShip.x,
        enemyShip.y,
        60,
        60
      );

      if (enemyShip.y !== battleship.y - 61) {
        enemyShip.y += enemyShip.grav;
      }

      if (enemyShip.y == 60) {
        this.enemyShipes.push({
          x: Math.floor(Math.random() * 710),
          y: 0,
          grav: 0
        });
      }
    }

    //Вот я повесил событие в котором условие которое проверяет, если нажата кнопка пробел то этот
    //элемент должен появляться на холсте, но пуля не появляется
    window.addEventListener("keydown", (event) => {
      if (event.keyCode == 32) {
        this.ctx.drawImage(
          this.sprites.bullet,
          this.bullet.x,
          this.bullet.y,
          50,
          50
        );
      }
    });
  },

  run: function () {
    this.render();

    window.requestAnimationFrame(() => {
      game.run();
    });
  }
};

game.battleship = {
  x: 100,
  y: 100
};

let battleship = game.battleship;

game.enemyShipes = [];
game.enemyShipes[0] = {
  x: Math.floor(Math.random() * 200),
  y: 0,
  grav: 1
};

//Параметры пули
game.bullet = {
  x: battleship.x + 100,
  y: battleship.y
};

window.addEventListener("load", () => {
  game.start();
});
canvas {
  width: 300px;
  height: 300px;
}
<canvas id="myCanvas"></canvas>

→ Ссылка