2

我已经在 Flash/Actionscript/Starling 中实现了一个游戏循环,我想把它扔给你看看这是否是一个有效的实现。我想有一个可变的时间步长方法。

private var _deltaTime:Number = 0;
private var _lastTime:Number = 0;
private var _speed = 1000 / 40;

private function onEnterFrame() {
    var now = new Date().getTime();
    var delta = now - _lastTime;
    _deltaTime += delta - _speed;
    _lastTime = now;

    //skip if frame rate to fast
    if (_deltaTime <= -_speed) {
        _deltaTime += _speed;
        return;
    }
    update();
}

private function update() {
    updateGameState();

    if (_deltaTime >= _speed) {
        _deltaTime -= _speed;
        update();
    }
}

到目前为止我得到的是我有一个恒定的速度(或多或少)。

我的问题是有没有更好的方法让动作看起来更流畅。

让我真正感到惊讶的是,即使你的 FPS 几乎是恒定的(60FPS),运动有时也比简单的游戏循环更颠簸但更流畅。

4

2 回答 2

4

你在正确的轨道上 - 假设 onEnterFrame 是由 Event.ENTER_FRAME 以某种方式触发的 - 而不是跳过更新,而是在每一帧上调用它,但传递经过的时间:

private function onEnterFrame() {
    var now = new Date().getTime();
    var delta = now - _lastTime;
    _lastTime = now;
    updateGameState(delta/1000);//divide by 1000 to give time in seconds
}

在 updateGameState 中,您可以利用 'delta' 来计算移动等,例如:

function updateGameState(timeElapsed:Number):void {
    myAlien.x += myAlienSpeedPerSecond*timeElapsed;
}

这样,即使帧速率发生变化,您也可以获得流畅的移动。

于 2013-02-21T19:50:27.923 回答
0

从 Starling 介绍页面中,它显示经过的时间已内置到 EnterFrameEvent 类中。

// the corresponding event listener
private function onEnterFrame(event:EnterFrameEvent):void
{
    trace("Time passed since last frame: " + event.passedTime);
    enemy.moveBy(event.passedTime * enemy.velocity);
}

http://wiki.starling-framework.org/manual/animation#enterframeevent

于 2013-11-18T15:24:52.437 回答