Search code examples
javascriptpreventdefaultonkeydown

Javascript - How to avoid the double use of keyboard keys


I'm working on a snake game project (For a JavaScript course). I try to avoid a "bug" that when two keys are used simultaneously, the game considers that there is collision while visually no.

Snake Game Error

Code for keyboard key management

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

How to avoid this? Someone told me about the preventDefault () event, should I use it?

EDIT1

Here is the checkCollision method that is part of my constructor function for the snake:

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:

So, after your answers, here is the solution used.

I used a switch before, I decided to use an if/else instead.

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

BUT, the problem still exist if all the properties of the map object are at false, what happens when I press two keys simultaneously.

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

I don't know how to prevent this.


Solution

  • Please take a look at this example on how to handle simultaneous keystrokes.

    Click on the results screen with the console opened and press top + left or right and you'll see custom console.log to each one :)

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

    Example made based on this question: How to detect if multiple keys are pressed at once using JavaScript?