Jump to content
  • Advertisement
Sign in to follow this  
Hanksha

Advice to lock frame rate

This topic is 1606 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi!
 
I'm on a project of a 2D platform action game (it's my first "ambitious" project, I've just been able to finish mini game) code in C++ with SDL2.
 
I need some advice about how to lock the frame rate (by lock I understand that it's lock for frame rate to go higher but not lower). 
On my game the movement of the player is frame based, 6 pixel per frame (or 8 pixel when running), I've not been able to understand correctly the time based movement (At least to understand enough to write my own code), I thought to lock frame rate is my best solution. The game will not be graphically heavy so I guess it will not be a big deal since most of the computer could run it.
 
I've been able to write the following code:
 
- My game loop:

#define FRAMERATE 60

void CMain::GameLoop()
{
    while (windowEvent->GetMainEvent()->type != SDL_QUIT)
    {
    timerFps = SDL_GetTicks();


    windowEvent->Begin();


    SDL_GetMouseState(&MouseX, &MouseY);


    Player->Update();
    environment->Update();


    environment->DrawBack();
    environment->DrawFront();
    
    Player->Draw();

    windowEvent->End();
    
    timerFps = SDL_GetTicks() - timerFps;

        if(timerFps < 1000/FRAMERATE)
        {
            SDL_Delay((1000/FRAMERATE) - timerFps);
        }
    }
}

 Detail of functions used:

void CWindow_Event::Begin()
{
    SDL_PollEvent(mainEvent);
    SDL_RenderClear(renderer);
}

void CWindow_Event::End()
{
    SDL_RenderPresent(renderer);
}

When I check my frame rate with other tools, it indicates a fps around 65 (not steady), I notice on other 2D game (e.g Rogue Legacy or Spelunky) the frame rate is really stable 60.
So I guess there is something wrong in my code, and maybe it will look horrible for some of you. What should I change?
 
(ps: I have many question on other topic related to my project, should I open a topic for each or put everything in here?
pps: Sorry for my english, it's not my mother tongue.)

Share this post


Link to post
Share on other sites
Advertisement

On any platform you could control the rate of update and render with this simple algorithm

 

float dt; //delta time in seconds

float clock; //last time sample in seconds

float render_timer; //time control for rendering

 

dt = 0.0;

render_timer = 0.0; //init the render timer

clock = getTime(); //API callback to get the current time in seconds

 

while(true) //game loop

{

   dt = getTime() - clock; //get the current delta time for this frame

   clock = getTime(); //updates the clock to check the next delta time

 

   update(); //update stuff;

 

   if(render_timer >= (1.0f/60.0f)) //checks if the frame is ready to render

   {

      render(); //render your stuff

      render_timer -= (1.0f/60.0f); //do not set to zero, remove the accumulated frame time to avoid skipping

   }

 

   render_time += dt; //updates the render timer

 

}

Share this post


Link to post
Share on other sites

I never understood why ppl would lock their framerate manually rather than letting vsync do it's job...

Share this post


Link to post
Share on other sites

On any platform you could control the rate of update and render with this simple algorithm
 

 

 

I think I'm doing pretty much the same:

#define FRAMERATE 60
int timererFps;

while (true)
    {
        timerFps = SDL_GetTicks(); // SDL_GetTicks() gives the number of milliseconds since the program start.
                                   // I initialize the timer.

        update(); //update stuff...

        timerFps = SDL_GetTicks() - timerFps; //I get the time it took to update and draw;

        if(timerFps < 1000/FRAMERATE) // if timerFps is < 16.6666...7 ms (meaning it loaded the frame too fast)
        {
            SDL_Delay((1000/FRAMERATE) - timerFps); //delay the frame to be in time
        } 
        render(); // render stuff...
    }

Am I not correct?

 

ps: I just noticed I was rendering before to delay, I correct it, now I'm around 58fps.

 

 

 

 

I never understood why ppl would lock their framerate manually rather than letting vsync do it's job...

 

Because I don't know how to enable vsync with SDL2 I didn't see such thing.

Share this post


Link to post
Share on other sites


I think I'm doing pretty much the same

 

I think yours and eduardo's are different. Your algo will update, render and wait some time as filler to make it 16 millisec per frame (1 update per render with waiting), while eduardo's will update multiple times until 16 millisecs or more has passed before rendering (one or more updates per render without waiting).

 

For more information, look at the article Fix your timestep! on the internet, it talks about various kinds of game loops.

Share this post


Link to post
Share on other sites

Ah thank you I understand the difference, so are they equivalent or the one of eduardo is better to implement?

Share this post


Link to post
Share on other sites
Because I don't know how to enable vsync with SDL2 I didn't see such thing.

 

I never used SDL, but judging from that post and my opengl experience, i guess you didn't use double buffering. Double buffering will remove any tearing effect on fast moving scenes, and lock your framerate for you as a bonus by default.

Edited by Vortez

Share this post


Link to post
Share on other sites

Ah thank you I understand the difference, so are they equivalent or the one of eduardo is better to implement?

 

 

With frame based movement, they are most definitely NOT equivalent.  Quite the opposite, actually.  Multiple updates will cause multiple frame-based moves in a single 'frame'.  With frame based movement, you want only a one to one ratio of updates and renders.

 

Your fps fluctuations are possibly due to the precision of SDL_GetTicks, which is inadequately documented.  The precision of this call is platform dependent, but may be as poor as 10ms, which would prevent you from precisely locking down your framerate.  Even at it's documented 1ms accuracy you'll have trouble precisely locking down your framerate as the difference between 60fps and 65fps is only a bit over 1ms (16.66ms per frame vs 15.38ms per frame).

 

The real solution is to take the time and learn time based movement and get away from frame based movement.  Otherwise, look at using a sub-ms resolution high performance counter, which is going to be very platform dependent.  On Windows, look at QueryPerformanceCounter/QueryPerformanceFrequency.

Share this post


Link to post
Share on other sites

 

Because I don't know how to enable vsync with SDL2 I didn't see such thing.

 

I never used SDL, but judging from that post and my opengl experience, i guess you didn't use double buffering. Double buffering will remove any tearing effect on fast moving scenes, and lock your framerate for you as a bonus by default.

 

 

I think I found the better way, looking at the function SDL_SetVideoMode (which I think doesn't exist in SDL2) I notice a flag that I didn't see before SDL_RENDERER_PRESENTVSYNC , I just add it to my renderer creation function:

 

renderer = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

 

Now the fps is stable 60. (But I wonder if this vsync can be still disable by the user)

 

So I guess now my best call is to really work on time based movement.

 

Thanks everyone for the help!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!