使onkeydown事件仅针对特定键发生一次

时间:2019-01-17 03:36:51

标签: javascript html 2d-games

我正在创建一个简单的游戏,该游戏具有使玩家向前,向左转,向右转或转身的功能。我希望按键仅触发一次特定的对应功能。我发现此有用的代码仅触发该事件一次,但似乎无法弄清楚如何在其中指定某些按键。

    var shouldHandleKeyDown = true;
    document.onkeydown = function(){
      if (!shouldHandleKeyDown) return;
      shouldHandleKeyDown = false;
      // HANDLE KEY DOWN HERE
    }
    document.onkeyup = function(){
      shouldHandleKeyDown = true;
    }
})();

我想要实现的是:

用户按下吗? 向前移动功能会发生一次(即使按住向上键也是如此)

用户向左按下?左转功能发生一次,等等。

谢谢大家的帮助。

编辑说明:

我正在尝试以NES巫师之类的旧标题的风格来建造第一人称地牢爬行者。基本上,我希望每按一次前进按钮将播放器向前移动一帧。如果他们向左按,则玩家会向左转一帧,依此类推。如果您熟悉游戏,您将会明白我的意思。

3 个答案:

答案 0 :(得分:1)

我会忽略onkeydown事件,而只使用onkeyup。这样,只有在用户抬起手指时才触发该事件,从而确保每次按键仅移动一次。

要确定事件处理程序中按下了哪个键,请将事件传递给函数。 Here是指向键值的链接,因此您可以执行以下操作:

document.onkeyup = function(event) {
    var keycode = event.keyCode;

    if (keycode === 38) {
        moveUp();
    }
}

答案 1 :(得分:0)

没有一个好的方法可以解决此问题,这主要取决于您将如何使用这些关键输入。

例如,如果要控制始终更新的动画,则字典中带有{left: bool, right: bool, up: bool, down: bool}的简单信号量在 keydown 中设置为true,并设置为{{1} }(在 keyup 中),并且每帧检查一次就足够了。

false
const directions = {
  up: false,
  right: false,
  down: false,
  left: false
};
onkeydown = e => {
  const key = e.key.replace('Arrow', '').toLowerCase();
  if(key in directions) {
    e.preventDefault();
    directions[key] = true;
  }
};
onkeyup = e => {
  const key = e.key.replace('Arrow', '').toLowerCase();
  if(key in directions) {
    e.preventDefault();
    directions[key] = false;
  }
};
const w = canvas.width = innerWidth;
const h = canvas.height = innerHeight;
const ctx = canvas.getContext('2d');
const character = {
  x: w/2,
  y: h/2,
  update: function() {
    const speed = 2;
    // this is where we will check our keyboard's status
    // we do it every frame
    let dir_x = 0,
      dir_y = 0;
    dir_x += directions.left ? -1 : 0;
    dir_x += directions.right ? 1 : 0;
    dir_y += directions.up ? -1 : 0;
    dir_y += directions.down ? 1 : 0;
    this.x += dir_x * speed;
    this.y += dir_y * speed;
  },
  draw: function() {
    ctx.fillRect(this.x - 20, this.y-20, 40, 40);
  }
};

function anim() {
  character.update();
  ctx.clearRect(0,0,w, h);
  character.draw();
  requestAnimationFrame(anim);
}
anim();
:root,body{margin:0px}

但是,如果您没有保持连续的动画循环并且确实需要在第一个操作时触发此事件,那么在keydown处理程序中,您可能需要添加逻辑

<canvas id="canvas"></canvas>

... if(key in directions) { e.preventDefault(); const changed = directions[key] !== true; directions[key] = true; if(changed) { triggerChange(key); } } 可以触发您的独奏操作。

triggerChange(key)
const directions = {
  up: false,
  right: false,
  down: false,
  left: false
};

function triggerChange(dir) {
  character.update();
}

onkeydown = e => {
  const key = e.key.replace('Arrow', '').toLowerCase();
  if (key in directions) {
    e.preventDefault();
    const changed = directions[key] !== true;
    directions[key] = true;
    if (changed) {
      triggerChange(key);
    }
  }
};
onkeyup = e => {
  const key = e.key.replace('Arrow', '').toLowerCase();
  if (key in directions) {
    e.preventDefault();
    directions[key] = false;
  }
};

const w = canvas.width = innerWidth;
const h = canvas.height = innerHeight;
const ctx = canvas.getContext('2d');
const character = {
  x: w / 2,
  y: h / 2,
  update: function() {
    const speed = 5;
    // this is where we will check our keyboard's status
    // we do it every frame
    let dir_x = 0,
      dir_y = 0;
    dir_x += directions.left ? -1 : 0;
    dir_x += directions.right ? 1 : 0;
    dir_y += directions.up ? -1 : 0;
    dir_y += directions.down ? 1 : 0;
    this.x += dir_x * speed;
    this.y += dir_y * speed;
  },
  draw: function() {
    ctx.fillRect(this.x - 20, this.y - 20, 40, 40);
  }
};

function anim() {
  // it is now keydown that is responsible for character.update()
  ctx.clearRect(0, 0, w, h);
  character.draw();
  requestAnimationFrame(anim);
}
anim();
:root,body{margin:0}

答案 2 :(得分:-1)

function()更改为function(e),然后按下键在e.key

(运行摘要后,单击运行按钮下方的白色矩形,然后按键)

var shouldHandleKeyDown = true;
document.onkeydown = function(e) {
  if (!shouldHandleKeyDown) return;
  shouldHandleKeyDown = false;
  console.log(e.key);
      // HANDLE KEY DOWN HERE
}

document.onkeyup = function(){
  shouldHandleKeyDown = true;
}