首页 > 解决方案 > 如何阻止按钮被按下两次

问题描述

所以我正在制作一个神,如果你点击回车,它会发射一个炮弹,回车按钮会增加球的速度。问题是当我多次点击进入时,我不知道如何制作,以至于人们无法多次点击它以使大炮超快。我也不知道如何点击按钮进入,所以我只是使用向上箭头。

document.onkeydown = (e) => {
  e.preventDefault();

  if (e.repeat) return; // Do nothing

  const { key } = e;

  switch(key) {
    case 'ArrowUp':
      cannonball.dx++,
      cannonball.dy++
      break;
  }
};

这是我正在使用它的东西

const c = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
//variables
const cannon = {
w: 150,
h: 75,
x:0,
y:0
}

const cannonball = {
x: 77,
y: 565,
r:25,
dx:0,
dy:0
}

const cannonRotate = {
degree: -43.5
}



//running the whole function
function animate(){
c.clearRect(0,0,innerWidth,innerHeight);
//cannon
c.save();
c.translate(-25,600);
c.rotate(cannonRotate.degree * Math.PI / 180);
c.fillStyle = '#000';
c.fillRect(cannon.x,cannon.y,cannon.w,cannon.h);
c.restore();

//cannonball
c.beginPath();
c.arc(cannonball.x,cannonball.y, cannonball.r, 0, Math.PI * 2, false);
c.fillStyle = '#000';
c.fill();

cannonball.x += cannonball.dx;
cannonball.y -= cannonball.dy;



document.onkeydown = (e) => {
  e.preventDefault();

  if (e.repeat) return; // Do nothing

  const { key } = e;

  switch(key) {
    case 'ArrowUp':
      cannonball.dx += 5,
      cannonball.dy += 5
      break;
  }
};

requestAnimationFrame(animate)
}

标签: javascript

解决方案


有很多方法可以做到这一点,但这里有一个节流示例,您可以尝试将其应用于您的代码。这个想法是用一个包含上次调用时间的闭包来包装一个函数。对于重复调用,在重新调用函数之前检查最后一次。一个cooldown变量确定在允许重新触发之前延迟多长时间(以毫秒为单位)。这是一个通用功能,您几乎可以将其应用于任何事情(例如,HTTP 请求以强制执行速率限制)。

除此之外,在动画循环中重新注册事件处理程序可能是一个错误。这应该是一次性的设置任务,而不是您想要每秒执行 30-60 次的任务。

至于你要节流的东西,炮弹只有在按下箭头键时才会移动是不寻常的。对于下面的最小示例,我正在限制发射率,这(可能?)对游戏更有意义。

const throttle = (fn, cooldown=1000) => {
  let lastCall = 0;
  return (...args) => {
    if (Date.now() - lastCall > cooldown) {
      lastCall = Date.now();
      fn(...args);
    }
  };
};

const canvas = document.createElement("canvas");
document.body.appendChild(canvas);
const ctx = canvas.getContext("2d");
canvas.width = innerWidth;
canvas.height = innerHeight;
ctx.fillStyle = "#000";

const cannonBalls = [];

(function animate() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  for (const e of cannonBalls) {
    e.dx *= 0.99;
    e.dy += 0.1;
    e.x += e.dx;
    e.y += e.dy;
    ctx.beginPath();
    ctx.arc(e.x, e.y, e.r, 0, Math.PI * 2);
    ctx.fill();
  }

  requestAnimationFrame(animate);
})();

const fire = throttle(() => cannonBalls.push({
  x: 10, 
  y: 10,
  dx: 10,
  dy: 0,
  r: 10
}));

document.addEventListener("keydown", e => {
  if (e.keyCode === 32) {
    e.preventDefault();
    !e.repeat && fire();
  }
});
<p>press spacebar to fire</p>


推荐阅读