Вот собственно есть такой код:
var control = null;
control = new controlDispatcher();
document.body.onkeydown = control.keyDown;
document.body.onkeyup = control.keyUp;
function controlDispatcher() {
this.UP = 38;
this.DOWN = 40;
this.LEFT = 37;
this.RIGHT = 39;
this.movePressedButtons = {};
this.movePressedButtonsArr = [];
this.keyDown = function(e) {
if (app.player)
control.changePlayerDirectionMove(e.keyCode);
}
this.changePlayerDirectionMove = function(key) {
var moveKeyCode = null;
switch (key) {
case this.UP:
app.player.direction = {x : 0, y : -1};
moveKeyCode = key;
break;
case this.DOWN:
app.player.direction = {x : 0, y : 1};
moveKeyCode = key;
break;
case this.LEFT:
app.player.direction = {x : -1, y : 0};
moveKeyCode = key;
break;
case this.RIGHT:
app.player.direction = {x : 1, y : 0};
moveKeyCode = key;
break;
}
if (moveKeyCode) {
//Заносим ключ клавиши в объект, как атрибут со значение true (для сохранения только одного нажатия клавиши (т.е. чтобы избежать дубликатов))
this.movePressedButtons[moveKeyCode] = true;
//Заносим ключи объекта, как значения в массив
this.movePressedButtonsArr = Object.keys(this.movePressedButtons);
app.player.move = true;
}
}
this.keyUp = function(e) {
//Если есть атрибуты в объекте
if (control.movePressedButtons.hasOwnProperty(e.keyCode))
{
//Удаляем атрибут, который соответствует нажатой клавише
delete control.movePressedButtons[e.keyCode];
if (Object.keys(control.movePressedButtons).length)
{
//Заносим ключи объекта, как значения в массив
control.movePressedButtonsArr = Object.keys(control.movePressedButtons);
}
else
{
control.movePressedButtonsArr = [];
}
}
if (app.player)
{
//Если еще есть нажатые клавиши
if (control.movePressedButtonsArr.length)
{
//Получаем последнюю нажатую клавишу
var keyCode = control.movePressedButtonsArr[control.movePressedButtonsArr.length-1];
control.changePlayerDirectionMove(parseInt(keyCode));
}
else
{
app.player.move = false;
}
}
}
}
Суть его - отлавливать нажатия 4 клавиш. Работает он отлично, но меня от него тошнит.
Собственно проблема в том, что если такой случай, как одновременное нажатие 2-3-4 клавиш, то при отпускании одной из них я хочу сделать так, чтобы (это игра) обрабатывалась клавиша, которая была нажата последней. Поясню:
Я зажимаю ВВЕРХ и ВЛЕВО. Игрок движется влево. Я отпускаю ВВЕРХ - игрок движется влево. Я опять нажимаю ВВЕРХ (ВЛЕВО еще нажато), и игрок опять движется вверх(!!! прямо как в Crysis, замечательная игра прям будет).
Для этого я создал объект controlDispatcher::movePressedButtons. В него при каждом нажатии сохраняется ключ нажатой клавиши как атрибут (дикость номер раз). Это надо для того, чтобы иметь "массив" нажатых сейчас клавиш. Почему я не хочу делать это простым массивом? Надо проверять уникальность элемента в массиве - затраты ресурсов - недопустимо в браузерке (при зажатой клавише событие document.body.onkeydown будет вызывать обработчик бесчисленное кол-во раз).
Далее при отпускании одной из клавиш я удаляю соответствующий атрибут из объекта, и (дикость 2) заношу атрибуты объекта в массив как значения. Это мне нужно для того, чтобы определить последнюю из нажатых клавиш (объекты не поддерживают ни каких порядков в атрибутах, поэтому тут на честном слове работает).
Из этой простыни (если ее кому-то будет не лень читать) вытекает один простой вопрос - можно ли это реализовать элегантнее, правильнее (но при том не жертвуя скорость приложения)?
В приложении есть сама игра. Она очень увлекательная - там серый квадрат на черном квадрате. Серый квадрат можно шевелить кнопками клавиатуры. Настоятельно рекомендую.