在游戏循环中使用 sleep() 会使增量时间不稳定

Using sleep() in game loop makes delta time unstable

我正在用 sfml 编写游戏循环。当我不让它休眠时,每次循环迭代经过的时间约为 1 毫秒。但是当我添加 sleep(sleepTime) 突然 dt 很高。我在循环开始时重新启动 dt,但它似乎增加了最后一个睡眠时间。是什么原因造成的?

sf::Clock clock;
float dt;
sf::Time sleepTime = sf::milliseconds(0);

while(m_Window.isOpen())
{
    sf::Time elapsed = clock.restart();
    dt = elapsed.asMilliseconds();

    cout << "Elapsed: " << dt;

    sf::Event event;

    while(m_Window.pollEvent(event))
    {
        switch(event.type)
        {
            case sf::Event::Closed:
                m_Window.close();
                break;
        }
    }

    sleepTime = sf::milliseconds(16 - dt);

    float time = sleepTime.asMilliseconds();
    cout << "\tSleep time: " << time << endl;

    if(sleepTime >= sf::Time::Zero)
    {
        sf::sleep(sleepTime);
    }
    else
    {
        cout << "Shit." << endl;
    }

没有睡眠:https://aww.moe/sn1z0a.png

有睡眠:https://aww.moe/7seof1.png

您尝试做的事情——将游戏限制在一个特定的帧率——已经内置到 SFML 中。只需将您预期的帧率作为参数调用 sf::Window::setFrameRateLimit() 即可。也可以使用垂直同步(通过使用 sf::Window::setVerticalSyncEnabled())来限制 frames/updates 的数量,尽管这通常被认为是一个坏主意,因为如果目标机器无法渲染,游戏也会变慢以所需的帧率(或在 120 或 140Hz 下为高端屏幕加速 运行)。

但是,您通常希望将游戏更新与帧速率断开连接,这样游戏就不会变慢,即使当前机器无法足够快地更新屏幕也是如此。

使用 SFML 的基本方法通常如下所示(这是记忆中的,因此可能包含错误或拼写错误):

sf::Clock updateTimer; // Clock to monitor the time passed
sf::Time passedTime; // Accumulated game time
const sf::Time frameTime(sf::milliseconds(10)); // intended time per frame; here: 10ms

while (window.isOpen()) {
    sf::Event event;
    while (window.pollEvent(event)) {
        // Event handling
    }

    // First add the time passed
    passedTime += updateClock.restart();

    unsigned int numUpdates = 0; // Count the updates done

    // As long as enough time passed, do an update
    // Up to a specific maximum to avoid problems, e.g.
    // the main thread was blocked or can't catch up
    while (passedTime >= frameTime) {

        if (numUpdates++ < 10) {
            // Do your game update here
        }

        // Subtract the time we've "handled"
        passedTime -= frameTime;
    }

    window.clear();
    // Draw your game here
    window.display();
}

numUpdates 的用法一开始可能不太清楚,但请想象一下机器勉强能够 运行 所需的每秒 100 次更新的情况。如果你落后 20 次更新(一些小问题或其他),机器将永远无法再次正确地赶上,导致严重的卡顿或游戏变得无响应。