Box 2D 2.1a Tutorial – Part 10 (Fixed time step)

Box2D Fixed time step
So far, in each tutorial, we have been calling the step function on each frame update with a fixed delta time to apply the physics. This works quite well as we have seen.

However, there is a problem with this approach. While we may be targeting a frame rate of say 60fps, there is no guarantee that it will update that frequently. A user’s computer hardware may cause it to run slower or faster than this, and subsequently, the physics simulation may appear to run either in slow motion or to appear sped up.

So if you are finding this a problem in your game how can we go about fixing this? The answer is to separate the physics update from our game loop so the physics is not dependant on how often the game loop is called.

While there are a few ways we might want to achieve this, we have to consider the effects of the various implementations. For example, it would be fair to assume that instead of passing in a fixed delta to the step function, that we instead could measure the time it takes per frame for the game loop to be called, and based on this value, call the step function.

Unfortunately, there are a few problems with this approach. The main reason is that the size of the delta can significantly affect the physics engine. Simply, if it is too big, then the engine will exhibit all sorts of bizarre behaviour. Remember, in the real world physics is continuous, but in a computer simulation we don’t have such luxury so ideally we want to call the physics update as quickly as possible. Additionally, the simulation is no longer deterministic. That is, it is no longer predictable, so if we were to create a scene involving a few box2D bodies and apply some predetermined force, then each time we run the game, the resulting collisions would be slightly different.

This would make it impossible to accurately implement a replay function, or to set up some scene and ensure the outcome of applying forces will always be the same.

To solve this, we have to ensure that we don’t use a variable delta time for updating the step function, but that leaves us back to where we started. The trick is, that instead of calling the step function once per frame update, we call it a variable amount of times, depending on how long the games update loop takes.

There is a detailed explanation of the algorithm at http://gafferongames.com/game-physics/fix-your-timestep/

However, to save you some time, and also to serve as an alternative explanation, I will demonstrate the concept behind the algorithm using an example:

Underneath are the blocks that represent the time it takes per game loop. In a perfect world we would ideally want each loop to take 0.01666666 seconds to then be exactly 60 frames per second. But as you can see, the first loop is a little slower and takes 0.021 seconds. So we know that we can step at least once and have a little bit of a remainder left. So what do we do with this remainder? We could store this value and add the time to the next frame time for when we divide by the fixed rate. However, this causes what is known as temporal aliasing, a stuttering of the rendering due to the render and physics being out of sync.

Fixed time step diagram

An analogy would be to imagine a car with a fast constant velocity. If at time = k it does 2 steps and renders but then at time=k+1 it does 4 steps, then it won’t appear very smooth.
Therefore, with this remainder, we instead use whatever is left as a ratio of how far we are to the next physics state. So if we know the position of a body is [2,3] and the next state it is [4,5] and the ratio is 0.5, then we can figure out that the graphics should be rendered at [3,4].

But how do we know what the next state is? We don’t. That leaves us with two choices. Either predict what the next state might be (extrapolation), or, ideally, we run the loop and take the last state and the state before that as the two states (interpolation). Then we use the ratio on this. Of course, this means the renderer will always be 1 frame behind the physics but this should not be a problem. You can find a more detailed explanation at http://www.unagames.com/blog/daniele/2010/06/fixed-time-step-implementation-box2d. I have also gone and ported over their code into ActionScript 3.0 which you can find below.

private var _currentTime:Number = GameTimer.getVirtualTime() / 1000; //your implementation here may differ
private const FIXED_TIMESTEP:Number = 1 / 60;
private var fixedTimestepAccumulator:Number = 0;
private var fixedTimestepAccumulatorRatio:Number = 0;
private var velocityIterations:int = 8;
private var positionIterations:int = 1;

