簡體   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