为什么要对固定时间步长的游戏循环使用积分?(游戏中的灯光师)

YeO*_*ise 5 c c++ game-engine game-loop

http://gafferongames.com/game-physics/fix-your-timestep/

http://www.koonsolo.com/news/dewitters-gameloop/

在 Glenn Fiedler 的Fix Your Timestep的最后一个游戏循环中在文章中,他使用了一个更新循环,将游戏逻辑推进了一个固定的增量时间。既然delta时间是固定的,那他为什么要根据delta时间来积分呢?在基于固定时间步长的游戏中,移动不能像以下那样简单:

if ( keyboard pressing "W" ) {
    velocity += acceleration
}
position += velocity
Run Code Online (Sandbox Code Playgroud)

而不是传入增量时间变量:

if ( keyboard pressing "W" ) {
    velocity += integrated(acceleration, delta_time)
}
position += velocity * delta_time
Run Code Online (Sandbox Code Playgroud)

因为“固定”时间步长循环中的增量时间没有意义,它就像将所有内容乘以 1。在基于“可变”时间步长的游戏中,您必须使用增量时间并整合运动,但在这种情况下,这无关紧要. 请注意 delta time 的变量如何设置为常数并且从未改变,游戏逻辑已经是确定性的,而且似乎不需要在代码的任何地方将速度和加速度乘以 delta 时间。我从这篇文章中学到的是“修复你的时间步长!”,顾名思义,所以你有确定性的游戏逻辑,而不是浮点不准确和随着可变时间步长而来的爆炸物理。我只是对为什么将增量时间传递到更新函数中感到困惑,因为它似乎与本文的目的背道而驰。

double t = 0.0;
double dt = 0.01;

double currentTime = hires_time_in_seconds();
double accumulator = 0.0;

State previous;
State current;

while ( !quit )
{
    double newTime = time();
    double frameTime = newTime - currentTime;
    if ( frameTime > 0.25 )
        frameTime = 0.25;
    currentTime = newTime;

    accumulator += frameTime;

    while ( accumulator >= dt )
    {
        previousState = currentState;
        integrate( currentState, t, dt ); // integration
        t += dt;
        accumulator -= dt;
    }

    const double alpha = accumulator / dt;

    State state = currentState * alpha + 
    previousState * ( 1.0 - alpha );

    render( state );
}
Run Code Online (Sandbox Code Playgroud)

deWiTTERS 最后一个游戏循环做同样的事情:固定时间步长、内插渲染、渲染跳过。然而,它没有像另一个一样提到集成。

rcg*_*ldr 3

假设加速度随时间线性增加或减少,您可以将速度变化基于平均加速度

\n\n
\xce\x94v = (a0 + a1)(\xce\x94t)/2\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果游戏包含空气动力阻力等因素,则加速度会受到速度^2 的影响,通常使用 Runge Kutta 4 之类的东西来更新每个时间步的速度变化和位置变化。

\n\n
\n\n

我的印象是,大多数基于 PC 的游戏都使用独立的固定频率作为物理引擎,理想情况下与帧速率无关。对于这些游戏,即使显示速度很慢,如果玩家可以处理视觉效果,实际的游戏玩法也是一样的。我见过较旧的赛车游戏可以做到这一点,其中图形性能不会影响物理,而较新的赛车游戏则降低图形设置可以提高游戏汽车的性能,这是一个错误。

\n\n

链接到示例 Windows 代码,用于以几乎任何合理的固定频率运行线程,并且不会随着时间的推移而发生漂移。

\n\n

16.66ms 帧时间。当 sleep() 仅持续整毫秒时,如何获得完美的 60 fps?

\n\n

在 MSDOS 时代,由于 PC 以 (105/88) Mhz = 1.19318 Mhz 运行计时器,因此游戏将其用作高精度计时器。

\n