Javascript: ограничение скорости, с которой слушатель события нажатия клавиш может вызывать функцию, когда удерживается - PullRequest
1 голос
/ 08 марта 2019

Я работаю над игрой на основе JavaScript, и сейчас я работаю над движением игровых персонажей и анимацией. Это контролируется, когда игрок нажимает элементы управления (WASD) во время события keydown. У меня проблема в том, что обработчик вызывается слишком быстро, когда эти клавиши нажимаются и удерживаются, из-за чего мой игровой персонаж / спрайт выглядит так, как будто у него происходит захват (потому что он слишком быстро перебирает изображения спрайта).

Как я могу ограничить скорость, которая вызывает движение персонажа / анимацию? Мой код в настоящее время выглядит так:

let canvas = document.getElementById('myCanvas');
ctx = canvas.getContext('2d');
let xPos = 10
let yPos = 10
document.addEventListener('keydown', movement)

function movement(e){
//Player Controls 
// horizontal and vertical movement
    if (e.keyCode === 87 ){
         ctx.clearRect(0,0, canvas.width, canvas.height);
         y=y-3;
         sY = 97
         runningMan();
    }
     if(e.keyCode === 83){
        ctx.clearRect(0,0, canvas.width, canvas.height);
        y=y+3;
        sY = 0
        runningMan();
    }
    if(e.keyCode === 65){
        ctx.clearRect(0,0, canvas.width, canvas.height);
        x=x-3;
        sY = 32
        runningMan();
    }
    if(e.keyCode === 68){
        ctx.clearRect(0,0, canvas.width, canvas.height);
        x=x+3;
        sY = 64
        runningMan();
    }
  
 
    // keeping the player inside the canvas
    xPos = Math.min(Math.max(x, 0+5), canvas.width-10);
    yPos = Math.min(Math.max(y, 0+5), canvas.height-10); 
}

//img,SX,SY,SW,SH,DX,DY,DW,DH)
let img = new Image();
img.src = 'runningGood.png'
let cycle = 0
let sY;
let sW = 30 
let sH = 32
let x = 0
let y = 0
let increase = 0
// setInterval(runningMan, 200);
function runningMan(){
    ctx.clearRect(0,0,sW+increase,sH+increase);
    ctx.drawImage(img,cycle*sW,sY,sW,sH,x,y,70,70)
    cycle = (cycle + 1) % 3;
  }
<!DOCTYPE html>
    <html lang='en'>
        <head>
            <meta charset='UTF-8'>
            <script src='project.js' defer></script>
            <title>1045 Project</title>
        </head>
        <body>
            <canvas id='myCanvas' width='750' height ='750' style='border: 2px solid black'></canvas>
        </body>
    </html>

1 Ответ

0 голосов
/ 08 марта 2019

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

let canvas = document.getElementById('myCanvas');
ctx = canvas.getContext('2d');
let xPos = 10
let yPos = 10

/* Add: track state of current throttle timer */
let throttle;
/* Add: When keyup happens, just reset the throttle timer */
document.addEventListener('keyup', () => {
  if (throttle) {
    clearTimeout(throttle);
    throttle = null;
  }
})

document.addEventListener('keydown', movement)

function movement(e) {

  /* Add: only allow normal keypress processing if no throttle
  timer is currently active */
  if (!throttle) {

    //Player Controls 
    // horizontal and vertical movement
    if (e.keyCode === 87) {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      y = y - 3;
      sY = 97
      runningMan();
    }
    if (e.keyCode === 83) {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      y = y + 3;
      sY = 0
      runningMan();
    }
    if (e.keyCode === 65) {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      x = x - 3;
      sY = 32
      runningMan();
    }
    if (e.keyCode === 68) {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      x = x + 3;
      sY = 64
      runningMan();
    }


    // keeping the player inside the canvas
    xPos = Math.min(Math.max(x, 0 + 5), canvas.width - 10);
    yPos = Math.min(Math.max(y, 0 + 5), canvas.height - 10);


    /* Add: Start a "throttle" timer that prevents next keyboard processing
    until timer completed */
    throttle = setTimeout(() => {

      throttle = null;

    /* Your throttle interval - reduce/increase this number to suit you needs */
    }, 1000)
  }
}

//img,SX,SY,SW,SH,DX,DY,DW,DH)
let img = new Image();
img.src = 'https://via.placeholder.com/160'
let cycle = 0
let sY;
let sW = 30
let sH = 32
let x = 0
let y = 0
let increase = 0
// setInterval(runningMan, 200);
function runningMan() {
  ctx.clearRect(0, 0, sW + increase, sH + increase);
  ctx.drawImage(img, cycle * sW, sY, sW, sH, x, y, 70, 70)
  cycle = (cycle + 1) % 3;
}
<!DOCTYPE html>
<html lang='en'>

<head>
  <meta charset='UTF-8'>
  <script src='project.js' defer></script>
  <title>1045 Project</title>
</head>

<body>
  <canvas id='myCanvas' width='750' height='750' style='border: 2px solid black'></canvas>
</body>

</html>

Общая идея здесь - запустить таймер throttle после обычной обработки keydown. Таймер throttle в основном блокирует / предотвращает немедленную обработку keydown (т. Е. Перемещение игрового персонажа) на следующей итерации цикла приложения / события (что является причиной ошибочного движения игрового персонажа).

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...