首页 > 解决方案 > Javascript游戏,让宇宙飞船按间隔射击

问题描述

我正在研究我的游戏技能(主要是使用阵列)来生成敌人,现在用子弹将它们击落。我可以在测试时设置项目符号,但只有在我按下一个键(比如说空格键)时才可见,并且两者之间没有间隔,所以浏览器一次无法接收那么多。

有没有什么简单的方法可以让船在间隔发射子弹(不要加载浏览器那么多),也许在去敌人[i].x / y位置删除一个敌人并且子弹可以消失?

这是我现在拥有的尽可能多的清理代码(HTML 和 JS 文件。还有一些图像,如果需要,将提供游戏的 URL 以检查它 - http://sarahkerrigan.biz/spaceship

<!DOCTYPE html>
<html>
  <head>
    <title>Space Ship</title>
  </head>
  <body>
   <h3>Space Ship</h3>

   <canvas id="canvas" width="1000" height="600"></canvas>

   <script src="spaceship.js"></script>
  </body>
</html>

这是 spaceship.js 文件:

var cvs = document.getElementById("canvas");
var ctx = cvs.getContext("2d");
//-------------------------------

// load images

var player = new Image();
var enemy = new Image();
var bullet = new Image();


player.src = "images/player.png";
enemy.src = "images/enemy.png";
bullet.src = "images/fire.png";
//-------------------------------

// vars
var score = 0;
var pause = 0;

var playerY = 300;
var playerX = 100;

var upPressed = false;
var downPressed = false;
var leftPressed = false;
var rightPressed = false;

// audio
var fire = new Audio();
var hit = new Audio();

fire.src = "sounds/fire.mp3";
hit.src = "sounds/hit.mp3";


//-------------------------------
// on key down
document.addEventListener("keydown", keyDownHandler);

function keyDownHandler(e) {
  if (e.keyCode == 87) {
    upPressed = true;
  }
  if (e.keyCode == 83) {
    downPressed = true;
  }
  if (e.keyCode == 65) {
    leftPressed = true;
  }
  if (e.keyCode == 68) {
    rightPressed = true;
  }
}

// on key up
document.addEventListener("keyup", keyUpHandler);

function keyUpHandler(e) {
  if (e.keyCode == 87) {
    upPressed = false;
  }
  if (e.keyCode == 83) {
    downPressed = false;
  }
  if (e.keyCode == 65) {
    leftPressed = false;
  }
  if (e.keyCode == 68) {
    rightPressed = false;
  }
}




//-------------------------------



function moveUp() {
 if (playerY <= canvas.height - canvas.height){
 }
 else{
  playerY -= 6;
 }
}

function moveDown() {
 if (playerY >= canvas.height - player.height){
 }
 else{
  playerY += 6;
 }
}

function moveLeft() {
 if (playerX <= canvas.width - canvas.width){
 }
 else{
  playerX -= 6;
 }
}

function moveRight() {
 if (playerX >= canvas.width - player.width){
 }
 else{
  playerX += 6;
 }
}




//-------------------------------
// Enemy coordinates

var enemies = [];

enemies[0] = {
  x: cvs.width,
  y: 0
};

//-------------------------------

// reload page

function reLoad() {
  location.reload(); // reload the page
}


//-------------------------------
// draw images

function draw() {

  ctx.fillStyle = "black";
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  if (upPressed === true) {
    moveUp();
  }
  if (downPressed === true) {
    moveDown();
  }
  if (leftPressed === true) {
    moveLeft();
  }
  if (rightPressed === true) {
    moveRight();
  }


//-------------------------------
  for (var i = 0; i < enemies.length; i++) {

    //draw the enemy
    ctx.drawImage(enemy, enemies[i].x, enemies[i].y);

    // enemy movement speed
    enemies[i].x -= 3;

    if (enemies[i].x == 880) {
      enemies.push({
        x: cvs.width,
        y: Math.floor(Math.random() * enemy.height) * 10 - enemy.height
      });
    }

    // detect collision

    // if enemy hits player
    if (playerX + player.width >= enemies[i].x && playerX <= enemies[i].x + enemy.width && (playerY <= enemies[i].y + enemy.height && playerY + player.height >= enemies[i].y)) {
      pause = 1;
    }
  }
//-------------------------------


  //draw the player
  ctx.drawImage(player, playerX, playerY);



  //draw score
  ctx.fillStyle = "#fff";
  ctx.font = "20px Verdana";
  ctx.fillText("Destroyed ships : " + score + "$", 10, cvs.height - 20);


  function onPause() {
    if (pause >= 1) {
      hit.play();
      ctx.fillStyle = "#df8a62";
      ctx.fillRect(150, 150, 280, 100);

      ctx.fillStyle = "#000";
      ctx.font = "20px Verdana";
      ctx.fillText("You died:", 165, 170);

      document.addEventListener("keydown", reLoad);
    } else if (pause <= 0) {
      requestAnimationFrame(draw);
    }
  }

  onPause();

}

draw();

标签: javascript

解决方案


您想使用时间间隔而不是侦听器。

var myVar = setInterval(timeCycle, 50);
function timeCycle() {
    //all the stuff you currently have listeners for.
}

这样,当时间间隔发生时,它只会执行一次您的按键操作。然后,如果您想更改射速,请添加以下内容:

setInterval(timeCycle, 50);
rateOfFire = 5;
shootCoolDown = 0;
function timeCycle() {
    if (shootPressed === true) {
        if(shootCoolDown === 0){
            shootCoolDown = rateOfFire;
            shoot();
        } 
    }
    if (shootCoolDown > 0){
        shootCoolDown --;
    }
}

这样,它将每 5 个游戏周期(或在这种情况下为每秒 4 轮)射击一次。

你可以做更多花哨的事情来创建一个增量时间系统,通过根据你的 timeCycle 执行时间改变你的模拟速率来抵消滞后,但这往往更加复杂和容易搞砸,所以我不建议初学者进入那个兔子洞。

[编辑] 所以,我最近看到了几个关于 deltaTime 的问题,但没有看到任何关于如何实现它的好例子;所以,这是我放在一起的一个基本示例。要实现它,只需将 GAME STUFF 部分替换为游戏周期中发生的实际代码,并通过 delta() 函数运行所有基于时间的值,它会将您的值从每秒单位转换为每个 currentFrame 的单位。

My game us under a load of <input type="text" id="lag" value="100000000"> operations per frame.<br>
My speed is = <input type="text" id="speed" value="500"> px per second<br>
I moved <span id="adjusted"></span>px this frame.<br>
FPS: <span id="fps"></span>

<script>
function wrapDelta(lastTime){
   var d = new Date();
   var n = d.getSeconds()*1000 + d.getMilliseconds();
   if (lastTime >= n) {
        lastTime -= 60000;
   }
   return n - lastTime;
}

function delta(input){
   return input * deltaCoeff / 1000;
}

var d = new Date();
var ed = new Date();
var endTime =  d.getSeconds()*1000 + d.getMilliseconds();
var startTime =  d.getSeconds()*1000 + d.getMilliseconds();
var deltaCoeffMin = 25;
var deltaCoeff = deltaCoeffMin;

setInterval(function () {
    d = new Date();
    startTime =  d.getSeconds()*1000 + d.getMilliseconds();

    // START GAME STUFF
    var lag = Math.round(Math.sqrt(document.getElementById('lag').value)); //because comparing large numbers caused a wierd lag spike at from 9999999 to 10000000 
    var speed = document.getElementById('speed').value; 
    document.getElementById('adjusted').innerHTML = delta(speed);
    document.getElementById('fps').innerHTML = (1000/deltaCoeff).toFixed(2);
    var i; var j; var k; for (i=0; i<lag; i++){ for (j=0; j<lag; j++){ k = 1234567*1.1;}} //This is just a random math loop to simulate the lag cause by actual game stuff
    // END GAME STUFF

    ed = new Date();
    endTime = ed.getSeconds()*1000 + ed.getMilliseconds();
    deltaCoeff = endTime - startTime;
    if (deltaCoeff < deltaCoeffMin){deltaCoeff = deltaCoeffMin;}
  } , deltaCoeffMin);
</script>

推荐阅读