如何在Box2D和SFML中设置固定的绘图速度和世界步骤?

问题描述 投票:0回答:1

有一个简单的项目,Box2D从事物理学,SFML绘制。在不同机器上具有不同性能速度的程序各不相同。如何设定固定速度?那么在强大的,平均的和弱的计算机上,程序的速度(对象的移动)是一样的吗? 我们需要让Box2D以相同的速度在不同的计算机上运行。它还给出坐标,SFML在给定坐标处绘制一个正方形。如何解决这个问题呢?

c++ box2d sfml game-development
1个回答
1
投票

Constant Frame Rate是您正在寻找的。这是一个众所周知的问题。

如你所说,不同的机器将具有不同的处理器速度。这可能涉及具有更好硬件处理的计算机,您的游戏循环每秒更多次。

如果你想设置一个固定的帧速率,比方说,60 FPS,你所要做的就是(正如Öö Tiib指出的那样)限制你的更新每1/60秒进行一次更新。

这是一个常见的实现:

const sf::Time TimePerFrame = sf::seconds(1.f / 60.f);    // 60 FPS

void run(){
        sf::Clock clk;
        sf::Time timeSinceLastUpdate = sf::Time::Zero;
        while (_window.isOpen())
        {

            sf::Time dt = clk.restart();
            timeSinceLastUpdate += dt;
            while (timeSinceLastUpdate > TimePerFrame)
            {
                timeSinceLastUpdate -= TimePerFrame;

                processInput();
                update(TimePerFrame);
            }
            render();
        }
    }
}

这样,如果机器运行得更快,您将每1/60秒更新一次世界状态。


TL;DR;

当程序启动时,timeSinceLastUpdate取值0,检查while并获取自clk创建(或重新启动)以来经过的时间,假设数字t1小于1/60秒。程序将它添加到timeSinceLastUpdate并绘制场景,因为它是创建的(游戏的初始状态)。

你的while的第二个循环,你再次获得经过的时间(自上次循环以来经过,因为你重新启动了时钟)。让我们这次打电话给t2。同样,这个数字小于1/60秒,但是,当你将它添加到timeSinceLastUpdate时,两者都加起来大于1/60(所以timeSinceLastUpdate = t1 + t2 > TimePerFrame)。这一次,您将进入第二个循环,并像1/60秒一样更新您的世界。你从timeSinceLastUpdate减去1/60秒并再次检查。如果剩余超过1/60秒,您将再次更新,直到您保持最新状态。

如果你看起来很小心,你只需要调用update(TimePerFrame),所以你总是会以1/60秒的速度更新你的世界。


来自SFML Game Development Book。第1章:制作游戏勾号

Fixed time steps

到目前为止,我们提出的解决方案对于许多情况来说已经足够了。但它并不是一个完美的解决方案[...],因为每一帧都是独一无二的,你不能保证增量时间保持不变。考虑一个帧有时可能需要平均增量时间的三倍。这可能导致游戏逻辑中的严重错误,例如,当玩家移动三倍距离并穿过他通常会碰撞的墙壁时。这就是物理引擎期望修正增量时间的原因。

以下是描述我们所指的问题的图:

enter image description here

我们现在要做的是使用一种称为固定时间步骤的技术。我们编写的代码保证在任何情况下,无论发生什么,我们总是给更新函数提供相同的增量时间。如果你发现听起来很难,那与我们已经拥有的东西没什么大不同。我们只需要在代码中做一些记账,因为我们上次调用update()函数已经过了多长时间。

代码类似于上面的代码,内部while (timeSinceLastUpdate > TimePerFrame)

这种变化的实际效果是我们积累了变量timeSinceLastUpdate中经过了多长时间。当我们超过一帧所需的数量时,我们减去该帧的所需长度(即TimePerFrame),并更新游戏。我们这样做,直到我们再次低于所需的金额。这解决了变量delta时间的问题,因为我们保证始终运行相同数量的帧。在您可以下载的应用程序中,通过使TimePerFrame常数等于sf::seconds(1.f / 60.f),逻辑帧速率将设置为每秒60帧。

© www.soinside.com 2019 - 2024. All rights reserved.