我正在尝试开发一个JavaScript游戏引擎,遇到了这个问题:
- 当我按下SPACE键时,角色会跳跃。
- 当我按下→键时,角色向右移动。
问题是,当我按下右箭头键并按下空格键时,角色跳跃后停止移动。
我使用keydown
函数来获取键盘按键事件。如何检查是否同时按下多个键?
我正在尝试开发一个JavaScript游戏引擎,遇到了这个问题:
问题是,当我按下右箭头键并按下空格键时,角色跳跃后停止移动。
我使用keydown
函数来获取键盘按键事件。如何检查是否同时按下多个键?
注意:keyCode现在已经弃用。
如果您理解这个概念,多个按键的检测就很容易了。
我的做法是这样的:
var map = {}; // You could also use an array
onkeydown = onkeyup = function(e){
e = e || event; // to deal with IE
map[e.keyCode] = e.type == 'keydown';
/* insert conditional here */
}
keydown
事件,将 map[e.keyCode]
设置为 e.type == keydown
的值,该值评估为 true 或 false。现在,map[65]
和 map[66]
都设置为 true
。当您松开 A
时,会触发 keyup
事件,导致相同的逻辑确定 map[65]
(A)的相反结果,即现在为 false,但由于 map[66]
(B)仍然处于“按下”状态(它没有触发 keyup 事件),因此它保持为 true。map
数组如下所示:// keydown A
// keydown B
[
65:true,
66:true
]
// keyup A
// keydown B
[
65:false,
66:true
]
现在您可以做两件事情:
A) 创建一个键盘记录器(example)作为参考,以便日后快速查找一个或多个键码。假设您已经定义了一个HTML元素,并使用变量element
指向它。
element.innerHTML = '';
var i, l = map.length;
for(i = 0; i < l; i ++){
if(map[i]){
element.innerHTML += '<hr>' + i;
}
}
id
属性轻松获取元素。<div id="element"></div>
element
进行引用。alert(element); // [Object HTMLDivElement]
您甚至不需要使用document.getElementById()
或$()
来获取它。但为了兼容性,更广泛地推荐使用jQuery的$()
。
只需确保
myString[5]
和 5[myString]
是相同的吗?即使使用 -Wall -pedantic
编译选项,它也不会给你编译警告。这是因为 pointer[offset]
表示法获取指针,添加偏移量,然后解引用结果,使得 myString[5]
等同于 *(myString + 5)
。 - Braden Bestdocument.onkeydown = keydown;
function keydown (evt) {
if (!evt) evt = event;
if (evt.ctrlKey && evt.altKey && evt.keyCode === 115) {
alert("CTRL+ALT+F4");
} else if (evt.shiftKey && evt.keyCode === 9) {
alert("Shift+TAB");
}
}
使用keydown事件来跟踪按下的键,并且使用keyup事件来跟踪键何时被释放。
可以参考这个例子: http://jsfiddle.net/vor0nwe/mkHsU/
(更新:为防止jsfiddle.net失效,我在此处重现代码:)
<ul id="log">
<li>List of keys:</li>
</ul>
...以及使用jQuery的Javascript代码:
var log = $('#log')[0],
pressedKeys = [];
$(document.body).keydown(function (evt) {
var li = pressedKeys[evt.keyCode];
if (!li) {
li = log.appendChild(document.createElement('li'));
pressedKeys[evt.keyCode] = li;
}
$(li).text('Down: ' + evt.keyCode);
$(li).removeClass('key-up');
});
$(document.body).keyup(function (evt) {
var li = pressedKeys[evt.keyCode];
if (!li) {
li = log.appendChild(document.createElement('li'));
}
$(li).text('Up: ' + evt.keyCode);
$(li).addClass('key-up');
});
在这个例子中,我使用一个数组来跟踪哪些键被按下。在实际应用中,您可能希望在释放其关联键后删除
每个元素。
请注意,虽然我在此示例中使用了jQuery使事情变得容易,但在使用“原始的”JavaScript时,该概念同样适用。
onblur
事件处理程序,从数组中删除所有已按下的键。一旦失去焦点,需要再次按下所有键才能生效。不幸的是,JS没有相当于GetKeyboardState
的功能。 - Martijn需要完整示例代码的人。添加了右+左
var keyPressed = {};
document.addEventListener('keydown', function(e) {
keyPressed[e.key + e.location] = true;
if(keyPressed.Shift1 == true && keyPressed.Control1 == true){
// Left shift+CONTROL pressed!
keyPressed = {}; // reset key map
}
if(keyPressed.Shift2 == true && keyPressed.Control2 == true){
// Right shift+CONTROL pressed!
keyPressed = {};
}
}, false);
document.addEventListener('keyup', function(e) {
keyPressed[e.key + e.location] = false;
keyPressed = {};
}, false);
这不是一种通用的方法,但在某些情况下它很有用。它适用于像 CTRL + something 或者 Shift + something 或者 CTRL + Shift + something 等组合键。
例如:当您想使用 CTRL + P 打印页面时,首先按下的键是 CTRL,然后是 P。同样的,对于 CTRL + S、CTRL + U 和其他组合键也是如此。
document.addEventListener('keydown',function(e){
//SHIFT + something
if(e.shiftKey){
switch(e.code){
case 'KeyS':
console.log('Shift + S');
break;
}
}
//CTRL + SHIFT + something
if(e.ctrlKey && e.shiftKey){
switch(e.code){
case 'KeyS':
console.log('CTRL + Shift + S');
break;
}
}
});
// create some object to save all pressed keys
var keys = {
shift: false,
ctrl: false
};
$(document.body).keydown(function(event) {
// save status of the button 'pressed' == 'true'
if (event.keyCode == 16) {
keys["shift"] = true;
} else if (event.keyCode == 17) {
keys["ctrl"] = true;
}
if (keys["shift"] && keys["ctrl"]) {
$("#convert").trigger("click"); // or do anything else
}
});
$(document.body).keyup(function(event) {
// reset status of the button 'released' == 'false'
if (event.keyCode == 16) {
keys["shift"] = false;
} else if (event.keyCode == 17) {
keys["ctrl"] = false;
}
});
var keys = {}
function handleKeyPress(evt) {
let { keyCode, type } = evt || Event; // to deal with IE
let isKeyDown = (type == 'keydown');
keys[keyCode] = isKeyDown;
// test: enter key is pressed down & shift isn't currently being pressed down
if(isKeyDown && keys[13] && !keys[16]){
console.log('user pressed enter without shift')
}
};
window.addEventListener("keyup", handleKeyPress);
window.addEventListener("keydown", handleKeyPress);
我喜欢使用这个代码片段,它非常有用于编写游戏输入脚本。
var keyMap = [];
window.addEventListener('keydown', (e)=>{
if(!keyMap.includes(e.keyCode)){
keyMap.push(e.keyCode);
}
})
window.addEventListener('keyup', (e)=>{
if(keyMap.includes(e.keyCode)){
keyMap.splice(keyMap.indexOf(e.keyCode), 1);
}
})
function key(x){
return (keyMap.includes(x));
}
function checkGameKeys(){
if(key(32)){
// Space Key
}
if(key(37)){
// Left Arrow Key
}
if(key(39)){
// Right Arrow Key
}
if(key(38)){
// Up Arrow Key
}
if(key(40)){
// Down Arrow Key
}
if(key(65)){
// A Key
}
if(key(68)){
// D Key
}
if(key(87)){
// W Key
}
if(key(83)){
// S Key
}
}
Array.includes
在旧版浏览器或现代 IE 中支持不佳:https://caniuse.com/#feat=array-includes - XCSkeyMap
中可以检测多个键。此外,在这种情况下,您应该解释何时需要调用checkGameKeys
以及其目的是什么。 - NBTXcheckGameKeys()
才能使其正常工作。 - Simon O'Dohertydocument.keydown = function (key) {
checkKey("x");
checkKey("y");
};
$(document).ready(function () {
// using ascii 17 for ctrl, 18 for alt and 83 for "S"
// ctr+alt+S
var map = { 17: false, 18: false, 83: false };
$(document).keyup(function (e) {
if (e.keyCode in map) {
map[e.keyCode] = true;
if (map[17] && map[18] && map[83]) {
// Write your own code here, what you want to do
map[17] = false;
map[18] = false;
map[83] = false;
}
}
else {
// if u press any other key apart from that "map" will reset.
map[17] = false;
map[18] = false;
map[83] = false;
}
});
});