Javascript - Как избежать двойного использования клавиш клавиатуры - PullRequest
0 голосов
/ 21 января 2019

Я работаю над проектом игры со змеями (для курса 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);
}

Как этого избежать? Кто-то сказал мне о событии protectDefault (), стоит ли его использовать?

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

НО , проблема все еще существует, если все свойства объекта карты имеют значение false, что происходит, когда я нажимаю две клавиши одновременно.

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

Я не знаю, как это предотвратить.

Ответы [ 4 ]

0 голосов
/ 21 января 2019

Пожалуйста, посмотрите в этом примере о том, как обрабатывать одновременные нажатия клавиш.

Нажмите на экран результатов с открытой консолью и нажмите top + left или right, и вы увидитенастраиваемый 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);

Пример, составленный на основе этого вопроса: Как определить, нажимается ли сразу несколько клавиш с использованием JavaScript?

0 голосов
/ 21 января 2019

вы должны использовать событие onkeyup вместо onkeydown, это решит вашу проблему столкновения.

0 голосов
/ 21 января 2019

Это хорошо известная проблема в построении игры, и лучший способ сделать это - поставить в очередь действия. Это может быть через флаги или фактическую очередь. При нажатии клавиши пользовательские действия отмечаются или добавляются в список и выполняются.

Ваш игровой цикл отвечает за проверку флагов или очереди ввода в соответствующее время и соответственно обновляет состояние игры.

Следующий урок даст некоторое представление о том, как реализовать и обновить основные состояния ввода: https://developer.mozilla.org/en-US/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript/Paddle_and_keyboard_controls

0 голосов
/ 21 января 2019

что вы подразумеваете под столкновением? Событие 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
}
...