[英]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.