Javascript-如何避免重复使用键盘按键

时间:2019-01-21 08:59:19

标签: javascript preventdefault onkeydown

我正在从事蛇游戏项目(针对JavaScript课程)。 我试图避免出现“错误”,即当同时使用两个键时,游戏会认为存在碰撞,而在视觉上则没有碰撞。

Snake Game Error

键盘键管理代码

document.onkeydown = function handleKeyDown(e){
    const key = e.keyCode;
    let newDirection;
    switch(key){
        case 37:
            newDirection = "left";
            break;
        case 38:
            newDirection = "up";
            break;
        case 39:
            newDirection = "right";
            break;
        case 40:
            newDirection = "down";
            break;
        case 32:
            restart();
            return;
        default:
            return;
    }
    snakee.setDirection(newDirection);
}

如何避免这种情况? 有人告诉我了preventDefault()事件,我应该使用它吗?

EDIT1

这是我的蛇构造函数的一部分的checkCollision方法:

this.checkCollision = function(){
            let wallCollision = false;
            let snakeCollision = false;
            const head = this.body[0];
            const rest = this.body.slice(1);
            const snakeX = head[0];
            const snakeY = head[1];
            const minX = 0;
            const minY = 0;
            const maxX = widthInBlocks-1;
            const maxY = heightInBlocks-1;
            const isNotBetweenHorizontalWalls = snakeX < minX || snakeX > maxX;
            const isNotBetweenVerticalWalls = snakeY < minY || snakeY > maxY;
            if(isNotBetweenHorizontalWalls || isNotBetweenVerticalWalls){
                wallCollision = true;
            }
            for(let i = 0;i < rest.length;i++){
                if(snakeX == rest[i][0] && snakeY == rest[i][1]){
                    snakeCollision = true;
                }
            }
            return wallCollision || snakeCollision;
        };

EDIT2:

因此,在您回答完之后,这里是使用的解决方案。

我以前使用过switch,我决定改用if/else

const map = {};
  onkeydown = onkeyup = function(e){
    e = e || event;
    map[e.keyCode] = e.type == 'keydown';
    let newDirection;
    if(map[37]){
      newDirection = "left";
    } else if(map[38]){
      newDirection = "up";
    } else if(map[39]){
      newDirection = "right";
    } else if(map[40]){
      newDirection = "down";
    } else if(map[32]){
      restart();
    }
    snakee.setDirection(newDirection);
  }

,如果地图对象的所有属性都为假,那么问题仍然存在,当我同时按下两个键时会发生这种情况。

Object {
  32: false,
  37: false,
  38: false,
  39: false,
  40: false
}

我不知道如何防止这种情况。

4 个答案:

答案 0 :(得分:1)

碰撞是什么意思? onkeydown事件将仅返回按下键盘上的最后一个键,即使按住多个键也是如此。

如果先按down再按left,则onkeydown事件将返回left键的键码。

您不需要使用event.preventDefault(),因为这将停止寻找键按下键,而不会返回任何内容。

您的代码应该可以与我所看到的正常工作。

如果要检测多个击键,则应为此保留一个地图对象。

const keysPressed = {};
onkeydown = function(e) => {
  const e = e || event;
  keyPressed[e.keyCode] = e.keyCode >= 37 && e.keyCode <= 40;

  // move your snake now with the keys pressed
}

答案 1 :(得分:1)

这是游戏构建中的一个众所周知的问题,最好的方法是通过对操作进行排队。这可能是通过标志或实际队列。按键时,将记录用户操作或将其添加到列表中并执行。

您的游戏循环负责在适当的时间检查标志或输入队列,并相应地更新游戏状态。

以下教程将提供一些有关如何实现和更新基本输入状态的见解:https://developer.mozilla.org/en-US/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript/Paddle_and_keyboard_controls

答案 2 :(得分:1)

请查看at this example,了解如何处理同时击键。

在结果屏幕上单击,打开控制台,然后按top +向左或向右,您将看到自定义console.log到每个:)

var map = {}; // You could also use an array
onkeydown = onkeyup = function(e){
    e = e || event; // to deal with IE
    map[e.keyCode] = e.type == 'keydown';
    /* insert conditional here */
    console.log(map);
  
  if(map[38] && map[39]) {
    console.log('Moved Top & Right!')
  }
  
    if(map[38] && map[37]) {
    console.log('Moved Top & Left!')
  }
  

}

window.addEventListener('keydown', onkeyup);
window.addEventListener('keyup', onkeydown);

基于以下问题的示例:How to detect if multiple keys are pressed at once using JavaScript?

答案 3 :(得分:0)

您应该使用onkeyup事件代替onkeydown事件,它将解决您的碰撞问题。