I'm using SDL 1.2 and VS2008 for a smaller game-like application. I have recently (after getting some ideas from other posts on SO which i cannot find now, so sorry if you feel i should have linked your question for reference) re-written my game-loop to not use Sleep or SDL_Delay for timing. Instead i call my game logics with a known frequency and calculate distances and locations based on actual time step.
When doing this i was expecting the FPS to be limited by SDL_Flip to the framerate of the screen (vsynch?) but i ended up with roughly 300 FPS on my machine, which runs Windows 7. What could be the cause of this? Can you run the entire game loop (including SDL_Flip) multiple times in between monitor vsynchs? Is the behavior perhaps different on different machines or is SDL_Flip never supposed to synchronize to vsynch? I don't see any flickering or other effects of out of synch screen updating i would expect.
Here is my game loop for reference:
void GraphicsFramework::run()
{
Uint32 last_input_check = 0;
Uint32 last_logics_check = 0;
while(true)
{
Uint32 now = SDL_GetTicks();
if(now - last_input_check > 10) // Every 10 millisecond
{
if(!processEvents())
{
return;
}
last_input_check = now;
}
if(now - last_logics_check > 20) // Every 20 milliseconds
{
handleGameLogics();
last_logics_check = now;
}
draw(); // No FPS limitation
m_Window.flipSurface(); // Calls SDL_Flip(surface)
m_ActualFrameTime = SDL_GetTicks() - now;
}
}
Edit: Fixed FPS with busy waiting would look like this. Replace
m_ActualFrameTime = SDL_GetTicks() - now;
with
do
{
m_ActualFrameTime = SDL_GetTicks() - now;
} while ((Uint32)(1000/m_ActualFrameTime) > getDesiredFPS());
This gives a way more stable result than using SDL_Delay or Sleep, for which you get a somewhat variable FPS, at least on my machine. Both of course breaks the timing of processEvents() in the example.
Also adding the SDL_Delay variant for completeness:
Sint32 timeToSleep = (Uint32)(1000/getDesiredFPS()) - m_ActualFrameTime;
if(timeToSleep > 0)
{
SDL_Delay((Uint32)timeToSleep);
}
SDL_Flip simply pushes what you have on the surface to the screen. It has nothing to do with the fps. And no you shouldnt use SDL_Flip multiple times on the same loop, you should do it after you have updated your surface and are ready to show it on the screen.
To manage fps SDL_Delay (that simply calls sleep) is your best bet i think.