Jump to content
  • Advertisement
Sign in to follow this  
too_many_stars

regulating the main loop, and physics

This topic is 1062 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 Guys,

 

I am having some issues with regulating the main loop, the situation looks like this...

Uint32 time_start;
Uint32 time_end;
while(running){

    time_start=SDL_GetTicks();

    
    update()//using semi fixed time step as found here
            //http://gafferongames.com/game-physics/fix-your-timestep/


    render();


    time_end=SDL_GetTicks();
    time_diff=time_end-time_start;

    if(1000.0f/60.0f>time_diff)
        SDL_Delay((Uint32)(1000.0f/60.0f-time_diff));

}

Without SDL_Delay, am running around 1000-1200 fps. The physics, collisions, springs etc everything works fine

 

However, as soon as I limit the FPS to 60, via SDL_Delay, entities start jittering, collisions are missed and the physics breaks down. Additionally, there are noticable spikes when the simulation freezes for some milliseconds which looks awful.

 

I remember reading in a few places that one should just let the main loop run at whatever speed is needed.

 

Conversly, I also read that it's a terrible waste of CPU power, and should be limited.

 

So my question is this. How does one limit the main loop to a desired FPS rate, and not have the physics break down and introduce annoying freezing.

 

Thanks,

 

Mike

 

 

 

 

 

Share this post


Link to post
Share on other sites
Advertisement

Thanks for the replay Alvaro,

 

As you will notice int the code section, beside the update() func, I mention that I am using the semi-fixed time step with the same link as you provided.

 

I will read the entire article again to make sure I did not miss anything.
 

Mike

Share this post


Link to post
Share on other sites

You can write a custom sleep function that uses the 'real' sleep function for sleeping most of the duration, but then uses a busy loop for the remaining time (because its more accurate)

 

For example:

 

You want to wait 16.66... ms

 

You assume windows sleep() function has error up to 2 ms (I dont know what a good value is, it varies at runtime and might depend on machine, so best would be measure it at runtime but dont let occasional spikes mess with the measurement)

 

So then sleep() for 16.66.. - error = 14.666 ms

 

Then measure how long you ACTUALLY waited, lets say 15.4 ms

 

Then just loop for the remaining time (until current time is 16.66... ms from initial timepoint)

 

 

If youre not using VSync that is.

Edited by Waterlimon

Share this post


Link to post
Share on other sites
Nice,
in real life we'll only need the busy loop (assuming we want to wait maximum 2ms).

Would it be ok to do this:

while (GetTicks() < targetTime) {SwitchToThread();}

to allow some other work to be done?



Or is this better? (seems just burning CPU):

while (GetTicks() < targetTime) {}

Share this post


Link to post
Share on other sites

if you go with "fix your timestep", you'll want to use the last algo presented in the article (with animation tweening between previous and current update states), not the semi-fixed timestep one described part way through the article.

 

the various algo's in the article show the evolution from basic game loop to full blown fixed update with unlimited render and animation tweening.

 

but each algo (except the last) has issues that are addressed in the next one presented.  this includes the semi-fixed timestep algo. its better than the one described before it in the article, but still has issues.  

 

you'l also need to make sure your variables don't overflow or underflow after multiplying by dt  - which would tend to make your physics "blow up".  

 

and you'll need to change your movement rates and such in update to reflect the change in update rate between unfixed and fixed timestep -  which also might make the physics "blow up".

 

also note that a ET cap is required to avoid frame dropping under heavy graphics load, and the spiral of death in extreme cases. 

 

and for full blown fixed timestep, you'll need to save both current and previous update states, IE the current AND previous location and rotation of EVERYTHING, and you'll have to tween between those for EVERYTHING you draw - everything that moves that is.

 

a framerate limiter is the other option - basically what you're trying to do now - burn extra milisecs leftover after one iteration of the main game loop. but there, a hi-rez timer is usually called for to get smooth consistent framerates.

 

also remember that a framerate limiter will also require you to adjust movement rates etc. in update to reflect the difference in update rate between unlimited and limited framerates. if everything is correct at 1200 fps, everything*x will be correct at 60 fps, where x=1200/60=120/6=20. IE you update 1/20th as often at 60fps, so the movement rate must be 20 times as great for the same result as that which you get at 1200 fps.

Edited by Norman Barrows

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!