Удалить задержку нажатия клавиши в javascript
У меня есть следующая проблема:
Я пытаюсь написать javascript-игру, и персонаж контролируется клавишами со стрелками.
Проблема в том, что когда вы удерживаете нажатой клавишу, происходит короткая задержка между запуском первого нажатия и повторным нажатием клавиши.
Кроме того, когда один нажимает клавишу "стрелка вправо" и удерживает ее нажатой, а затем нажимает клавишу "стрелка вверх", символ не перемещается в верхний правый угол, а останавливает движение в правильном направлении и начинает движение вверх.
Это код, который я использую:
<body onLoad="Load()" onKeyDown="Pressed(event)">
function Pressed(e) {
cxc = e.keyCode;
if(cxc == 37)
Move(-1,0);
if(cxc == 38)
Move(0,-1);
if(cxc == 39)
Move(1,0);
if(cxc == 40)
Move(0,1);
}
У кого-нибудь есть идея?
Ответы
Ответ 1
Если вы хотите, чтобы клавиша повторялась управляемым образом, вам придется реализовать ее самостоятельно, поскольку события нажатия клавиш запускаются в зависимости от идеи ОС о том, как ключи должны повторяться. Это означает, что могут быть переменные начальные и последующие задержки, и одновременное удерживание двух клавиш вызовет только один из них.
Вам нужно будет сохранить запись о том, нажата ли каждая клавиша, и игнорировать события keydown
, когда ключ уже отключен. Это связано с тем, что многие браузеры будут запускать keydown
, а также событие keypress
, когда происходит автоповтор, и если вы воспроизводите ключ, повторите сам, вам нужно будет его подавить.
Например:
// Keyboard input with customisable repeat (set to 0 for no key repeat)
//
function KeyboardController(keys, repeat) {
// Lookup of key codes to timer ID, or null for no repeat
//
var timers= {};
// When key is pressed and we don't already think it pressed, call the
// key action callback and set a timer to generate another one after a delay
//
document.onkeydown= function(event) {
var key= (event || window.event).keyCode;
if (!(key in keys))
return true;
if (!(key in timers)) {
timers[key]= null;
keys[key]();
if (repeat!==0)
timers[key]= setInterval(keys[key], repeat);
}
return false;
};
// Cancel timeout and mark key as released on keyup
//
document.onkeyup= function(event) {
var key= (event || window.event).keyCode;
if (key in timers) {
if (timers[key]!==null)
clearInterval(timers[key]);
delete timers[key];
}
};
// When window is unfocused we may not get key events. To prevent this
// causing a key to 'get stuck down', cancel all held keys
//
window.onblur= function() {
for (key in timers)
if (timers[key]!==null)
clearInterval(timers[key]);
timers= {};
};
};
то
// Arrow key movement. Repeat key five times a second
//
KeyboardController({
37: function() { Move(-1, 0); },
38: function() { Move(0, -1); },
39: function() { Move(1, 0); },
40: function() { Move(0, 1); }
}, 200);
Хотя в большинстве игр на основе действий есть цикл основного кадра с фиксированным временем, который вы можете связать с обработкой клавиш вверх/вниз.
Ответ 2
Я решил это так:
var pressedl = 0;
var pressedu = 0;
var pressedr = 0;
var pressedd = 0;
function Down(e) {
cxc = e.keyCode;
if(cxc == 37)
pressedl = 1;
if(cxc == 38)
pressedu = 1;
if(cxc == 39)
pressedr = 1;
if(cxc == 40)
pressedd = 1;
//alert(cxc);
}
function Up(e) {
cxc = e.keyCode;
if(cxc == 37)
pressedl = 0;
if(cxc == 38)
pressedu = 0;
if(cxc == 39)
pressedr = 0;
if(cxc == 40)
pressedd = 0;
//alert(cxc);
}
<body onLoad="Load()" onKeyDown="Down(event)" onKeyUp="Up(event)">
Ответ 3
Вы можете запустить движение onkeydown и только завершить его onkeyup?
Ответ 4
Как это событие должно перемещать whatever
из одной позиции в одну позицию, почему бы вам не использовать событие onkeypress
, поэтому таким образом, если пользовательский ключ нажал клавишу up
, whatever
будет продолжайте движение вверх, так как Pressed(e)
будет вызываться много раз, пока пользователь не отпустит ключ.
<body onLoad="Load()" onkeypress="Pressed(event)">
Ответ 5
Это решение Lucas в более абстрактной версии:
http://jsfiddle.net/V2JeN/4/
Кажется, вы можете только нажать 3 клавиши за раз, чтобы удивить.
Ответ 6
Я новичок в этом, но почему бы не комбинировать KeyDown с KeyUp? Я сейчас работаю над подобным проектом и после проверки quirksmode Я собираюсь рассказать о том, как объединить два такие события, что все время между "Вниз" и "вверх" реализует желаемый аффект.
Ответ 7
Это почти то же самое, что отличный ответ от @bobince
Я немного изменил его, чтобы разрешить отдельные значения для интервала
// Keyboard input with customisable repeat (set to 0 for no key repeat)
// usage
/**
KeyboardController({
32: {interval:0, callback: startGame },
37: {interval:10, callback: function() { padSpeed -= 5; } },
39: {interval:10, callback: function() { padSpeed += 5; } }
});
*/
function KeyboardController(keyset) {
// Lookup of key codes to timer ID, or null for no repeat
//
var timers= {};
// When key is pressed and we don't already think it pressed, call the
// key action callback and set a timer to generate another one after a delay
//
document.onkeydown= function(event) {
var key= (event || window.event).keyCode;
if (!(key in keyset))
return true;
if (!(key in timers)) {
timers[key]= null;
keyset[key].callback();
if (keyset[key].interval !== 0)
timers[key]= setInterval(keyset[key].callback, keyset[key].interval);
}
return false;
};
// Cancel timeout and mark key as released on keyup
//
document.onkeyup= function(event) {
var key= (event || window.event).keyCode;
if (key in timers) {
if (timers[key]!==null)
clearInterval(timers[key]);
delete timers[key];
}
};
// When window is unfocused we may not get key events. To prevent this
// causing a key to 'get stuck down', cancel all held keys
//
window.onblur= function() {
for (key in timers)
if (timers[key]!==null)
clearInterval(timers[key]);
timers= {};
};
};
У меня также есть план использования setTimeout вместо setInterval по причинам, указанным в этом вопросе: setTimeout или setInterval?
Я обновлю этот ответ после того, как изменю и испытаю.