c++ - 为什么对固定时间步长的游戏循环使用积分? (Gaffer 谈游戏)

标签 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

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

if ( keyboard pressing "W" ) {
    velocity += integrated(acceleration, delta_time)
}
position += velocity * delta_time

因为“固定”时间步长循环中的增量时间没有任何意义,它就像将所有内容乘以 1。在基于“可变”时间步长的游戏中,您必须使用增量时间并对运动进行积分,但在这种情况下它没关系。请注意 delta time 的变量是如何设置为常量且从未更改的,游戏逻辑已经是确定性的,并且您似乎不需要在代码中的任何地方将速度和加速度乘以 delta time。我从这篇文章中学到的是“修正你的时间步长!”,顾名思义,这样你就有了确定性的游戏逻辑,而不是可变时间步长带来的浮点不准确和爆炸性物理现象。我只是对为什么要将增量时间传递给更新函数感到困惑,因为它似乎违背了本文的目的。事实上,这两篇文章都提出了反对增量时间的相同论点。

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

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

最佳答案

假设加速度随时间线性增加或减少,您可以根据平均加速度改变速度

Δv = (a0 + a1)(Δt)/2

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


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

链接到以任何合理的固定频率运行线程的示例 Windows 代码,不会随时间漂移。

16.66ms frames times. How do you get a perfect 60 fps when sleep() only goes by whole milliseconds?

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

关于c++ - 为什么对固定时间步长的游戏循环使用积分? (Gaffer 谈游戏),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43302268/

相关文章:

c++ - 从构造函数体调用父类(super class)构造函数

c++ - ncurses:奇怪的行格式

ios - Swift 编译器错误 : 'Double' is not convertible to CGFloat

java - Slick2D游戏变速

java - "Lambda expressions are not supported in -source 7, use -source 8 to enable lambda expressions"

android - LIBGDX - body 在 Android 上掉落并缓慢运行,但在桌面上没有

c++ - 计算具有旋转前位置和旋转角度的点的绝对位置

c++ - 如何在 3D 点上绘制文本?

c - 如何查看/保存格式为 AV_PIX_FMT_YUVJ420P 的 AVFrame 到文件

C - 系统调用 - 读/写结构中的错误