How can I implement framerate-independant updates?

Edit: I fixed the problem by making jumpvelocity the one that is modified and added onto, and yvelocity just equal jumpvelocity * t. This is what I have right now:

if (GUI->Space && grounded){
jumpvelocity = -185.f * 2  / gravity;
grounded = false;

}

if(!grounded ){
if(jumpvelocity < terminaly){
jumpvelocity += 185.f * t * 4  / gravity;
yvelocity = jumpvelocity * t;
}
else{
jumpvelocity = terminaly;
yvelocity = jumpvelocity * t / gravity;
}
}
else{
yvelocity = 0.f;
jumpvelocity = 0.f;
}


Thanks for the help.

I am trying to get my gravity to work. The code I have so far is

if (jumpvelocity < 0){
yvelocity = jumpvelocity * t *2/gravity;
jumpvelocity += 185.f*t * 2 / gravity;
}

else if(!grounded ){
if(yvelocity < terminaly)
yvelocity += t / gravity;
else
yvelocity = terminaly;
}


Gravity scales upwards, the higher making falling and jumping slower. It's default value is 1. Jumpvelocity is set to 185 when the player wishes to jump. My problem is that you fall slower at a slower framerate, but you jump at the same speed as if it was a higher framerate. How would I make it frame independent? T is delta time.

• Can you show the code where Velocity is used to modify position? Oct 18, 2011 at 5:42
• So, re your comment... what's the problem? It works exactly the same way for x and y. Oct 18, 2011 at 17:54
• I'm using SFML so it's just you.Move(xvelocty, yvelocity). Oct 18, 2011 at 19:43
• Your updated code still has absolutely all the problems I pointed out. You are not averaging jumpvelocity with its previous value when updating yvelocity, giving you an accuracy error that will get worse at lower framerate. What you call yvelocity should actually be ymovement since it's a velocity multiplied by time. You are updating jumpvelocity when the character no longer touches the ground, which has no physical meaning. Your check for terminaly is done before updating, causing jumpvelocity to be greater than terminaly and worsens at lower framerates. Oct 19, 2011 at 11:27

On each main loop iteration:

1. Check your system timer and store as currentTime (eg. SDL_GetTicks())
2. timeDelta = currentTime - lastTime
3. Convert timeDelta to seconds (usually it's in ms or ns), store as timeDeltaSeconds
4. For each entity in entities: entity.position = velocityInUnitsPerSecond * timeDeltaSeconds
5. lastTime = currentTime (could also be done before step 1 instead of here)

...You will need to adjust your current numbers to be in units per second, i.e. so that they would make sense at 1FPS. For example, if you expected your character's horizontal velocity to be 2 pixels per tenth of a second, then you now need to set it as 20 pixels per second. That way, the above will work out correctly.

For some applications, it is better to fix your timestep to a given amount. In this case, timestep != timeDelta. The latter is the amount of system time that has actually passed; the former is a quantised amount you want to consume from your time accumulator each time you apply logic updates in your game. This assists integration when you are using iterative solvers like those found in the well-known physics engines, because timesteps must be equal when doing the calculus. In this case, because you are not simply using up all of the time you have remaining on each tick, you will have fractions of time left over, and you need to accumulate these for use in later ticks. For more about this, read Fix Your Timestep by Glenn Fiedler.

• Op here, sorry I'm not sure how to respond to an answer, but I already have a timestep set into place which is 1/60th of a second or lower depending on the value returned. My xvelocity works well, and is frame independent (200.f * t), but my yvelocity is not. Oct 18, 2011 at 17:29
• You do not want velocityInUnitsPerSecond but the average velocity during the elapsed timeframe. If velocity is constant, then your code is correct. If velocity varies linearly, as is the case with gravity, then that value is 0.5 * (OldVelocity + NewVelocity). Otherwise, you may need to integrate over a smaller timestep in order to avoid accuracy issues. Oct 18, 2011 at 19:57

It does not seem that jumpvelocity is needed at all. Jumping means instantly setting velocity to a given value: once the feet no longer touch the ground, the only thing that can change velocity is gravity (and air resistance, that you implement using terminal velocity).

Another remark: floating point divisions are extremely slow. I suggest you store 1.0f / gravity instead of gravity.

Finally, there is a possibility that for one frame yvelocity can be larger than terminaly.

My suggestion:

if (GUI->Space && grounded) {
yvelocity = 185.f;
grounded = false;
} else if (!grounded ) {
yvelocity += t * inv_gravity;
if (yvelocity > terminaly)
yvelocity = terminaly;
}


And remember that the following is not accurate:

ypos += t * yvelocity;


You need to do:

ypos += t * 0.5f * (old_yvelocity + yvelocity);