我是JS的初学者,目前正在开发一个游戏(在我的情况下是Snake游戏)的项目。一切都进行得很好,除非我立即快速按下多个键,否则Snake会死掉,因为(我认为)这是碰撞。这就是为什么我想以某种方式禁用多个按键,以尝试解决问题的原因。 我的代码:
var Snake = function()
{
//this is the direction table; UP, RIGHT, DOWN, LEFT
this.directions = [[0, -1], [1, 0], [0, 1], [-1, 0]];
}
function onKeyDown(event)
{
if (gameover)
tryNewGame();
else
{
if (event.keyCode == 37 || event.keyCode == 65)
{
if (snake.direction != 1)
snake.direction = 3;
}
else if (event.keyCode == 38 || event.keyCode == 87)
{
if (snake.direction != 2)
snake.direction = 0;
}
else if (event.keyCode == 39 || event.keyCode == 68)
{
if (snake.direction != 3)
snake.direction = 1;
}
else if (event.keyCode == 40 || event.keyCode == 83)
{
if (snake.direction != 0)
snake.direction = 2;
}
}
}
答案 0 :(得分:0)
您可以在按键功能上使用setTimeout函数,例如
编辑:2000ms只是示例时间。您可以将其设置为每1/2秒500ms,或者您想要的任何其他数量的ms
setTimeout(
function onKeyDown(event)
{
if (gameover)
tryNewGame();
else
{
if (event.keyCode == 37 || event.keyCode == 65)
{
if (snake.direction != 1)
snake.direction = 3;
}
else if (event.keyCode == 38 || event.keyCode == 87)
{
if (snake.direction != 2)
snake.direction = 0;
}
else if (event.keyCode == 39 || event.keyCode == 68)
{
if (snake.direction != 3)
snake.direction = 1;
}
else if (event.keyCode == 40 || event.keyCode == 83)
{
if (snake.direction != 0)
snake.direction = 2;
}
}
},
2000ms
);
答案 1 :(得分:0)
对于这种用例,我总是推荐去抖动或节流函数。放手,那是最好的。
Lodash对_.debounce
和_.throttle
都有不错的实现。另外,请确保您已阅读this article,以完全理解这些概念。
基本思路是在第一次调用后,在短时间内“冻结”事件处理程序。它仍然被调用并接收事件,只是没有任何作用。
答案 2 :(得分:0)
问题可能是蛇的形状更新之前方向改变了两次,因此实际上忽略了这两个方向改变中的第一个。
克服此问题的一种方法是将方向变化缓冲在队列中(实现为数组)。
因此,在关键事件处理程序中,您不会这样做:
if (snake.direction != 1)
snake.direction = 3;
但相反:
if ((snake.queue.length ? snake.queue[0] : snake.direction) != 1)
snake.queue.unshift(3);
此队列应在Snake
构造函数中初始化:
this.queue = [];
然后,当您以一定的时间间隔更新蛇的位置时,如果其中有东西,您将消耗:
if (snake.queue.length)
snake.direction = snake.queue.pop();
// Now apply this direction:
// ... this would be code you already have...
您可以为此队列设置一个最大值,因为如果用户持续按下按键的速度比蛇更新要快,它将变得很尴尬。
答案 3 :(得分:0)
如此处所述,限制事件将很好地进行。这是一个可以用作调节器的简单类:
class CooldownTimer {
constructor(time) {
this.cooldownTimeout = null
this.cooldownTime = time
this.startedAt = null
}
isReady = () => {
return !this.cooldownTimeout
}
start = () => {
if (!this.cooldownTimeout) {
clearTimeout(this.cooldownTimeout)
}
this.startedAt = Date.now()
this.cooldownTimeout = setTimeout(() => {
this.cooldownTimeout = null
}, this.cooldownTime)
}
}
您必须在某个地方(可能是您绑定事件的地方)定义一个CooldownTimer:
let keyPressCooldown = new CooldownTimer(200)
然后您可以在事件代码中使用它:
function onKeyPress(event) {
if (keyPressCooldown.isReady()) {
console.log('key pressed')
keyPressCooldown.start() // Do not forget to start the cooldown here
}
}