Timebased physics

Started by
23 comments, last by JohnBolton 19 years, 7 months ago
Hi, I'm just running into trouble with the physics in my Jump 'n' Run game. All the movements in the game are based on the time of the last frame, so is the gravity. But with the gravity I got the problem, that the simulation runs different on various machines. I think, that's because on a fast machine there are a lot more simulation steps calculated than on a slow one. For example I do jumping in my game by just setting the vertical velocity to a negative value. Then gravity is applied to the object every frame. On my computer the height of the jump is just right, but on a slower machine the player doesn't jump high enough. Any idea, how I can solve this problem? thx, fallen
Advertisement
The solution to the problem is to use frame-rate-independent physics steps. Search the forum archives for keywords like "physics time step" and you should find several good old threads.

The basic idea is that you always use a constant time step, say 1/100 second, for your physics updates. Then, during the game, you do NOT update physics during a frame UNLESS more than 1/100 second has passed. When you do a physics update, you do as many physics updates as needed to catch up. Pseudo-code looks like this:

pts = physics time step = 0.01;accumulated_frame_time = 0.0;for (each frame){  accumulated_frame_time += current_time - previous frame time;  while (accumulated_frame_time > pts)  {    DoOnePhysicsStep(pts);    accumulated_frame_time -= pts;  }}


That way, every time you render a frame, your physics will catch up, and the solution will be perfectly repeatable (for the same number of physics steps) on ANY machine. Now, you may be doing more than one physics step per frame, and there may be frames where you do zero physics steps, but you can be assured that the physics results will be machine independent.
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
I have got problems of the same nature, in my case I have a constant acceleration: when it takes very short to render a frame, the new speed is calculated more often and the object moves faster over a set amount of time. But when it takes long to render a frame, the new speed is not calculated very often, and the object moves only a smaller distance at that same time.

So, if someone could help us out (same kind of problem), thanks beforehand. If the problem is not the same as the TS, please ignore this post, I'll start a serperate thread then.

--
Sijmen Mulder
That is very good advice, thank you. That solves the issue(s)!
this is how you should do it if you are not already doing it like this for each frame:

acceleration = gravitational_constant (e.g. -10)
velocity += acceleration * frametime
position += velocity * frametime

[Edited by - SpaceDude on August 27, 2004 4:01:28 PM]
Quote:Original post by SpaceDude
this is how you should do it if you are not already doing it like this for each from:

acceleration = gravitational_constant (e.g. -10)
velocity += acceleration * frametime
position += velocity * frametime


That solution is not indipendent of the framerate, as I explained above.
Thank you, works fine! :-)
But this would only be necessary for accelerated movements, right? When the velocity stays constant, I can simply do the movements by adding speed*time to the position?!
Yes. [grin]
Quote:Original post by SpaceDude
acceleration = gravitational_constant (e.g. -10)
velocity += acceleration * frametime
position += velocity * frametime
This is a common mistake. The problem is that there is some error and the amount of error depends on the frame rate. If you don't want to use a fixed time step (as suggested by grhodes_at_work), the following will give you the exact results for motion with constant acceleration (i.e. gravity).
t = duration of the last framea = accelerations = current positionv = current velocitys += v*t + 0.5*a*t*t;v += a*t; 
Note: the order of execution is important -- the old velocity is used to compute the new position.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
Or you could just multiply all your values by a function which returns the number of seconds passed (it would need to be a float) from last frame to this one. Then make all your values per second.
"Learn as though you would never be able to master it,
hold it as though you would be in fear of losing it" - Confucius

This topic is closed to new replies.

Advertisement