这是许多依赖键盘中断来控制游戏角色的编码语言的标准问题,并不是特定于JavaScript . 解决这个问题的方法是将键与角色的移动分开捕获,而不是依赖键盘事件来重绘/更新游戏 . 相反,使用一个连续的游戏循环,可以并且经常不做任何事情(很多次一秒) - 直到游戏中的某些内容发生变化 . 这似乎是一件奇怪的事情,但它是许多游戏的设计和构建方式 - 即使在JavaScript中也是如此;)
/// store key codes and currently pressed ones
var keys = {};
keys.LEFT = 37;
keys.RIGHT = 39;
/// store reference to character's position and element
var character = {
x: 100,
y: 100,
element: document.getElementById("character")
};
/// key detection (better to use addEventListener, but this will do)
document.body.onkeyup =
document.body.onkeydown = function(e){
var kc = e.keyCode || e.which;
keys[kc] = e.type == 'keydown';
};
/// character movement update
var moveCharacter = function(dx, dy){
character.x += dx||0;
character.y += dy||0;
character.element.style.left = character.x + 'px';
character.element.style.top = character.y + 'px';
};
/// character control
var detectCharacterMovement = function(){
if ( keys[keys.LEFT] ) {
moveCharacter(-1);
}
if ( keys[keys.RIGHT] ) {
moveCharacter(1);
}
};
/// game loop
setInterval(function(){
detectCharacterMovement();
}, 1000/24);
一个实例(也有上下移动):
/// store key codes and currently pressed ones
var keys = {};
keys.UP = 38;
keys.LEFT = 37;
keys.RIGHT = 39;
keys.DOWN = 40;
/// store reference to character's position and element
var character = {
x: 100,
y: 100,
speedMultiplier: 2,
element: document.getElementById("character")
};
/// key detection (better to use addEventListener, but this will do)
document.body.onkeyup =
document.body.onkeydown = function(e){
/// prevent default browser handling of keypresses
if (e.preventDefault) {
e.preventDefault();
}
else {
e.returnValue = false;
}
var kc = e.keyCode || e.which;
keys[kc] = e.type == 'keydown';
};
/// character movement update
var moveCharacter = function(dx, dy){
character.x += (dx||0) * character.speedMultiplier;
character.y += (dy||0) * character.speedMultiplier;
character.element.style.left = character.x + 'px';
character.element.style.top = character.y + 'px';
};
/// character control
var detectCharacterMovement = function(){
if ( keys[keys.LEFT] ) {
moveCharacter(-1, 0);
}
if ( keys[keys.RIGHT] ) {
moveCharacter(1, 0);
}
if ( keys[keys.UP] ) {
moveCharacter(0, -1);
}
if ( keys[keys.DOWN] ) {
moveCharacter(0, 1);
}
};
/// update current position on screen
moveCharacter();
/// game loop
setInterval(function(){
detectCharacterMovement();
}, 1000/24);
#character {
position: absolute;
width: 42px;
height: 42px;
background: red;
border-radius: 50%;
}
以上只是基础知识,您可以进行一些优化 . 上面也不是控制游戏角色的全部内容,遗憾的是,浏览器中的键盘事件是不可预测的(与JavaScript没有任何关系),如果有任何问题,你会发现你开始尝试制作更复杂的控制系统,即某些键不能同时按下而不会出现问题(尤其是控制字符,如CMD或CTRL) .
有一天,如果JavaScript有一个Keyboard对象,那就像上面的 keys 对象一样 . 这意味着您可以随时测试当前按下的任何键的状态,而无需依赖事件模型 . 它可能发生在一些尚未知的未来点,但我们必须拭目以待 .
如果确实发生了,我想建议一个功能:
Keyboard.isPressed(Keyboard.ANY)
这将有助于无数的游戏介绍/菜单屏幕(为什么我必须在看到菜单之前按任意键?我们是否梦想街机?) . 更不用说上述内容将有助于所有那些仍在等待他们认为缺少密钥的人的存在 .