简体   繁体   English

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

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

In my game, I use the event listeners keyup and keydown to track which keys are pressed ( this.input is a reference to the Input function below):在我的游戏中,我使用事件侦听器keyupkeydown来跟踪按下了哪些键( this.input是对下面Input函数的引用):

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

Everything works as expected, until I press 2 keys at once.一切都按预期工作,直到我一次按下 2 个键。 The left key moves the player left, the shift key fires a weapon.左键将玩家向左移动,Shift 键发射武器。 Separately, they work fine.另外,它们工作正常。 If both are pressed at once, however, and held, the player shoots twice.但是,如果同时按下并按住两者,则玩家会射击两次。

Here is the code I am using to handle the inputs (removed other key events for brevity)这是我用来处理输入的代码(为简洁起见,删除了其他关键事件)

shootSpecial should only be called once since keyMap.shift is only true on keydown . shootSpecial只应调用一次,因为keyMap.shift仅在keydown上为true Once keyup is triggered, it is set to false : keyMap[key] = e.type === 'keydown';一旦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();
  };
};

The console.log reports that left and shift are true on keydown and then both false on keyup so I'm not too sure why it would be triggering the shootSpecial event twice. 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>

As you can see by the fiddle, one event gets called twice.正如您在小提琴中看到的那样,一个事件被调用两次。

Your problem is that you're handling keydown and keyup with the same code, with the result that releasing key1 while pressing key2 has the same effect as pressing key2.您的问题是您使用相同的代码处理 keydown 和 keyup,结果是在按下 key2 的同时释放 key1 与按下 key2 具有相同的效果。

The fix is pretty easy: don't call your handleKeyPress function at all on keyup events.修复非常简单:根本不要在 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>


Adding a suggestion in response to OP's comment.添加建议以回应 OP 的评论。 Your problem is that your handleKeyPress() has no information about whether the key was pressed down or up, and it also doesn't know which key was even pressed, only which keys are down at the time it is called.你的问题是你的 handleKeyPress() 没有关于键是按下还是按下的信息,它也不知道哪个键被按下,只有在调用它时哪些键被按下。 To get what you're aiming for, I would do something like this:为了达到你的目标,我会做这样的事情:

 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>

If you press two keys, you'll fire two events, whether you press them at the same time or not.如果您按下两个键,您将触发两个事件,无论您是否同时按下它们。 The same for the keyup event. keyup事件也是如此。 So in total the handleKeypress function is called four times.所以总共调用了四次handleKeypress函数。

The order might well happen to be:顺序很可能是:

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

So in that scenario you shoot twice.所以在那种情况下你射击两次。 Of course, this will not always be the case, as the order might be different.当然,情况并非总是如此,因为顺序可能不同。

Solution解决方案

Pass the key as argument to the handleKeyPress function to make sure you only execute an action that corresponds to that key.将键作为参数传递给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