Domanda

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);
        }
È stato utile?

Soluzione

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top