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.

Using delta time with addition and subtraction is easy.

player.speed += 100 * dt

However, multiplication and division complicate things a bit. For example, let's say I want the player to double his speed every second.

player.speed = player.speed * 2 * dt

I can't do this because it'll slow down the player (unless delta time is really high). Division is the same way, except it'll speed things way up.

How can I handle multiplication and division with delta time?

Edit: it looks like my question has confused everyone. I really just wanted to be able to implement deceleration without this horrible mass of code:

else
    if speed > 0 then
        speed = speed - 20 * dt
        if speed < 0 then
            speed = 0
        end
    end
    if speed < 0 then
        speed = speed + 20 * dt
        if speed > 0 then
            speed = 0
        end
    end
end

Because that's way bigger than it needs to be. So far a better solution seems to be:

speed = speed - speed * whatever_number * dt
share|improve this question
3  
What are you trying to accomplish? –  Justin Skiles Oct 7 '12 at 15:12
    
I want to have the player decelerate without having to use a bunch of if statements. –  tesselode Oct 7 '12 at 15:19
    
Are you wanting to accelerate and decelerate exponentially every time? You seem somewhat confused about what you're asking since you say you want to double the speed every second, but your code shows doubling the position. –  Byte56 Oct 7 '12 at 17:03
    
Yeah, I want to change the speed, not the position. Fixed. –  tesselode Oct 7 '12 at 17:16
2  
possible duplicate of Friction in 2D game –  Byte56 Oct 7 '12 at 18:27
add comment

5 Answers

This is where you want to use a little more physics than just modifying the position by some constant value. Give your player a velocity and an acceleration. Then, when you update you can do this:

player.velocity += player.acceleration * dt;
player.x += player.velocity * dt;

Then it's a simple matter of making the acceleration 0 to maintain a constant velocity, or you can make it a positive number to increase velocity or a negative number to decrease velocity.

If you want to "decelerate" just just a negative acceleration, that's all friction is. Friction is just another force like accelerating.

share|improve this answer
    
+1 but I was struggling a little bit to answer the sub-question (how to double speed every second) - I can't find a way to exactly double the speed every second, given only delta_time elapsed and current speed! –  Markus von Broady Oct 7 '12 at 16:03
    
You would use an exponential function for the acceleration to double the speed every second. I'm not sure if OP actually wants that. It will get out of hand quickly. –  Byte56 Oct 7 '12 at 16:05
    
I guess I need to go back to school. –  Markus von Broady Oct 7 '12 at 16:06
    
The OP seemed to be talking about doubling the position every second anyway (player.x = player.x * 2) Which would get out of hand even quicker, exponentially quicker. –  Byte56 Oct 7 '12 at 16:08
    
