间隔引起的不需要的延迟

时间:2018-03-01 01:43:39

标签: javascript jquery intervals

为超级简单的jQuery游戏处理角色动画。

我的问题是,如果您快速切换移动键,则会有大约半秒的延迟。例如,如果您按住W然后非常快速地按D,则会出现意外延迟。我希望它是即时的。有什么方法可以解决这个问题吗?

这是我的代码:

$(document).ready(function () {
    var character = $('#character');
    var movement;
    var move_keys = {
        87: {top: "-=1"}, // up
        83: {top: "+=1"}, // down
        65: {left: "-=1"}, // left
        68: {left: "+=1"} // right
    };
    var moving = false;
    var move_timer;

    $(this).keydown(function (e) {
        e.preventDefault();

        if (!moving) {
            moving = true;
            movement = move_keys[e.keyCode];
            move_timer = setInterval(startMoving, 1);
        }
    });

    $(this).keyup(function (e) {
        e.preventDefault();

        moving = false;
        clearInterval(move_timer);
    });

    function startMoving() {
        if (movement !== undefined) {
            character.css(movement);
        }
    }
});

jsfiddle:https://jsfiddle.net/4rycer59/1/

2 个答案:

答案 0 :(得分:1)

同时按下键时,您将以不同的顺序接收键盘事件。

我做了以下更改:

var moving; // no longer boolean
var move_timer;

$(this).keydown(function (e) {
    e.preventDefault();

    if (moving !== e.keyCode) {
        moving = e.keyCode; // which key is moving?
        movement = move_keys[e.keyCode];
        clearInterval(move_timer); // just in case keyup is late
        move_timer = setInterval(startMoving, 1);
    }
});

$(this).keyup(function (e) {
    e.preventDefault();

    if(moving === e.keyCode) { // only cancel if not 'late'
        moving = false;
        clearInterval(move_timer);
    }
});

https://jsfiddle.net/Lc8hcnnw/7/

答案 1 :(得分:1)

我建议将按键逻辑与运动逻辑分开。它使事情更容易推理,并允许在多个方向上移动。您还可以使用setTimeout而不是setInterval来改善游戏循环,以便尽可能频繁地运行游戏逻辑。然后,如果您考虑增量时间(自上次游戏循环以来的时间),您可以进一步平滑移动,因为setIntervalsetTimeout并不总是延迟相同的时间。

$(document).ready(function () {

    var character = $('#character');

    var position = character.position();

    var keysPressed = {};

    $(this).keydown(function (e) {
        keysPressed[e.keyCode] = true;
    });

    $(this).keyup(function (e) {
        delete keysPressed[e.keyCode];
    });

    function loop(callback, lastTime) {
        var currentTime = new Date().getTime();
        callback(currentTime - lastTime);
        setTimeout(function () {
            loop(callback, currentTime);
        });
    }

    loop(function(deltaTime) {

        // Use delta from last frame to "smooth" movement
        var steps =  deltaTime / 10;

        if (keysPressed[87]) { // UP
            position.top -= steps;
        }
        if (keysPressed[83]) { // DOWN
            position.top += steps;
        }

        if (keysPressed[65]) { // LEFT
            position.left -= steps;
        }
        if (keysPressed[68]) { // RIGHT
            position.left += steps;
        }

        character.css(position);
    });
});