Подтвердить что ты не робот

Удалить задержку нажатия клавиши в 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);
    }

У кого-нибудь есть идея?

4b9b3361

Ответ 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?

Я обновлю этот ответ после того, как изменю и испытаю.