Как нарисовать пули у игрока в ванильном Javascript? - PullRequest
1 голос
/ 20 марта 2019

Я пытаюсь сделать аркадный шутер с прокруткой вверх.Я застрял на том, как отвести пули вверх от игрока туда, где будут враги.Я использую setInterval, чтобы повторить стрельбу в месте нахождения игрока, но пули следуют только за истребителем, сбрасывая интервал каждый раз, когда игрок перемещается на указанное количество.

Любая помощь?

Вот мой код на данный момент.

Заранее спасибо.

var project, ctx, img, img2, width, height, mid, midh, startPx, startPy, audio,interval,bulletStartPx,bulletStartPy;
var score = 0;

function setUp() {
 project = document.getElementById("project");
 ctx = project.getContext("2d");
 width = 505;
 height = 900;
 mid = width/2;
 midh = height/2;
 startPx = width/2-30;
 startPy = height-150;

 audio = new Audio("bgm.mp3");
 audio.play();

 img = new Image();
 img2 = new Image();
 img.src = "bg.png";
 img2.src = "fighterjet.png"
 img.onload = function(){
   ctx.shadowColor = "#ffffff";
   ctx.shadowBlur = 15;
   ctx.drawImage(img, 0, 0);
   ctx.drawImage(img2, startPx, startPy)
 }
 
 window.addEventListener("keydown", checkKeyPress);
}

function drawObject(x, y) {
  ctx.drawImage(img2, startPx, startPy)
}

function checkKeyPress(event) {
  if (event.keyCode == "87") {//W(UP)
    ctx.clearRect(0,0,width,height);
    if (startPy >= 20) {
    startPy -= 20;
    }
    ctx.drawImage(img, 0, 0);
    ctx.drawImage(img2, startPx, startPy)
  } else if (event.keyCode == "83") {//S(DOWN)
    ctx.clearRect(0,0,width,height);
    if (startPy <= 785) {
    startPy += 20;
    }
    ctx.drawImage(img, 0, 0);
    ctx.drawImage(img2, startPx, startPy)
  } else if (event.keyCode == "65") {//A(LEFT)
    ctx.clearRect(0,0,width,height);
    if (startPx >= 0) {
    startPx -= 20;
    }
    ctx.drawImage(img, 0, 0);
    ctx.drawImage(img2, startPx, startPy)
  } else if (event.keyCode == "68") {//D(RIGHT)
    ctx.clearRect(0,0,width,height);
    if (startPx <= 410) {
    startPx += 20;
    }
    ctx.drawImage(img, 0, 0);
    ctx.drawImage(img2, startPx, startPy)
  } else if (event.keyCode == "72") {
    for (let i = 0; i < 6; i++) {
      bullets();
  }
}
}

function bullets() {
  return setInterval(function(){
          bulletStartPx = startPx+48;
          bulletStartPy = startPy-30;
          ctx.fillStyle = "gold"
          ctx.beginPath();
          ctx.arc(bulletStartPx,bulletStartPy,5,0,2*Math.PI);
          ctx.fill();
          score += 25; }, 100);
}

function GameOver(){
  document.getElementById('bm').pause();
  ctx.font = '30px Courier New'
  ctx.filltext('GAME OVER', mid, midh)
  ctx.filltext('Your score was: '+score, mid, midh+40)
}

function showScore(){
  ctx.fillStyle = '#ff0000'
  ctx.font = '18px Courier New'
  ctx.text(score, width-10, 15)
}






/*
function bullet(){
  this.x = startPx;
	this.y = startPy - 10;

  this.draw = function() {
    ctx.fillStyle = "#b20808";
    ctx.shadowColor = "#b20808";
    ctx.shadowBlur = 15;
    this.y -= bulletSpeed;
    ctx.fillRect(this.x, this.y, 2, 8);
  }
}

function fireGun(){
if (event.keyCode == "32") {
   bullet();
   }
}*/
<!DOCTYPE html>
<html>
  <head>
    <title>Project</title>
    <meta charset="utf-8">
    <script src="project.js" type="text/javascript" defer></script>
  </head>
  <body>
    <h1>Arcade Shooter</h1>
    <fieldset>
    <legend><h2>Instructions:</h2></legend>
    <h3>Press W, A, S, D to Move</h3>
    <h3>Press Space Bar to Fire</h3>
    <h3>Goal: Survive as long as you can!</h3>
    </fieldset>
    <br>
    <canvas id="project" style="border-style: solid" width=505 height=900 ></canvas>
    <br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      <input id="start" type="button" value="START THE GAME" onclick="setUp()" style="width: 300px">
  </body>
</html>

Ответы [ 2 ]

0 голосов
/ 20 марта 2019

Вы не хотите использовать setInterval каждый раз, когда вы запускаете пули.Вы хотите использовать один setInterval для всей игры, который вызывает функцию обновления или рисования для каждого игрового объекта.Например

var game={
  //this is a list of items in the game I want to move around or do stuff
  //nothing there yet
  objects:[]
}
//this is a bullet object which can be created calling new bullet()
function Bullet(){
   //IM CHEATING HERE. DON'T DRAW TO THE DOM FOR GAMES
   //this is just a shortcut instead of drawing on a canvas
  this.object=document.createElement('div');
  this.object.style.width="10px";
  this.object.style.height="10px";
  this.object.style.position='absolute';
  this.object.style.top="100px";
  this.object.style.backgroundColor='red';
  document.body.appendChild(this.object)
  ///
  //these hold the bullet's current location on screen
  this.x=100;
  this.y=100;

  //this is the update function that gets called every frame
  this.update=function(){
     //I'm updating the bullet's y position.
    this.y-=10;
    if(this.y>0){
     
      //don't draw to the dom like this. use canvas like you were doing.
      this.object.style.top=this.y+"px";
    }
  }
}

