Jump to content
  • Advertisement
Sign in to follow this  
tonyp7

Handling timing+physics properly

This topic is 4334 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys, I've been starting a small game, kind of old 2D space shooter. My problem is that I'm currently using a 15ms delay between each update of the game state, but I'd like to move to a more precise timing. So far, I have a spaceship that can move (method update), this method is called every 15ms and checks if the user is using throttle and other inputs like turning left, update the position of the spaceship and go on. I'd like to know how to change my code to use the: speed = distance/time equation. I can compute the time between each frame, but what about the speed? How could I know it? Currently 3 forces are applied to the spaceship: gravity, frictions and a force in the direction of the ship if the user is using throttle. This give me a resulting force, but how can I translate this into a "speed"? I don't know if I'm explaining well, so anyway I uploaded my code (C# MDX, only the starship class will be useful http://xboxemul.free.fr/dotnet/spaceship.zip) so maybe one of you can take a look. Cheers, Tony

Share this post


Link to post
Share on other sites
Advertisement
Simply stated, a = F/m, when means acceleration equals force divided by mass.

Acceleration is the derivative of velocity, so to find the velocity, you integrate the acceleration. Now, it probably isn't possible to integrate the acceleration analytically in your case, so you must do it numerically. Numerical integration isn't exact, but it is usually close enough. There are several numerical integration algorithms. The simplest (and least accurate) is called Euler integration. Every frame, you simply do this: v = v + at, where v is the current velocity, a is the current acceleration, and t is the amount of time since the last update. v and a can be scalars or vectors.

Since velocity is the derivative of distance, you can do the same thing to find the position every frame: s = s + vt, where s is the current position, v is the current velocity, and t is the amount of time since the last update. Again, s and v can be scalars or vectors.

If you have problems with the accuracy, you might consider using a better (and more complicated) integration algorithm such as Verlet or Runge-Kutta.

Share this post


Link to post
Share on other sites
I recommend not letting the passage of real time affect your game logic. If your game is being updated at close enough to every 15 ms, that is good enough. Old style games did not use variable update times, and even new games usually don't.

Share this post


Link to post
Share on other sites
Quote:
Original post by JohnBolton
<snip>


Great answer. I'm gonna give this a try.

Vorpy> Well 15ms is a fairly good timing of course, but I'm not happy with it. The game still computes 5/6 frames between those timings, and well if you compile the code, you can see it's a little bit choppy when you move fast enough. I'm not happy with it.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by tonyp7
I'm not happy with it.


15ms resolution for Physics calculations should be fine.
Perhaps the choppiness you see, is not the Physics itself, but an issue with the Graphics and rendering updates?

Generally, while you keep your physics calcs at a fixed interval, the graphics will occure at their own different rate as well; either locked to the monitor refresh rate, or operating as fast as possible

If those rates and your physics rate happen to have a 'beat frequency' you can get some very ugly choppiness problems. Happened to me once...

Share this post


Link to post
Share on other sites
Here's the code that's currently handling the timing:

// Update time elapsed since last frame
m_timeElapsed = (float)(m_currentTime - m_lastTime) / (float)m_ticksPerSecond;
m_runningTime += m_timeElapsed;
//if 15ms is reached, game is ready for a new turn
if (game_ticks_counter >= 0.015)
{
game_ready = true;
game_ticks_counter = 0;
}
else
{
game_ready = false;
game_ticks_counter += m_timeElapsed;
}


Instead of game_ticks_counter = 0, you should use game_ticks_counter -= .015. That will get you closer to your target number of updates per second.

You can also smooth out the graphics without affecting the game logic/physics. I think your current code always draws the same thing between updates. There's no point in drawing the scene multiple times if it looks the same each time. You're getting several redraws per second because your game isn't doing much work right now. You also might be getting some ugly screen tearing if your redraws aren't v-synched, and no update method can fix that (besides v-synching).

Share this post


Link to post
Share on other sites
Quote:
Original post by Vorpy
Instead of game_ticks_counter = 0, you should use game_ticks_counter -= .015. That will get you closer to your target number of updates per second.


Good point. I don't know why I haven't thought of it.

Quote:
Original post by Vorpy
You can also smooth out the graphics without affecting the game logic/physics. I think your current code always draws the same thing between updates. There's no point in drawing the scene multiple times if it looks the same each time.


Well that's the problem. Each 15ms, the scene moves, then several draws are being done but there are indeed the same thing until another 15ms is reached.
Between those 15ms, if a vertex moves from point A to point B, it would be of course nice to use the time between the 15ms to smooth the movement, instead of brutally moving from A to B, but I don't know how to achieve that.

You are really of a great help. I wouldn't expect some people to actually take the time to explain me those basic things (I have read some timing articles though...). Thanks a lot.

Share this post


Link to post
Share on other sites
you want to look at linear interpolation. A big word, but basically, if you want to move from A to B, with a fraction u,

P(u) = A + u * (B - A), 0 <= u <= 1.

The trick is to calculate 'u'.

Say A was computed at frame 'ta', and B at frame 'tb', and you are at time 't', t in range [ta, tb].

u = (t - ta) / (tb - ta);

however... Doing it like that, you would require to run the rendering 'behind' a little bit, so that when you render, you always have a 'B' position for your object, else you have to extrapolate.

u = ((t - frame_time) - ta) / (tb - ta);
u = max(min(u, 1.0f), 0.0f);

You can use other types of interpolation, such as cubic, or quadratic. But linear should do fine.

That's kind of how interpolation works for some network games (frame_time being replaced by the send_rate), and how player positions are represented on client machines. Running behind also introduces 'lag', which depends on your target framerate.

You can also have less restriction, and use a exponential decay, such as this, to smooth out the transition between the latest calculated physics position and your last rendered position. That also does not require you to cache your physics positions from frame to frame.

RenderPos += (PhysicsPos - RenderPos) * 0.5f;

So every time it is called, the 'gap' between physics and reder positions will be reduced by 2. This is not frame rate independent though. This would be the easiest thing to do to smooth out the rendered position.

It's not very hard to make it framerate independent as well.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!