public function process():void
{
	var newTime:Number = GameTimer.getVirtualTime() / 1000;
	var dt:Number = newTime - _currentTime;
	_currentTime = newTime;

	const MAX_STEPS:int = 5;
	fixedTimestepAccumulator += dt;
	const nSteps:int = Math.floor(fixedTimestepAccumulator / FIXED_TIMESTEP);

	if (nSteps > 0)
	{
		fixedTimestepAccumulator -= nSteps * FIXED_TIMESTEP;
	}
	fixedTimestepAccumulatorRatio = fixedTimestepAccumulator / FIXED_TIMESTEP;
	const nStepsClamped:int = min(nSteps, MAX_STEPS);

	for (var i:int = 0; i < nStepsClamped; ++i)
	{
		resetSmoothStates();
		singleStep(FIXED_TIMESTEP);
	}
	world.ClearForces();
	smoothStates();
}

Our singleStep function has to do a few things that depends on how you have set up the rest of your system so I can’t supply you with copy n paste code. Before the world.Step function is called, you will want to apply the various forces to the world bodies to ensure constant speed of objects regardless of the render frame rate. Same goes for polling of key inputs.
After the world.Step function is called you will also want to process any collisions.

private function singleStep(dt:Number):void
{
	//TODO apply physics forces, poll inputs etc
	world.Step(dt, velocityIterations, positionIterations);
	//TODO process collisions
}

The following code will again depend on how you have set up your game so don’t copy it verbatim.

private function smoothStates():void
{
	const oneMinusRatio:Number = 1.0 - fixedTimestepAccumulatorRatio;

	//Makes it easier to wrap up the Box2D body in another object so we can track other variables.
	for each (var body:Body in bodies)
	{
		var box2Dbody = body.box2DBody;

		texture.position.x = fixedTimestepAccumulatorRatio * box2Dbody.GetPosition().x + (oneMinusRatio * body.previousPosition.x);

		texture.position.y = fixedTimestepAccumulatorRatio * box2Dbody.GetPosition().y + oneMinusRatio * body.previousPosition.y;

		texture.rotation = box2Dbody.GetAngle() * fixedTimestepAccumulatorRatio + oneMinusRatio * body.previousAngle;
	}
}

private function resetSmoothStates():void
{
	for each (var body:Body in bodies)
	{
		texture.position.x = body.previousPosition.x = body.box2Dbody.GetPosition().x;

		texture.position.y = body.previousPosition.y = body.box2Dbody.GetPosition().y;

		texture.rotation = body.previousAngle = body.box2Dbody.GetAngle();
	}
}

