Fixed timestep logic help

This forum is for discussing shmup development, tools, engines and techniques.
Posts: 1
Joined: Tue Aug 14, 2012 1:53 am

Fixed timestep logic help

Postby ._. » Mon Aug 27, 2012 11:26 pm

I need help visualizing this. I've read almost every timestep article that I could find and I always get lost at the interpolation part. What I think I understand is that to simulate frames using time, each update loop should take t amount of time to go through, and if this time is greater or less than 1/FPS, I do something like position + velocity*(t / (1/FPS)) to have the object at the right position at any time.

What I'm not understanding is a few steps in the middle of this process where the "accumulator" is used as well as integration. Also where in my code would I do all these calculations? I suspect that they would all be done in main and then the "accumulator ratio" would be passed as an argument, but the examples that I've seen make me think otherwise since objects with 2 states are used in the calculations.

The 2 main links I'm trying to learn from:
http://blog.allanbishop.com/box-2d-2-1a-tutorial-part-10-fixed-time-step/
http://gafferongames.com/game-physics/fix-your-timestep/

Would appreciate an image representation of interpolation between the 2 states if possible.

-Fulltime lurker from the old forum

Posts: 1
Joined: Sat Aug 18, 2012 5:37 pm

Re: Fixed timestep logic help

Postby Meseki » Tue Aug 28, 2012 8:16 pm

From a quick look over the second link, the accumulator seems to be a value representing the amount of time left to be processed for physics/etc. In order to keep physics consistent regardless of frame rate, the physics have to be processed in fixed-length steps. In that example, physics are processed in .01 second steps, so if a frame takes .017 seconds, it needs to keep track of the left over .007 seconds so that it would process 2 physics steps in the next .017 second frame:
  • .017 / .01 = 1, remainder .007
  • (.007 + .017) / .01 = .024 / .01 = 2, remainder .004

The integrate() function seems to be where physics are actually processed, so the code decreasing the accumulator is probably best put after input events are acknowledged. The code involving the frame time would go at the beginning of the main loop. You should not have an FPS-based multiplier on the velocity, since the movement would be processed multiple times (if necessary) to keep things moving at the right speed in accordance with real-time.

User avatar
Posts: 34
Joined: Sun Jul 29, 2012 4:44 pm

Re: Fixed timestep logic help

Postby kdmiller3 » Thu Aug 30, 2012 7:40 pm

Here's the way I approach it.

Simulated entities have two transform values, one from the previous simulation step (T0) and one from the current simulation step (T1). They start with the same value at initialization.

Every frame, multiply the time step (dt) by the simulation turn rate (S) and add it to the fractional turn accumulator (f). While the accumulator is greater than or equal to one, subtract one from the turn accumulator, copy the current transform to the previous transform (T0 = T1), and run the simulation using a fixed step (1 / S) to update the current transform (T1). When rendering each entity, use the fractional turn value to interpolate between the previous and current transform (T = T0 + f * (T1 - T0)).

Using S = 10 turns per second:
dt = 0.016667: f += 10 * dt; f = 0.16667
Render T = T0 + 0.16667 * (T1 - T0)
dt = 0.016667: f += 10 * dt; f = 0.33334
Render T = T0 + 0.33334 * (T1 - T0)
dt = 0.016667: f += 10 * dt; f = 0.50001
Render T = T0 + 0.50001 * (T1 - T0)
dt = 0.016667: f += 10 * dt; f = 0.66668
Render T = T0 + 0.66668 * (T1 - T0)
dt = 0.016667; f += 10 * dt; f = 0.83335
Render T = T0 + 0.83335 * (T1 - T0)
dt = 0.016667; f += 10 * dt; f = 1.00002
f -= 1; f -> 0.00002; T0 = T1; run simulation update (1 / S) -> new T1
Render T= T0 + 0.00002 * (T1 - T0)
(lather, rinse, repeat)

The nice thing about all this is that the simulation runs smoothly even when your frame rate varies significantly. The downside is that it introduces a constant latency of 1 / S. It's unnoticeable if S is large (at least 20; 30 is better; 60 is best).

Initializing the fractional turn to 1 on startup forces an update the first frame so things start moving immediately. I definitely recommend it, especially if you're using a low simulation rate.

(Each entity could be on its own update schedule with its own simulation rate and turn accumulator but that way madness lies...)

Return to Development

Who is online

Users browsing this forum: No registered users and 2 guests