Fixed Time Step and Box2D

Hi,

I am struggling to implement a fixed time step and a box2d based world in my game.

Specifically I am referring to this article on fixed time step: http://gafferongames.com/game-physics/fix-your-timestep/

I found this implementation: http://plaincode.blogspot.com/2012/05/fixed-timestep-in-cocos2d-x-with-box2d.html

I am trying to implement physics based jumping using box2d.
Trying out my world with two different fixed time steps, 0.1 and 0.05 seconds, my player’s jump height is noticeably different.

This is the simplified jump logic:

if(this->isJumping() && this->hasContactBelow()) { 
    float desiredVelocity = 25.0f;
    float velocityChange = desiredVelocity - currentVelocity.y;
    float impulseY = this->body->GetMass() * velocityChange;
    this->body->ApplyLinearImpulse(b2Vec2(0, impulseY), this->body->GetWorldCenter());
}

Alternatively, I’ve tried setting the velocity directly

this->body->SetLinearVelocity(b2Vec2(currentVelocity.x, 25.0f));

In both cases, depending on which fixed time step I use, the player jumps to a different height.

I’ve tried the linked implementation above, but was seeing bad results. I am a bit confused on how to properly implement the partial render step.
In the implementation above at plaincode.blogspot, they are calling the world step AFTER the manual positioning of the world bodies and attached Node objects.
When I tried that I was seeing the b2Body shake back and forth with the Node positioning lagging behind an iteration.

When I tried moving the world step BEFORE the calls to renderFullStep(), the shaking was gone, but my issue with the variable jump height between fixed time step values was still present.

The best I have currently is simply this:

void GameLayer::update(float dt) {
    _accumulator += dt;
    while(_accumulator > fixedTimeStep) {
        _accumulator -= fixedTimeStep;
        this->_world->Step(fixedTimeStep, 8, 1);
        playerNode->update(fixedTimeStep);
    }
}

Any help is greatly appreciated,

Thanks

2 Likes

In any fixed time step physics simulation, the actual height of the jumper will vary. Why? Because you are not using continuous physics.

At t=0, jumper is at h=0
At t=2, jumper is at h=2
At t=4, jumper is at h=4
at t=6, jumper is at h=f(6) where f(6) < fmax
at t=8, jumper is at h=f(8) where f(8) < fmax

why? fmax occurred at t=7, and your simulation never touch time index 7.

This is also the bullet problem. Why did my bullet not hit the opponent! Well, because again not using continuous physics and so the time of impact is never “touched” during the update loop, so no collision is ever recorded.

Player |- - - - - - - - [opponent] - -* bullet
t= 0 1 2 3 4 5 6 7

Collision occurs at t=5.5, but your loop never hits t=5.5, so no bullet collision and you have lots of angry players.

Make sure you have continuous physics enabled and lock your time step with the update interval of your game processing engine.

Hi,

thanks for the reply.

When you say “lock your time step with the update interval of your game processing engine”, do you mean use a fixed time step equal to the FPS I am setting (i.e. pDirector->setAnimationInterval(1.0/60)) ) ?

I thought that rationale behind using a fixed time step, that the FPS and physics sim could operate independantly under different update intervals.

Yes, FPS = box2d update interval, or whatever you have set as your scheduler’s update interval for the director.

If you want real physics simulation to match your game draw and experience then you need to lock the two time steps.

otherwise, if you have passive physics, like background stuff falling, then you can get away with a more coarse physics time step. That’s where you would have multiple box2d worlds, if such a thing were possible ……. hmmmm - might need to get on twitter and poke Erin about that.

Any player/collision physics MUST be run on your update fps (or finer). Otherwise, you will get the bullet failure I mentioned above.

Ok thanks.

Excuse my ignorance though (I am still ramping up on game development)… but setting the FPS is only what my idea update interval is scheduled to be in cocos2d-x. It potentially will fall below that under heavy processing though, correct?

In that case would not my box2d timestep fall out of sync with the cocos2d update rendering?

I guess what I am asking, would the update logic look like so (as my current “fixed time step” implementation is):

void GameLayer::update(float dt) {
    _accumulator += dt;
    while(_accumulator > fixedTimeStep) {
        _accumulator -= fixedTimeStep;
        this->_world->Step(fixedTimeStep, 8, 1);
        playerNode->update(fixedTimeStep);
    }
}

or would I simply call the box2d step each time my layer update is called like so?

void GameLayer::update(float dt) {
    this->_world->Step(dt, 8, 1);
    playerNode->update(dt);
}

Thanks for the help

You can’t do “catch up” on your physics or else you will lose collisions.

A real physics simulation requires a bit more code work because you will need to use the predictor capabilities of the physics engine to know if one object “would have” collided with another object, so you can back trace and process the collision while your draw() experience is still bogged down.

void GameLayer::update(float dt) {
*accumulator += dt;
while {
*accumulator = fixedTimeStep;
this
>_world~~>Step;
playerNode~~>update(fixedTimeStep);
}
}

Yes, do this, but you need to process your physics during this accumulation rundown.