[英]Key Event happening twice when pressed with another key
在我的游戲中,我使用事件偵聽器keyup
和keydown
來跟蹤按下了哪些鍵( 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
被觸發,它就會被設置為false
: keyMap[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
報告left和shift在keydown
上為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.