在我的游戏中,我使用事件监听器 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>
正如您通过 fiddle 所看到的,一个事件被调用两次。
最佳答案
您的问题是您使用相同的代码处理 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>
关于javascript - 用另一个键按下时发生两次按键事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39923228/