删除Javascript中的按键延迟

IT技术 javascript events dom-events
2021-02-22 13:04:20

我有以下问题:我正在尝试编写一个 Javascript 游戏,并且角色由箭头键控制。
问题是,当一个人按住键时,在触发第一个keypress和重复之间有一个短暂的延迟keypress
此外,当按下“向右箭头键”并保持按下时,然后按下“向上箭头键”时,字符不会移动到右上角,而是停止向右移动并开始向上移动。
这是我正在使用的代码:

<body onLoad="Load()" onKeyDown="Pressed(event)">
功能按下(e){ 
        cxc = e.keyCode;
        如果(cxc == 37)
            移动(-1,0);
        如果(cxc == 38)
            移动(0,-1);
        如果(cxc == 39)
            移动(1,0);
        如果(cxc == 40)
            移动(0,1);
    }

有人有想法吗?

6个回答

如果您希望以可控方式重复按键,则必须自己实现,因为按键事件的触发取决于操作系统对按键应如何重复的想法。这意味着可能会有可变的初始和后续延迟,同时按住两个键只会导致其中一个重复。

您必须记录每个键当前是否被按下,并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's 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);

尽管如此,大多数基于动作的游戏都有一个固定时间的主帧循环,您可以将键向上/向下处理绑定到其中。

我是这样解决的:

varpressedl = 0;
varpressu = 0;
varpressedr = 0;
varpressed = 0;

功能下降(e){ 
        cxc = e.keyCode;
        如果(cxc == 37)
            按下 l = 1;
        如果(cxc == 38)
            压力 = 1;
        如果(cxc == 39)
            按下 = 1;
        如果(cxc == 40)
            按下 = 1;
        //警报(cxc);
    }
    函数向上(e){
        cxc = e.keyCode;
        如果(cxc == 37)
            按下 l = 0;
        如果(cxc == 38)
            压力 = 0;
        如果(cxc == 39)
            按下 = 0;
        如果(cxc == 40)
            按下 = 0;
        //警报(cxc);
    }

<body onLoad="Load()" onKeyDown="Down(event)" onKeyUp="Up(event)">

你可以开始 onkeydown 运动,然后只结束它 onkeyup?

这与@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's 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?

一旦我修改和测试,我会更新这个答案。

由于这个事件是whatever从一个位置移动到一个位置,为什么不使用onkeypress事件,这样如果用户按键按下该up键,whatever它将继续向上移动,因为Pressed(e)将被多次调用直到用户释放钥匙。

<body onLoad="Load()" onkeypress="Pressed(event)">
同样的问题。1秒的延迟仍然存在,当按下两个键时,它只识别其中的1个。
2021-04-23 13:04:20