繁体   English   中英

用另一个键按下时键事件发生两次

[英]Key Event happening twice when pressed with another key

在我的游戏中,我使用事件侦听器keyupkeydown来跟踪按下了哪些键( this.input是对下面Input函数的引用):

$(document.body).on('keydown', this.input.keyPress.bind(this.input));
$(document.body).on('keyup', this.input.keyPress.bind(this.input));

一切都按预期工作,直到我一次按下 2 个键。 左键将玩家向左移动,Shift 键发射武器。 另外,它们工作正常。 但是,如果同时按下并按住两者,则玩家会射击两次。

这是我用来处理输入的代码(为简洁起见,删除了其他关键事件)

shootSpecial只应调用一次,因为keyMap.shift仅在keydown上为true 一旦keyup被触发,它就会被设置为falsekeyMap[key] = e.type === 'keydown';

var Input = function () {
  var keyMap = {};

  this.handleKeyPress = function () {
    if (keyMap.arrowleft === true) {
      game.player.moving.left = true;
    } else if (keyMap.shift === true) {
      game.player.shootSpecial();
    }
  };

  this.keyPress = function (e) {
    var key = e.key.toLowerCase();
    if (key === ' ') {
      key = 'space';
    }
    keyMap[key] = e.type === 'keydown';
    console.log(key, keyMap[key]);
    this.handleKeyPress();
  };
};

console.log报告leftshiftkeydown上为true ,然后在keyup上都为false ,所以我不太确定为什么它会触发两次shootSpecial事件。

 var keyMap = {}; var handleKeyPress = function () { if (keyMap.arrowleft === true) { console.log('left'); } else if (keyMap.shift === true) { console.log('shift'); } }; var keyPress = function (e) { var key = e.key.toLowerCase(); keyMap[key] = e.type === 'keydown'; if (document.getElementById(key)) document.getElementById(key).innerText = e.type === 'keydown'; handleKeyPress(); } document.addEventListener('keydown', keyPress); document.addEventListener('keyup', keyPress);
 LEFT:<div id="arrowleft">false</div> SHIFT:<div id="shift">false</div>

正如您在小提琴中看到的那样,一个事件被调用两次。

您的问题是您使用相同的代码处理 keydown 和 keyup,结果是在按下 key2 的同时释放 key1 与按下 key2 具有相同的效果。

修复非常简单:根本不要在 keyup 事件上调用您的 handleKeyPress 函数。

 var keyMap = {}; var handleKeyPress = function () { if (keyMap.arrowleft === true) { console.log('left'); } else if (keyMap.shift === true) { console.log('shift'); } }; var keyPress = function (e) { var key = e.key.toLowerCase(); keyMap[key] = e.type === 'keydown'; if (document.getElementById(key)) document.getElementById(key).innerText = e.type === 'keydown'; // Only call handleKeyPress if the key is pressed if (keyMap[key]) { handleKeyPress(); } } document.addEventListener('keydown', keyPress); document.addEventListener('keyup', keyPress);
 LEFT:<div id="arrowleft">false</div> SHIFT:<div id="shift">false</div>


添加建议以回应 OP 的评论。 你的问题是你的 handleKeyPress() 没有关于键是按下还是按下的信息,它也不知道哪个键被按下,只有在调用它时哪些键被按下。 为了达到你的目标,我会做这样的事情:

 var keyPress = function (e) { var key = e.key.toLowerCase(), isKeyDown = e.type === "keydown", output = key + (isKeyDown ? "-down" : "-up") + ": "; switch (key) { case "shift": if (isKeyDown) { output += "pew pew"; } else { output += "doing nothing" } break; case "arrowleft": output += "updating walking_left"; document.getElementById("walking_left").innerText = isKeyDown; break; default: output += "doing nothing"; } console.log(output); }; document.addEventListener('keydown', keyPress); document.addEventListener('keyup', keyPress);
 Walking left:<div id="walking_left">false</div>

如果您按下两个键,您将触发两个事件,无论您是否同时按下它们。 keyup事件也是如此。 所以总共调用了四次handleKeypress函数。

顺序很可能是:

key        | event   | keyMap.arrowleft | keyMap.shift | effect
-----------+---------+------------------+--------------+----------
shift      | keydown |     false        |     true     | shoot
arrowleft  | keydown |     true         |     true     | moving.left=true
arrowleft  | keyup   |     false        |     true     | shoot
shift      | keyup   |     false        |     false    | nothing

所以在那种情况下你射击两次。 当然,情况并非总是如此,因为顺序可能不同。

解决方案

将键作为参数传递给handleKeyPress函数,以确保您只执行与该键对应的操作。

var Input = function () {
  var keyMap = {};

  this.handleKeyPress = function (key) {
    switch (key) {
    case 'arrowleft':
      game.player.moving.left = keyMap[key]; // also sets back to false
      break;
    case 'shift':
      if (keyMap.shift) game.player.shootSpecial();
      break;
    }
  };

  this.keyPress = function (e) {
    var key = e.key.toLowerCase();
    if (key === ' ') {
      key = 'space';
    }
    keyMap[key] = e.type === 'keydown';
    this.handleKeyPress(key); // pass key
  };
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM