代码之家  ›  专栏  ›  技术社区  ›  kjdion84

间隔造成的不必要延迟

  •  1
  • kjdion84  · 技术社区  · 7 年前

    正在为一个超级简单的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);
            }
        }
    });
    

    JSFIDLE(JSIDLE): https://jsfiddle.net/4rycer59/1/

    2 回复  |  直到 7 年前
        1
  •  1
  •   Lee Kowalkowski    7 年前

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

    我做了以下更改:

    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/

        2
  •  1
  •   Jake Holzinger    7 年前

    我建议将按键逻辑与动作逻辑分开。它使事情更容易推理,并允许向多个方向移动。您还可以通过使用 setTimeout 而不是 setInterval 以便尽可能频繁地运行游戏逻辑。然后,如果您考虑了增量时间(自上次游戏循环以来的时间),则可以进一步平滑移动 设置间隔时间 设置超时 不要总是拖延同样的时间。

    $(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);
        });
    });