Фиксированная частота кадров SFML

Есть проект для работы с физикой с использованием sfml, но на разных устройствах программа работает по-разному. Как задать фиксированные промежутки времени между обновлениями?

Код:

#include <SFML/Graphics.hpp>

const int WIDTH = 800, HEIGHT = 600;

int main()
{
    sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "Title", sf::Style::Titlebar | sf::Style::Close);
    sf::Clock clock;

    while (window.isOpen())
    {
        float dt = clock.restart().asSeconds();

        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        //update
        update(dt);
        //скорость += ускорение * dt
        //позиция += скорость * dt

        window.clear();
        
        //render
        render(window);

        window.display();
    }

    return 0;
}

Пробовал window.setFramerateLimit(), но это ограничивает только максимальную частоту кадров.


Ответы (2 шт):

Автор решения: a_nR1085__i
//DELTA_TIME = 1.0f / 60.0f

window.setFramerateLimit(1.0f / DELTA_TIME);

while (window.isOpen())
    {
        float dt = clock.restart().asSeconds();

        //update
        unsigned int nr = std::ceil(dt / DELTA_TIME);
        for (int i = 0; i < nr; i++)
            update(DELTA_TIME);

        window.clear();
        
        //render
        render(window);

        window.display();
    }
→ Ссылка
Автор решения: KoVadim

Так как внутрицикловая логика может выполнятся с разной скоростью, то нужно вручную ее "подкорректировать". Обычно это делается так

float want_fps = 50;
while (need_run) {
    int start = getCurrentTime();
    // логика
    //....
    // отрисовка
    //....
    int time_to_sleep = (1.f/want_fps - (stop-start);
    if (time_to_sleep > 0) {
       sleep(time_to_sleep);
    }
}

перепишем это на sfml

float want_fps = 50;
sf::Clock loop_timer;
while(....) {
   // логика и отрисовка
   // ....
   sf::Int32 frame_duration = loop_timer.getElapsedTime().asMilliseconds();
   sf::Int32 time_to_sleep = int(1000.f/want_fps) - frame_duration;
   if (time_to_sleep > 0) {
        sf::sleep(sf::milliseconds(time_to_sleep));
    }
    loop_timer.restart();
}
→ Ссылка