I'm writing a game loop with sfml. When I don't make it sleep, time elapsed for each loop iteration is ~1ms. But when I add sleep(sleepTime) suddenly dt is high. I restart dt at the beginning of the loop but it seems that it adds last sleep time to it. What causes it?
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;
}
Without sleep: https://aww.moe/sn1z0a.png
With sleep: https://aww.moe/7seof1.png
What you're trying to do – limiting the game to a specific framerate – is already built into SFML. Just call
sf::Window::setFrameRateLimit()
with your intended framerate as parameter and you're set. It's also possible to use vertical synchronization (by usingsf::Window::setVerticalSyncEnabled()
) to limit the number of frames/updates, although it's often considered a bad idea, since the game would also slow down if the target machine can't render at the desired framerate (or speed up for high end screens running at 120 or 140Hz).However, you'll typically want to disconnect your game updates from your frame rate so the game doesn't slow down, even if the current machine can't update the screen fast enough.
The basic approach using SFML will typically look like this (this is from memory, so might include bugs or typos):
The usage of
numUpdates
might not be clear at first, but just imagine a situation where the machine is barely able to run the desired 100 updates per second. If you're 20 updates behind (some hick-up or whatever) the machine will never be able to catch up again properly, causing heavy stuttering or the game becoming unresponsive.