Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

When you use a fixed time step you can call speed=speed*0.95 to emulate speed deceleration in a simple way.

I want to do the same thing with variable time step.

I wish to have a simple function speed=f(speed,dt); where dt is the time step since last frame.

share|improve this question
add comment

3 Answers

up vote 9 down vote accepted

I would like to make an exact version of David's answer. Since I copied so much from him, I'm making this community wiki.

TL;DR

static float ApplyFriction(float value, float friction, float dt)
{
    return value * pow(friction, dt);
}

Why is it important?

It is often good to make approximations. But approximations are only good when they are good. You should only make approximations when you know their domain of validity.

Using a linear approximation of the above formula, iterating at 60 fps for a 5% speed decrease every second gives you an error under 0.2%.

But what if you want to iterate at 30 fps for, say a 35% speed decrease every second? Then you get an error of more than 20%! Surely that's no longer acceptable.

Explanation

First realize that:

speed = speed * friction;

Is equivalent to (taking some notation liberties here):

log(speed) = log(speed * friction);

log(speed) = log(speed) + log(friction);

Then simply apply the timestep:

log(speed) = log(speed) + log(friction) * dt;

Which is equivalent to:

log(speed) = log(speed) + log(pow(friction, dt));

log(speed) = log(speed * pow(friction, dt));

speed = speed * pow(friction, dt);
share|improve this answer
    
+1 That was very educational. I totally missed that the accuracy of my solution depended a lot on the actual friction value. Thank you for also demonstrating the process behind your reasoning. This is the correct answer. –  David Gouveia Dec 12 '11 at 17:37
    
I hope you don't mind that I filled in a few of the intermediate steps in the explanation. It's just that I had to Google and brush up on my logarithms to follow the entire process, and maybe this will make all the steps more clear. –  David Gouveia Dec 12 '11 at 18:02
    
I'm fine with it. That's why it's community wiki :) –  Sam Hocevar Dec 12 '11 at 18:13
    
Thank you. As pow is a bit slow, here is an approximation that could be used here is yo don't care too much about exact values : martin.ankerl.com/2007/10/04/… –  jptsetung Dec 13 '11 at 6:55
    
@jpsetung: a very interesting article, thanks! –  Sam Hocevar Dec 13 '11 at 8:05
add comment

I'm leaving this post as reference and context for Sam's answer, but you should use his version instead.


TL;DR

Here's your function (in C#) where I took the liberty to add the friction as a parameter instead of hard-coding it:

static float ApplyFriction(float value, float friction, float dt)
{
    return value - value  * (1f - friction) * dt;
}

You might also want to do a speed=Max(0,speed) afterwards.

Explanation

So you'd like speed to reduce 5% per second instead of per frame? That's easy enough to approximate.

First realize that:

speed = speed * friction;

Is equivalent to:

speed = speed - speed * (1 - friction);

Then simply apply the timestep:

speed = speed - speed * (1 - friction) * dt;

While not giving exactly perfect results because the friction is applied as a percentage of the value during each individual step instead of the initial value at each second, in practice the difference is insignificant, as you may check with this sample test:

http://ideone.com/JkJ2I (with 60 evenly spaced frames)

or

http://ideone.com/XKfSw (with an unknown number of variable frames adding up to 1 second)

Where an initial speed of 1000 and a friction value of 0.95 yielded:

  • 950 when applying it with fixed time step.
  • 951.2092 when applying it with variable time step over the course of 60 frames in a second.

That's about 0.1% divergence i.e. they're equivalent for pratical purposes.

share|improve this answer
    
Thanks david. In the sample, we call the variable time step method with always the same time step. I would have make another test to see if it really gives the same results with variable time steps, here it is : ideone.com/XsUB2 –  jptsetung Dec 12 '11 at 9:45
    
Hum, I don't see the point in your change to the sample. The first ApplyFriction method was only there to show the "classic" way of doing it as comparison. –  David Gouveia Dec 12 '11 at 16:09
    
If you want a sample with actual variable timestep here it is: ideone.com/XKfSw . The results are still as good as before. I've edited that test into the answer. –  David Gouveia Dec 12 '11 at 16:21
    
Really, the difference is not insignificant. Check again with 0.55 instead of 0.95, for instance. –  Sam Hocevar Dec 12 '11 at 17:31
    
Indeed, I totally missed that :) –  David Gouveia Dec 12 '11 at 17:38
add comment

If there is a force on an object causing it to decelerate, the deceleration causes a linear-decrease, not exponential:

//Do this every frame - make 'acceleration' negative to decelerate
speed = speed + acceleration

If you want the force to stop when the car stops (like with car-brakes), make sure to constrict speed to being >= 0

share|improve this answer
1  
Using an acceleration does mimic reality more closely, but sometimes the simpler model described is enough to get the desired result. I'm guessing the poster asked it in this way because he wanted to know if he could keep the same model in a variable step context. –  David Gouveia Dec 11 '11 at 18:42
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.