Как предотвратить множественные нажатия клавиш в Javascript - PullRequest
0 голосов
/ 18 апреля 2019

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

Ответы [ 4 ]

0 голосов
/ 18 апреля 2019

Как уже упоминалось, регулирование события будет работать хорошо. Вот простой класс, который может служить вашим регулятором:

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
  }
}
0 голосов
/ 18 апреля 2019

Я всегда рекомендую функцию debounce или throttled для такого случая использования.Руки вниз, это лучшее.

У Lodash есть достойная реализация как _.debounce и _.throttle.Также убедитесь, что вы прочитали эту статью , чтобы полностью понять концепции.

Основная идея заключается в том, что после 1-го вызова вы «замораживаете» обработчик событий на короткий период времени.Он все еще вызывается и получает события, но не имеет никакого эффекта.

0 голосов
/ 18 апреля 2019

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

Способ преодолеть это состоит в том, чтобы буферизовать изменения направления в очереди (реализовано как массив).

Таким образом, в вашем ключевом обработчике событий вы бы этого не сделали:

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...

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

0 голосов
/ 18 апреля 2019

вы можете использовать функцию setTimeout для вашей функции нажатия клавиш, как это ...

РЕДАКТИРОВАТЬ: 2000 мс просто пример времени. Вы можете сделать это 500 мсек за каждую 1/2 секунды или любое другое количество мсек, которое вы хотите

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
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...