如何处理主游戏循环中的按键事件?

How to handle keyup events in main game loop?

我正在 JavaScript 中编写一个简单的游戏,它已经可以像这样处理基本的键盘输入:

var input = {};
document.onkeydown = function(e) {
    input[e.keyCode] = true;
}
document.onkeyup = function(e) {
    input[e.keyCode] = false;
}

while (!done) {
    handleInput(input);
    update();
    render();
}

现在我需要游戏来处理组合键(例如 CTRL+X)。我希望它仅在 keyup.

上接受这样的组合

编辑: 修改键不需要与 "main" 键同时全部向上。 /编辑

我想到的两个可能的解决方案是:

  • 公开包含 keyup 事件列表的数组(带有 "main" 键加修饰符的对象)。 handleInput 函数将负责在每次轮询时清空队列
  • 跟踪 handleInput 中可能的组合键(观察按住的修改键)并在 "main" 键上升时触发组合行为(我实际上不太喜欢这个)

你能建议我一个优雅的方式来扩展当前的功能吗?

您所要做的就是创建 upInput 变量,您将在其中存储您的 keyup 键。然后,要检查是否按下了组合键,您必须检查是否只有 CTRL + C (或 17、67)变量组合,如果它们都是 true。然后轻松打印您的消息并重置 upInput 变量。

var input = upInput = {};

document.onkeydown = function(e) {
    input[e.keyCode] = true;
    if (JSON.stringify(Object.keys(upInput)) != '["17","67"]')
        upInput = {};
}
document.onkeyup = function(e) {
    var k = e.keyCode;
    input[k] = false;
    if ([17, 67].indexOf(k) > -1)
        upInput[k] = true;
    if (JSON.stringify(Object.keys(upInput)) == '["17","67"]'
            && upInput[17] && upInput[67]) // CTRL + C
        alert('YES!'),
        upInput = {};
}

Demo

希望对您有所帮助!

我会采用其中一种方式:

  • 正在检查 handleInput 部分中的组合(您的那种 第二个方法)
  • 保留最近 X 键盘事件的列表(其中 X 是最大值 组合序列的长度)并检查此列表是否匹配 任何预定义的组合触发器

试试这个 ;) 当您按下 CTRL + X 并释放其中一个(或两个)时,它会出现一条消息

var map = {17: false, 88: false};
var fire_event = false;

window.addEventListener('keydown', function(e) {
    if (e.keyCode in map) {
        map[e.keyCode] = true;
        if (map[17] && map[88]) {
            fire_event = true;
        }
    }
}, false);

window.addEventListener('keyup', function(e) {
    if (e.keyCode in map) {
        map[e.keyCode] = false;
    }
    if (fire_event) {
        fire_event = false;
        alert('YOU PRESSED CTRL + X');
    }
}, false);

尝试一下是否有效:

var KEY_QUEUE = [];
var KEYs = [17, 88];

document.onkeydown = function (e) {
    if (KEY_QUEUE.indexOf(e.keyCode) === -1) {
        KEY_QUEUE.push(e.keyCode);
    }
};

document.onkeyup = function (e) {
    var index = KEY_QUEUE.indexOf(e.keyCode);
    if ( isSubArray(KEYs, KEY_QUEUE) 
         && KEYs.indexOf(e.keyCode) > -1 ) {
        console.log("You press CTRL + X");
    }
    KEY_QUEUE.splice(index, 1);
};

function isSubArray(ary, targetAry) {
  return new RegExp(ary.toString()).test(targetAry.toString());
}

我已经检查了一些情况,例如 Ctrl xx CtrlCtrl x aCtrl a x,它按我的预期工作。但是不知道是不是跟你的想法一样