Advertisement

Consistent physics at different framerates

Started by November 05, 2015 04:37 PM
10 comments, last by Irlan Robson 9 years, 3 months ago

Hello everyone at gamedev.net,

for a 2d game, I want the user's to be able to change the framerate in their settings (framerate won't change during gameplay tough). However I'm having trouble getting the physics consistent at different framerates. Here is what my main loop looks like:

update()

draw()

remaining = dpf - elapsed

if (remaining > 0)

Sleep(remaining)

The value called "dpf" is the game time that should elapse in one frame. So for 60 fps, it is 1000 / 60 = 16.

Now I drew this out on paper and this is what I think should do the job for physics:

dpfmult = dpf / 16

hacc = hforce / mass

vacc = vforce / mass

hspeed = hforce * dpfmult

vspeed = vforce * dpfmult

xpos += siqnsqrt(hspeed * dpfmult)

ypos += siqnsqrt(vspeed * dpfmult)

The reasoning being that I apply the multiplier twice, hence I take the (signed) square root at the end. Yet this gives me completely different behaviour for 120, 60 or 30 fps.

I also have animations in my game dependent on the dpf valule and those look the same at every fps. So If anyone could take a look at it and check what's wrong that would be great. Thanks!

Fix your timestep

Advertisement

Thanks for the reply. The article seems to be about variable timesteps tough, I just want to enable a few different settings, 120-60-30 fps.

Thanks for the reply. The article seems to be about variable timesteps tough, I just want to enable a few different settings, 120-60-30 fps.


Read through that article in some more detail. What it is suggesting is that you control you physics update and redraws separately. If your framerate drops, you may have multiple physics and logic updates in a single redraw making sure the game continues to update in realtime. If your framerate is high enough, you may render multiple frames per physics update. If that ever happens it is key that your frame interpolation works well, otherwise you would just be rerendering the same consecutive frame.
My current game project Platform RPG

The article seems to be about variable timesteps tough


No, the article concludes that it is best to run physics with a CONSTANT timestep,
and to sync with realtime, you need to run a VARIABLE number of physics iterations per frame.

Example using 1/60 sec timestep fpr physics:
60 fps: 1 x physics per frame
30 fps: 2 x physics per frame
120 fps: run physics onle each 2nd. frame

That means graphics and physics may become out of sync,
then you need to either interpolate actual and old physics positions,
or extrapolate actual physics position with velocity to make it look smooth.
(only for nice graphics - you can care for this later)


But more inportant, your integration seems somehow wrong (or at least misleading / confusing to me).
It should be like:

float accV = -9.81f + body.forceV / body.mass; // example with gravity
body.velocityV += accV * timestep;
body.positionV += body.velocityV * timestep;

EDIT:
If you find Euler integration not 100 percent intuitive, read this about verlet integration:
http://www.pagines.ma1.upc.edu/~susin/files/AdvancedCharacterPhysics.pdf
To me that's much easier, and also it's very stable.

Okay so if I follow the above it would look like this?

elapsed = last - now

while (elapsed > 0)

update(16)

elapsed -= 16

draw(elapsed) // use remainder to extrapolate

Just in theory, not accurately I mean.

Advertisement

Almost. (Changes bold)

Okay so if I follow the above it would look like this?

elapsed = last - now

while (elapsed > 16)

update(16)

elapsed -= 16

draw(elapsed) // use remainder to extrapolate

Just in theory, not accurately I mean.

I've tested it a bit more, one more question tough, shouldn't I keep the remaining time between cycles too?

remain += last - now

while (remain > 15)

update(16)

remain -= 16

draw (remain)

I've tested it a bit more, one more question tough, shouldn't I keep the remaining time between cycles too?


Yeah, that is right
My current game project Platform RPG

This should help you measure correct time values: https://irlans.wordpress.com/2015/11/09/asynchronous-keyboard-input/

This topic is closed to new replies.

Advertisement