Page 1 of 1

About FPS and dt

Posted: Mon Dec 23, 2013 4:28 pm
by fede0d
Hello everybody. I have some questions about FPS and dt not only on LOVE but on game programming on general.
If I want to move something on the screen and keep constant speed no matter what FPS the game is running on, I have to use something like this:

Code: Select all

x = x + VEL*dt;
Here, if FPS is high dt tends to 0, so VEL*dt is low and tends to 0 (I have to move less on each frame).
On the contrary if FPS is low dt tends to 1, so VEL*dt tends to VEL (I move more on each frame compared to low FPS)

This works ok if I move things by myself. But if I need to apply force on a body in a physics simulation this doesn't work.
I figured out I needed to use:

Code: Select all

applyForce(VEL * (1-dt));
If FPS is high, on each frame I apply more force. And if FPS is low I apply less force on each frame. This seems contradictory, but it works. And I don't know why!
I guess it's something related to the physics simulation, the friction of the body and other things.

Do you know why this is this way? I'm I doing something wrong? How do you manage these things?

[]

Posted: Mon Dec 23, 2013 6:07 pm
by bekey
-snip-

Re: About FPS and dt

Posted: Tue Dec 24, 2013 8:15 am
by ivan

Code: Select all

x = x + VEL*dt;
This works because dt is in seconds and VEL is in meters per seconds.

Code: Select all

applyForce(VEL * (1-dt));
This doesn't look right.
In Box2D, applyForce works with Newtons where the formula is f = mA

Code: Select all

force = mass*acceleration
Where the acceleration = (V2 - V1)/dt

Code: Select all

acceleration = (desired velocity - current velocity)/dt
So your code might look something like:

Code: Select all

-- find the acceleration required to reach a desired velocity
local vx, vy = body:getLinearVelocity()
local cVel = math.sqrt(vx*vx + vy*vy) -- current velocity
local dVel = DESIRED_VELOCITY -- desired velocity
local accel = (dVec - cVel)/dt -- acceleration
-- get the force vector
local mass = body:getMass()
local force = accel*mass
local fx = vx/cVel * force
local fy = vy/cVel * force
applyForceToCenter(body, fx, fy)
This should make your body move at a constant speed which is OK but it's not very realistic.
It is similar to setLinearVelocity except that it won't override the effects of gravity and collisions with other bodies.
The problem with the code I wrote above is that the acceleration of the body can vary A LOT.
Usually, the acceleration should be clamped to a certain value so that your bodies accelerate and decelerate GRADUALLY:

Code: Select all

accel = math.max(accel, -MAX_ACCELERATION)
accel = math.min(accel, MAX_ACCELERATION)
Or you can clamp the "force" variable if you want heavier objects to accelerate slower.
Also, keep in mind that Box2D should be updated with a constant time step to avoid wild behavior in joints; to avoid tunneling and overlap with stacked bodies.

Re: About FPS and dt

Posted: Tue Dec 24, 2013 3:01 pm
by fede0d
Thanks guys! This helped me a lot.