在循环函数外部调用时事件侦听器不工作,但在函数内部声明时一遍又一遍地声明?

Event listener not working when called outside of a recurring function, but being declared over and over again when declared inside of one?

我正在制作一种“抓住篮子里的鸡蛋”游戏,我使用箭头键的控件,运行 事件监听器,随着事件监听器的增多,会变得越来越敏感移动桨,因为它们是在设置游戏帧率的函数内部声明的,每个移动桨,但是当我将事件侦听器放在函数之外时,它不起作用。有什么建议么?这是我的代码。

var canvas = document.getElementById("ok");
var ctx = canvas.getContext("2d");
var loggingMachine = document.getElementById("loggy");
var score = 0;

const Rg = Math.floor(Math.random() * 480);
function ball(x) {
  this.x = x;
  this.y = 0;
  this.width = 20;
  this.height = 20;
}
var firstBall = new ball(Rg);

function newBall() {
  if (firstBall.y < 480) {
    ctx.clearRect(0, 0, 480, 480);
    ctx.fillRect(firstBall.x, firstBall.y, firstBall.width, firstBall.height);
    firstBall.y++;
  } else {
    const playerStart = player.x;
    const playerEnd = player.x + player.width;

    const ballStart = firstBall.x;
    const ballEnd = firstBall.x + firstBall.width;

    const test1 = ballEnd - playerStart;
    const test2 = ballStart - playerEnd;

    if (test1 >= 0 && test2 <= 0) {
      score++;
      loggingMachine.innerText = score;
    } else {
      score = 0;
    }
    firstBall.y = 0;
    firstBall.x = Math.floor(Math.random() * 480);
  }
}
function paddle(x) {
  this.x = x;
  this.y = 470;
  this.width = 70;
  this.height = 20;
}

var player = new paddle(50);
function renderPlayer() {
  ctx.fillRect(player.x, player.y, player.width, player.height);
}
function tick() {
  newBall(Rg);

  function logKey(e) {
    if (e.code === "ArrowLeft") {
      if (player.x > 0) {
        player.x = player.x - 0.05;
      }
    } else if (e.code === "ArrowRight") {
      if (player.x + player.width < 480) {
        player.x = player.x + 0.05;
      }
    }
  }
  document.addEventListener("keydown", logKey);

  renderPlayer();
  setTimeout(tick, 5);
}
loggingMachine.innerText = score;

tick();
<!DOCTYPE html>
<canvas id="ok" width="480" height="480"></canvas>
<p id="loggy"></p>
<script src="script.js"></script>

您每隔 tick() 添加了一个事件侦听器,但没有删除旧的。 你应该像下面这样把它设置在外面:

var canvas = document.getElementById("ok");
var ctx = canvas.getContext("2d");
var loggingMachine = document.getElementById("loggy");
var score = 0;

const Rg = Math.floor(Math.random() * 480);
function ball(x) {
  this.x = x;
  this.y = 0;
  this.width = 20;
  this.height = 20;
}
var firstBall = new ball(Rg);

function newBall() {
  if (firstBall.y < 480) {
    ctx.clearRect(0, 0, 480, 480);
    ctx.fillRect(firstBall.x, firstBall.y, firstBall.width, firstBall.height);
    firstBall.y++;
  } else {
    const playerStart = player.x;
    const playerEnd = player.x + player.width;

    const ballStart = firstBall.x;
    const ballEnd = firstBall.x + firstBall.width;

    const test1 = ballEnd - playerStart;
    const test2 = ballStart - playerEnd;

    if (test1 >= 0 && test2 <= 0) {
      score++;
      loggingMachine.innerText = score;
    } else {
      score = 0;
    }
    firstBall.y = 0;
    firstBall.x = Math.floor(Math.random() * 480);
  }
}
function paddle(x) {
  this.x = x;
  this.y = 470;
  this.width = 70;
  this.height = 20;
}

var player = new paddle(50);
function renderPlayer() {
  ctx.fillRect(player.x, player.y, player.width, player.height);
}
function tick() {
  newBall(Rg);     

  renderPlayer();
  setTimeout(tick, 5);
}
loggingMachine.innerText = score;

document.addEventListener("keydown", (e) => {
    if (e.code === "ArrowLeft") {
      if (player.x > 0) {
        player.x = player.x - 5;
      }
    } else if (e.code === "ArrowRight") {
      if (player.x + player.width < 480) {
        player.x = player.x + 5;
      }
    }
});

tick();
<!DOCTYPE html>
<canvas id="ok" width="480" height="480"></canvas>
<p id="loggy"></p>
<script src="script.js"></script>

您的问题: 在使用多个侦听器之前,x 坐标在一个方向上用 0.05px 更新了多次。结果是这样的:0.05 px * 100 listeners = 5 px

现在它只会在一个方向上用 0.05 px 更新一次。这太慢了,你看不到它:-) 将步骤增加到 5px,效果非常好。

提示:尝试学习如何debug your code