//now let's add a bullet to the game
game.objects.push(new bullet());

//the function that updates each of our objects
function runGame(){
  for(var i=0;i<game.objects.length;i++){
      game.objects[i].update();
  }
}
//start the game
setInterval(runGame, 1000)

ПРИМЕЧАНИЕ: НЕ рисуйте на DOM, как это.Используйте холст, как вы делали.Я просто сделал дом в качестве ярлыка, чтобы продемонстрировать

0 голосов
/ 20 марта 2019

1) вам нужно переопределить глобальную переменную, где вы будете отслеживать все:

var gameData = {
    interval: null, // Controls the refresh
    redrawRequired: false, // Flag
    allBullets: [], // Moving bullets
    defaultBulletSpeed: 20 // Bullet speed
}

2) Проверять действие только в функции checkKeyPress (событие), включая действие fireGun:

function checkKeyPress(event) {
    if (event.keyCode == "87") {//87 W(UP)
        if (startPy >= 20) {
            startPy -= 20;
            gameData.redrawRequired = true;
        }
    } else if (event.keyCode == "83") {//83 S(DOWN)
        if (startPy <= 785) {
            startPy += 20;
            gameData.redrawRequired = true;
        }
    } else if (event.keyCode == "65") {//65 A(LEFT)
        if (startPx >= 0) {
            startPx -= 20;
            gameData.redrawRequired = true;
        }
    } else if (event.keyCode == "68") {//68 D(RIGHT)
        if (startPx <= 410) {
            startPx += 20;
            gameData.redrawRequired = true;
        }
    } else if (event.keyCode == "72") { // 72 SPACEBAR ?? Actually H
        fireGun();
    }
}

3) Вот как вы определяете объект маркера и функцию firegun ():

function Bullet() {
    // Object defining a bullet.
    this.x = startPx;
    this.y = startPy - 10;
    this.bulletSpeed = gameData.defaultBulletSpeed;
}

Bullet.prototype.draw = function () {
    // Draws the bullet on canvas...
    ctx.fillStyle = "#b20808";
    ctx.shadowColor = "#b20808";
    ctx.shadowBlur = 15;
    ctx.fillRect(this.x, this.y, 2, 8);
}

Bullet.prototype.move = function () {
    // Moves the bullet...
    this.y = this.y - this.bulletSpeed;
}


function fireGun() {
    var newBullet = new Bullet();
    gameData.allBullets.push(newBullet);
}

4) Затем вы решаете, когда перерисовывать холст, используя одну основную функцию (refreshGame).и еще одна функция для проверки наличия маркеров для обновления (refreshBullets):

function refreshBullets() {
    var i = 0;
    var currentBullet;
    // Start by eliminating bullets out of the screen...
    while (i < gameData.allBullets.length) {
        currentBullet = gameData.allBullets[i];
        if (currentBullet.y < -10) {
            gameData.allBullets.splice(i, 1); // Remove the bullet outside of the screen.
        } else {
            currentBullet.move();
            gameData.redrawRequired = true;
            i += 1; // Next bullet...
        }
    }
}


function refreshGame() {
    refreshBullets();
    if (gameData.redrawRequired) {
        ctx.clearRect(0,0,width,height);
        ctx.drawImage(img, 0, 0, width, height);
        ctx.drawImage(img2, startPx, startPy);

        for (var i = 0; i < gameData.allBullets.length; i++) {
            gameData.allBullets[i].draw();
        }
    }
    gameData.redrawRequired = false;
}

5) И, наконец, вы инициализируете целое, включая setInterval в функции setUp ():

function setUp() {
    project = document.getElementById("project");
    ctx = project.getContext("2d");
    width = 505;
    height = 900;
    mid = width / 2;
    midh = height / 2;
    startPx = width / 2 - 30;
    startPy = height - 150;

    audio = new Audio("bgm.mp3");
    audio.play();

    img = new Image();
    img2 = new Image();
    img.src = "bg.png";
    img2.src = "fighterjet.png"
    img.onload = function() {
        ctx.shadowColor = "#ffffff";
        ctx.shadowBlur = 15;
        ctx.drawImage(img, 0, 0, width, height);
        ctx.drawImage(img2, startPx, startPy);
    }

    window.addEventListener("keydown", checkKeyPress);

    // Here ! And do something about that start button or the game will start over again...
    gameData.interval = window.setInterval(refreshGame, 100);
    document.getElementById("start").style.display = "none";
    project.focus();
}

Примечания:

  • Подход холста с setInterval считается плохим подходом из-за проблем производительности.Попробуйте найти «обновление интервала JavaScript с помощью canvas», есть другие способы решения проблемы.Переменная / свойство refreshRequired является только заполнителем для объяснения обходного пути.На самом деле, вам придется постоянно перерисовывать сцену, так как фон, цели и угрозы будут перемещаться ниже струи, и вы обновите счет в процессе.

  • Перед написанием кода выДолжен ли дизайн игры, каковы цели, персонажи, элементы управления, пределы, уровни ....... Бумага и карандаш это хорошее начало.Проблема в том, что когда вы начинаете писать код заранее, вы застреваете в тот момент, когда спрашиваете себя, как заставить пулю столкнуться с целью?А что если я смогу использовать ракеты вместо этого?В конце концов, ваш код станет тяжелым и потребляет много ресурсов процессора, потому что вы пытались решить проблему при создании другой ... Просто совет;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...