如何阻止按钮被按下两次



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

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)
}

如果我正确理解你的问题,你想限制按键间隔,对吗?因此,您可以通过实现一个计时器来实现这一点,该计时器在完成之前忽略下一次按键:

let ignoreKeyPress = false;
document.onkeydown = (e) => {
e.preventDefault();
if (e.repeat || ignoreKeyPress) return; // Do nothing
ignoreKeyPress = true;
setTimeout(() => ignoreKeyPress = false, 1000); // change the 1000 to the interval between keypresses that you want in miliseconds.
const { key } = e;
switch(key) {
case 'ArrowUp':
cannonball.dx++,
cannonball.dy++
break;
}
};

有很多方法可以做到这一点,但这里有一个节流示例,您可以尝试将其应用于代码。这个想法是用一个包含最后一次调用时间的闭包来包装函数。对于重复调用,在重新调用函数之前会检查最后一次时间。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>

最新更新