He 'wanted' (because I also think he doesn't need that) to double his speed, not position every second, and he wanted to base it on delta_time! I find the problem hard without storing some "oldSpeed" value, refreshed every second. –  Markus von Broady Oct 7 '12 at 16:12
show 1 more comment

In these cases you should use exponential functions instead of a normal multiplying. meaning :

player.velocity.x = player.velocity.x * pow(CONSTANT_FACTOR, dt);

It's pretty simple to explain why: when write player.velocity.x += CONSTANT * dt, assuming your game is running @60fps you are adding CONSTANT * 1/60 to velocity 60 times per second, meaning in each second your speed will increase by CONSTANT * 1/60 * 60 = CONSTANT.

Now you want playing velocity to get twice or three times every second, so after one second you'll have new_velocity = old_velocity * CONSTANT you can break this into smaller multiplications and write

new_velocity = old_velocity * CONSTANT ^ (1/60) * CONSTANT ^ (1/60) * ... 
             = old_velocity * CONSTANT ^ (1/60 * 60) 
             = old_velocity * CONSTANT ^  1 = old_velocity * CONSTANT

which means in each frame you need to multiply velocity by CONSTANT^dt

EDIT

Based on the edits the edits you made in your question, you don't really need to implement this exponential method. Assuming you are going to simulate friction, you can also implement more physical method:

Physically friction reduces speed by linear manner, assuming Object mass doesn't change over time. It's applying a force to the object, exactly in opposite direction as object's current velocity. For example let's assume Friction always reduces speed by two units every second, you need to find velocity's current direction, reverse it, and reduce a vector of length two in that direction multiplied dt. here is some code to help you understand:

Velocity_Direction = Velocity / Length(Velocity)
Friction_Power = 2
Friction_Direction = -Velocity_Direction
New_Velocity = Old_Velocity + Friction_Direction * dt

there is one small little thing that you might want to notice, by that code if speed is too low, the Object will jitter in it's position. That's because Fricton_Direction * dt is bigger than velocity itself, which will lead to object moving exactly in opposite direction in the next step, instead of standing still. to fix that you need to add an if statement to check if Velocity is too low and Object should be completely stopped. I'll do it like this:

Friction_Power = 2

if(Length(Velocity) > dt * Friction_Power)
    Velocity_Direction = Velocity / Length(Velocity)
    Friction_Direction = -Velocity_Direction
    New_Velocity = Old_Velocity + Friction_Direction * dt
else
    New_Velocity = Vector(0)

note that Length is a function which gets a vector as an input and returns it's length. for example if your game has a 2d world Length (Velocity) = Sqrt(Sqr(Velocity.x) + Sqr(Velocity.y))

share|improve this answer
    
+1, it works! v *= Math.pow ( 2, dt ); to double the speed every second (dt is fraction of a second) –  Markus von Broady Oct 7 '12 at 17:43
add comment

Without reading more into your question and answering your question as is, this is a simplification of your code:

speed = (speed>0)?MAX(speed - 20 * dt, 0):MIN(speed + 20 * dt, 0)

But as others have stated, to achieve a more realistic (i.e. Newtonian) result, you should implement an "acceleration" variable and update your entity like so:

position = position + velocity * dt + acceleration * dt * dt * 1/2
velocity = velocity + acceleration * dt

Here velocity would be (presumably) your "speed" variable. (If I recall correctly from physics, "speed" is technically ABS(velocity), therefore should be always >= 0)

share|improve this answer
    
Very good answer +1 –  Arthur Wulf White Oct 8 '12 at 6:50
add comment

As others have noted, the correct formula for deceleration due to dry friction is

velocity += constant * dt * -dir( velocity )

where dir(v) returns a vector of unit length pointing in the same direction as v. (For one-dimensional movement, dir(v) = 1 if v > 0 and dir(v) = -1 if v < 0.) One way to calculate it is as

dir(v) = v / abs(v)

where abs(v) gives the length or magnitude of the vector v.

To keep objects from jittering after they come to a stop (and to avoid dividing by zero if we try to calculate the direction of a prefectly stationary object), we should also ensure that the change in velocity never exceeds the original magnitude of the velocity — that is, friction should never cause an object to start moving backwards. Putting all this together, a reasonable implementation of friction in a game is:

friction = constant * dt;
speed = abs( velocity );
if ( friction < speed ) {
    delta_v = friction * -( velocity / speed );
} else {
    delta_v = -velocity;    // the object stops, or was stopped already
}
velocity += delta_v;

Note that this works even if the object is moving in more than one dimension, so that velocity is a vector. (Of course, the actual code for doing this with vectors might look somewhat different, depending on what notation your language uses for vector arithmetic.)

You can add other velocity changes before or after this code; if you add them before, then small enough forces may be completely canceled by friction, which is actually realistic. In fact, for further realism, you may want to implement static friction by having the constant in the friction calculation vary depending on whether or not the velocity of the object was non-zero at the beginning of this timestep.

Also, if you want to be really accurate, you should take acceleration during the timestep into account when updating the object's position. That is, instead of just doing

velocity += delta_v;
position += velocity * dt;

you should do

velocity += delta_v;
position += ( velocity - delta_v / 2 ) * dt;

where velocity - delta_v / 2 is the average of the velocities before and after adding in delta_v.

This latter approximation to Newton's laws of motion is actually exact as long as acceleration = delta_v / dt is constant, and in any case is a better approximation than the former even for changing delta_v. However, for games with a small and constant timestep dt, the difference is generally not noticeable, at least without side-by-side comparison. The main advantage of the more accurate form is that it makes object trajectories less sensitive to changes in dt.

I should also point out that (dry) friction is not the only force that can slow down moving objects. For example, objects moving through water or air experience drag, which follows a formula that generally looks something like

delta_v = ( a * speed + b ) * -velocity * dt

where a and b are constants that depend on a lot of things such as the density and viscosity of the fluid and the mass, size and shape of the object moving through it. (See the Wikipedia link above for details; a above corresponds to Newton drag, while b corresponds to Stokes drag.)

For macroscopic objects moving through fairly inviscid fluids like water or air, b should be very small or even zero, whereas a viscous fluid like lava or molasses calls for a higher b. For game purposes, just play around with the values until you get the effect you want.

Note that, unlike with dry friction, drag forces never bring a moving object to a complete stop, so we generally don't need to worry about accidental direction reversals. The exception to this is if (a * speed + b) * dt > 1, which can happen if dt is too large or if the object somehow acquires an unusually high velocity; if that might happen, the solution is either to dynamically adjust dt to be smaller for fast-moving objects or to use a higher-order motion integrator (which really goes beyond the scope of this post).

share|improve this answer
add comment

To make that code shorter, you could do the following:

//define a constant somewhere in your code so you could adjust the value later
DECCELLARATION_RATE = 20;
//Checks if the speed is positive or negative so we will decrease it's absolute value:
sign = (speed >= 0? 1 : -1);
//Decrease the absolute value of the speed while maintaing it's sign
speed -= sign * DECCELLARATION_RATE * dt
//If the object is moving too slowly, the above command will change the speed's sign and with it the direction of the movement. 
//What we want to do is stop the object in this case.
if(sign != (speed >= 0? 1 : -1)) speed = 0;

The operator (condition ? value_if_true : value_if_false ) is called the ternary operator. You can read about it more here:

http://en.wikipedia.org/wiki/Ternary_conditional_operation

share|improve this answer
    
1. you answer only works for 1D world. 2. in case we assume OP wanted 1D answer both me and Byte have already given this answer. –  Ali.S Oct 7 '12 at 19:23
3  
The link you gave is goes to the generic page about question marks. Why is your answer spending more space explaining ternary operators with absolutely no explanation of your movement code? –  Justin Skiles Oct 7 '12 at 19:33
    
@JustinSkiles Thanks, I fixed the link. He asked how to make his code short and simple, I offered a tool called a ternary operator. I'm guessing the OP is not familiar with it so I explained what it does in detail. I edited the answer to add some comments explaining the code itself. I thought it was very short and pretty clear once your know what a ternary operator does. –  Arthur Wulf White Oct 7 '12 at 19:42
    
@Gajoo All the things you wrote do not change the fact that 1.this answer is suitable for manipulating the x-axis speed in a 2D platformer game. 2. It matches the edited question perfectly. 3. You most likely downvoted Byte56 originally and myself now because of being competative. None of your explainations show why this answer is less useful when considering the question. In addition the last part of your answer deals with the exact same suituation. So you must think it's somewhat useful. –  Arthur Wulf White Oct 7 '12 at 20:32
2  
+1 it may be not the best answer, but it shows the solution in a different way, and therefore is a positive input not deserving -3 for sure. –  Markus von Broady Oct 7 '12 at 21:08
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.