[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Of time scaling and FPS

Steve Baker wrote:

> "Miguel A. Osorio" wrote:
>>Hey people,
>>        I have some matters about time scaling and a little FPS problem I'm
>>having on my project to discuss. About time scaling, just to make sure,
>>the correct way to calculate one frame time could be:
>>// Main loop - no time scaling
>>        get_input()
>>        update_states_and_variables()
>>        render()
>>        The calculation I'm talking about would be something like:
>>// Main loop
>>        tf = gettime()
>>        delta = tf - ti
>>        ti = gettime()
>>        get_input()
>>        update_states_and_variables() // Use delta here on time dependent
>>        render()
>>        Is this one right way to do it?
> That's one way...so all of your equations for motion say things like:
>    position += speed * delta ;

(a lot of text cut out here)

> However, for some genre's of game, this is the way to go because as the
> programmer, you have better control.  For example, if you have a character
> that jumps - then with the first approach, the *exact* maximum height
> he'll reach will depend to some slight degree on the update rate of your
> graphics...not by much - but enough that if you've *carefully* designed the
> scene so that he has to jump *just* right to land on some platform - then
> on some computers the jump will be easy and others it'll be impossible.
> Without a boatload of testing and annoying tweaking of initial accellerations
> and stuff, it'll be a pain.

You could heavily decrease that error with a little mathematical 
sophistication. The point is that you are numerically integrating a 
differential equation (although it's a simple one). That does give you 
errors in any case. But the error you get heavily depends on the method 
you chose to integrate.

The method you presented above is the Euler-Couchy method which is easy 
to understand and actually very poor. It may not even be the fastest out 
there, but that's just my guess right now.

One of the more sophisticated methods to do the job is Runge-Kutta. It's 
still rather simple and comes in several dozens of variants which vary a 
little bit in their calculation effort and precision. Best thing would 
be that you get a good book on numerical mathematics before you try 
that. One that's currently in my bookshelf is William H. Press et al., 
"Numerical Recipies in C", but one thing I don't like about it is that 
the code examples are very obfuscated in fact. You can also have a look 
at their website: http://www.nr.com

Basically Runge-Kutta may look as being more expensive, but you can 
savely play some tricks on them like adaptive step size without having 
to loose precision (in fact adaptive step size is used to *gain* 
precission, but to small a stepsize will kill too much performance). And 
besides, if you integrate using a different step size than you have in 
your rendering loop you will need an additional interpolation step, 
though. In terms of efficiency that's comparable to Euler-Cauchy.

So it all boils down to trading speed for precision. But that's not to 
far off reality in game programming. Just have a glance at what ODE 
does, and simulations like that run in realtime even in games. I'm 
mentioning that example only because it shows that the calculation time 
can be there if it is done right.

> My TuxKart game works the first way - and on slow machines, I get bad
> problems with collision detection and the way one object richochets
> off another - Karts keep driving through walls and stuff like that.
> It's a real pain to fix it.  I wish I'd implemented it the second way.

It's very tricky to get right indeed. The point is that you *never* 
(even with fixed step sizes) get the exact moment in time when the the 
objects start to touch each other. Normally you'll first get a hint of 
the collision when the objects already interpenetrated each other. And 
that's where the trouble starts because you have to correct that in your 

  You might even totally miss collisions (like it seems to happen with 
the karts that go through walls). That happens with a step size that's 
far too big meaning that you will get positions of your objects before 
and after the collisision at times they are totally seperated from one 
another. So the simulation has no hint that the collision has taken 
place. The normal way to handle that is to limit the step size to do the 
integration with (yes, we're still talking about the same thing as 
above) to a value that guarantees that you won't miss any collisions. 
That value of course depends on the speed your objects are traveling 
with and their size (you even might determine that value dynamically to 
avoid wasting time with making small steps when they aren't needed).

> There is a third way - pick an update rate that all reasonable computers
> can manage - and slow all faster machines to that rate.  Anything that
> can't make your minimal performance is declared "too slow to run this
> program".  Now you don't need any time code at all - everything can
> just be hard coded.  My original TuxAQFH game works that way - and it's
> great!  You don't get 200Hz frame rate on a GeForce-4 ti 4600 - in fact
> you get the exact same speed as you get on a Voodoo-2 - but it's plenty
> fast enough to be playable - and it's a lot easier to write - so why would
> you care?  In fact, you could even adjust the amount of detail you render
> to keep the frame rate around your nominal rate so that you'd get nicer
> graphics on a fancy modern card.

Seen from a mathematical point of view this one is very similar to the 
second method you proposed. The only thing here is that you also couple 
rendering with your simulation. One pitfall here is that the simulation 
might become inacurate if you are choosing to large a step size (steps 
of 10ms+ are large steps).


PS: Before you tear me apart: I know that I'm not that wrong except for 
the parts in which I mention things about calculation costs. So, if you 
feel like attacking anything, try that first :) [hm... maybe I shouldn't 
provoke you like I managed to do the last time on that dl* stuff - sorry 
for that!]

* Gregor Mueckl                 GregorMueckl@gmx.de *
*                                                   *
* The ChallengeOS project:                          *
* http://challengeos.sourceforge.net                *
* Math problems?                                    *
* Call 1-800-[(10x)(13i)^2]-[sin(xy)/2.362x].       *