我在Javascript中使用RPG并且正在为主播放器设置控件,但是我遇到了一些关于keyEvent处理的问题。此代码控制玩家移动和动画。我认为,出现问题的地方是,如果游戏在已经存在另一个keydown的同时注册了keydown,然后第一个键上升,则sprite暂停(isMoving属性基本上停止移动和动画,当它为false时)。 / p>
// For example:
// I hold W. Sprite begins moving up.
// While holding W, I begin to hold D. Sprite begins moving right.
// I release W. Sprite should keep going right, but pauses momentarily when the
// keyup is registered
var move = function(e) {
xavier.isMoving = true;
switch(e.keyCode)
{
case 87: xavier.direction = 'up'; break; //W
case 65: xavier.direction = 'left'; break; //A
case 68: xavier.direction = 'right'; break; //D
case 83: xavier.direction = 'down'; break; //S
};
};
var wait = function(e) {
xavier.isMoving = false;
};
window.addEventListener("keydown", move, false);
window.addEventListener("keyup", wait, false);
有没有更好的方法来设置控件,以便我的游戏可以同时处理多个键?
此外,当按下mac命令键时,精灵会移动。不知道为什么。预先感谢您的帮助。这是我在StackOverflow上的第一个问题。希望没关系。
答案 0 :(得分:1)
您需要将关键事件与动画或主游戏循环取消关联。关键时刻,keyup事件是IO事件,不应该处理游戏逻辑,它们可以无论如何进入,你可能有很多帧之间,每个帧上应用逻辑只是浪费处理,更糟糕的是如果你有更多的逻辑参与玩家可能会错过逻辑事件,因为关键事件已经进行而没有主循环处理新位置。对于鼠标和触摸事件也是如此,您应该只记录事件并在游戏中处理它们。
// define keys and an array to keep key states
// global key log;
var keyState = [];
const KEY_UP = 38;
const KEY_DOWN = 40;
const KEY_LEFT = 37;
const KEY_RIGHT = 39;
// create a logging function
const keyEventLogger = function (e) { keyState[e.keyCode] = e.type == 'keydown';}
window.addEventListener("keydown", keyEventLogger);
window.addEventListener("keyup", keyEventLogger);
// define something to move
var player = {y : 100, x: 100};
const MOVE_SPEED = 2;
// in the main loop;
function update(timer) {
if (keyState[KEY_UP]) {
player.y -= MOVE_SPEED;
}
if (keyState[KEY_DOWN]) {
player.y += MOVE_SPEED;
}
if (keyState[KEY_LEFT]) {
player.x -= MOVE_SPEED;
}
if (keyState[KEY_RIGHT]) {
player.x += MOVE_SPEED;
}
requestAnimationFrame(update);
}
requestAnimationFrame(update);
答案 1 :(得分:0)
当然有。
您需要拥有一个数组和2个事件侦听器,一个用于keydown
,另一个用于keyup
。
每当有人按下按钮时,将id与按钮的keyCode相同的元素设置为true。如果你的数组被称为keys
,那么这看起来像这样:
keys[e.keyCode] = true;
然后,每当用户重新按钮时,将与该按钮的keyCode具有相同id的元素设置为false:
keys[e.keyCode] = false;
稍后,您可以检查,如果具有与按钮相同的ID的元素,则在您按下它之后发生特定事件是真的。
答案 2 :(得分:0)
var move = function(e) {
xavier.isMoving = true;
switch(e.keyCode)
{
case 87: xavier.direction.up = true; break; //W
case 65: xavier.direction.left = true; break; //A
case 68: xavier.direction.right = true; break; //D
case 83: xavier.direction.down = true; break; //S
};
};
var wait = function(e) {
switch(e.keyCode)
{
case 87: xavier.direction.up = true; break; //W
case 65: xavier.direction.left = true; break; //A
case 68: xavier.direction.right = true; break; //D
case 83: xavier.direction.down = true; break; //S
};
xavier.isMoving = xavier.direction.up ||
xavier.direction.left || xavier.direction.right ||
xavier.direction.down;
};
window.addEventListener("keydown", move, false);
window.addEventListener("keyup", wait, false);
答案 3 :(得分:0)
这是一个解决方案,可以跟踪向下(方向)的键,并在释放第二个键时返回另一个向下(方向)的键。这两个函数非常相似,它们组合成一个:
var xavier = {};
xavier.isMoving = false;
xavier.stack = [];
xavier.direction = '';
xavier.directions = {
87: 'up', //W
65: 'left', //A
68: 'right', //D
83: 'down', //S
};
var move = function(e) {
// get direction from mapping: key -> direction
var direction = xavier.directions[e.keyCode];
if (!direction) return; // not a move-key
var i = xavier.stack.indexOf(direction);
if (e.type === 'keydown' && i === -1) {
// If this key was not yet down, but is pressed,
// then add the direction to the list
xavier.stack.push(direction);
} else if (e.type === 'keyup' && i !== -1) {
// If this key was down, but is released,
// then remove the direction from the list
xavier.stack.splice(i, 1);
}
xavier.direction = xavier.stack.length ? xavier.stack[xavier.stack.length-1]
: '';
xavier.isMoving = xavier.direction !== '';
// Test for this snippet only:
document.body.textContent = xavier.direction;
};
window.addEventListener("keydown", move, false);
window.addEventListener("keyup", move, false);

Click here (to focus) and press/release ASQW keys

请注意,理论上这可以支持任意数量的键,但实际上键盘通常仅限于可以关闭的数字。超过此限制后,不会生成任何关键事件。