19 thoughts on “Box 2D 2.1a Tutorial – Part 10 (Fixed time step)

  1. Rocket Ronz says:

    Very refreshing to find someone that is willing to share their valuable knowledge and does so in such a clear and concise manner. The world needs more developers like yourself :)

  2. EaP says:

    Hey Alan, 
    I wanted to thank you for sharing your knowledge about box2d in the past tutorials. I had seen the package coming by a couple of times and finally decided to use it in some of my projects. Your tutorials were a great source to get started. Keep up the good work!  

  3. jeremy says:

    it’s not clear to me why this works.

    there is a previous state, current state, and some un-computed future state.

    reading this code, it looks like fixedTimestepAccumulatorRatio is a “progression” between “now”/current state and “next”/future state

    but smoothStates blend the previous and current state, not the current and future state (obviously, since the future state is not available).

    why does that interpolation have any meaningful relationship to the progression between the current and future state?

  4. jeremy says:

    okay, i jumped the gun with this question. i actually read the text and not just the code now and you do spell out that we’re shifting everything by one step on the timeline.

  5. Florian says:

    Hey Allan,

    Thanks for your refreshing concept.

    I’ve tried your code it in my application, though I’m still facing some temporal aliasing errors.

    Could you briefly explain what “GameTimer.getVirtualTime()” exactely returns? Is it like the number of elapsed ticks? Or would you return the amount of time the rendering thread used for the last frame? Also, in which unit is it?

    Thanks for your answer.

  6. allanbishop says:

    You can double check your code with the original, non as3 source at http://www.unagames.com/blog/daniele/2010/06/fixed-time-step-implementation-box2d and see if that helps.

    GameTimer.getVirtualTime() is a wrapper for getTimer() which returns the total time the game has been running in milliseconds. The reason I made a wrapper is that it supports pausing, so you can pause the game and the time that is returned takes into account the total pause time. Hope that helps.

  7. Florian says:

    Hello Allan,

    Thanks for your really quick response (I’m surprised how quickly you reponse, but not less thankful for your comment).

    I have already carefully read the original page. However Daniele uses the “dt” as a paremeter to his void PhysicsSystem::update (float dt) function and does not precisely explain what “dt” is. I know it’s “delta time” and probably the time it took for the last iteration. But which “delta time” is it? I’m asking this because for one of my applications I’m running my physics system in a seperate thread than the rendering thread. Now which “dt” would it be? The “dt” for the physics loop or for the rendering loop?

  8. allanbishop says:

    No problem :) I think it is the rendering loop. In the original Fix Your Timestep! article, Glenn says “The renderer produces time and the simulation consumes it in discrete dt sized chunks.”

  9. Florian says:

    Hello Allan,

    Thank you for your answer. It seems that it really was the rendering delta :) However I faced another issue: The physics thread, as its frequency is different than the one from the rendering thread, can’t reliably define the position of the physics body. This is, as the interpolation between each physics step has to be performed in the rendering thread, since this is where the position of each body is actually used.
    I have now put all physics calculation inside the rendering thread, as the original author probably inteded. Unfortunately, Daniele never mentions this in his post, but it’s basically my fault, as I thought he’d be running the physics in a seperate thread.
    Thank you again for your help!

  10. George says:

    Hey Allan,

    Thanks for the great article and code.

    I’m trying to implement it right now …but I can’t seem to get the Sprites to move smoothly.

    Here’s what I’m doing :

    I call process() every frame.

    I store the actors (the Sprite for each body) in body.userData.

    I’ve create a class for each actor that extends Sprite and added the previousPosition, previousAngle proprieties to it. Then I just use body.GetUserData() instead of texture (in your code).

    It runs smooth for a while but from time to time (when the frame rate drops and more steps are processed) the moving Sprites seem to jump ahead a bit and then back.

    Can you tell me what I’m doing wrong?

    Should I only be updating the Sprite positions in smoothStates? – I’ve tried it but it’s more unstable.

    Thanks again for the great code .

    I would really appreciate it if you could point me in the right direction.

  11. allanbishop says:

    Hi George,

    Sounds like something is going wrong with the interpolation. It’s hard to say what it is without seeing code, but just to clarify some things:

    1) You can update the B2Body position anywhere. The changes will only take effect in singleStep as that is when the Physics world is updated.

    2) Assuming you have not made a typo then your algorithm should run like the code above in regards to the steps.

    3) Once the steps have looped we then will begin interpolation, taking the last frames body position, and the current body position and then using the ratio to calculate where the Sprites display position is going to be (somewhere between its last frame position and the current). This means the display will always be one frame behind.

    As long as the interpolation happens once, after updating the body positions, then it should be fine. Things to check are your dt values. In my case I am using GameTimer.getVirtualTime() which is a wrapper around getTimer() but takes into account pausing. If you are using a Timer then that could cause a problem.

  12. George says:

    Thanks for the reply.

    So instead of :
    var newTime:Number = GameTimer.getVirtualTime() / 1000;
    I can just use:

    var newTime:Number = getTimer / 1000; ?

    Because I coincidentally have my own GameTimer class … with a getVirtualTime() method … that returns getTimer() – start (start is the time when the game started) and I’ve been using that. I’ve changed the newTime var to use getTimer …and it seems to work. Still testing now.

  13. allanbishop says:

    Yes, var newTime:Number = getTimer / 1000; would work exactly the same (as long as you don’t need to pause).

    Your getTimer()-start should be fine though. Let me know how the testing goes.

  14. George says:

    Managed to get it working smoothly by adding :

    if (i == nStepsClamped – 1) {
    resetSmoothStates();
    }
    in the step loop.

    I found this in a C version around the web and now it works very well.

    Thanks again for your help.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>