From Tue, 27 Mar 2007 09:51:25 -0600
Scott Harper wrote:
But what of situations where, say you have a platformer and the
designer wants to put in some wicked hard jumps that are timed
exactly to you have to do it JUST right in accordance to your
avatar’s jump height and timing.
What’s wrong with passing the delta time to all functions that
calculate the distance at which your sprite moves etc?
Yes, computing 3D physics is one of the places where precision is
required. But limiting the framerate actually helps the physics (and
not just the physics but most other computation algorithms) to be more
accurate: instead of doing 10 computations with 0.001sec interval
you’re doing just one computation with a 0.01sec interval.
There’s a catch here with the physics though: if you limit your FPS too
low (say 25FPS) an object could penetrate deep inside an obstacle if
it’s moving too fast (and perhaps even punch it through). So maximal
FPS should be adequate for the speed of the objects in the game.
How would you accomplish this on a system which cannot guarantee
a given framerate?
Yep, that’s why I’m passing the actual time between the previous and
current frame to the computation logic so that it can take that into
account.
Or what if the OS decides to be a process hog for the precious few
milliseconds where you would reach the summit of your jump, crest the
platform, and safely land on it?
This kind of errors could be compensated by not invoking the game logic
with deltas longer than some period. For example, if you set the
max FPS to 50 and min FPS to 10 your game logic will be never called
with time intervals larger than 100 milliseconds. If the delta between
two frames happens to be longer, game logic should be called twice.
By the way, I have reviewed the code I posted before and found some bad
bugs in it - sorry, I wrote it in a hurry. Here’s a fixed version,
with the MinFPS setting:
ulong CurrentTime = GetCurrentTime ();// in milliseconds
ulong PreviousTime = CurrentTime; // the time of the previous frame
ulong NextTime = CurrentTime; // the time of the next frame
ulong NextFrac = 0; // the fractional part of NextTime
int MaxFPS = 50; // top FPS limit
div_t MinFrameLen = div (1000, MaxFPS);// quotient and remainder
int MinFPS = 10; // bottom FPS limit
int MaxFrameLen = 1000 / MinFPS; // No need to have it too precise,
// so no fractional part
while (…)
{
long delta = CurrentTime - PreviousTime;
// Don’t allow update_game to be called with too long intervals
while (delta > MaxFrameLen)
update_game (MaxFrameLen), delta -= MaxFrameLen;
if (delta > 0)
update_game (delta);
// Now display whatever we computed
display_game ();
PreviousTime = CurrentTime;
CurrentTime = GetCurrentTime ();
NextTime += MinFrameLen.quot; // this is the integer part
NextFrac += MinFrameLen.rem; // and accumulate the remainder
// carry the remainder overflow into the integer part
while (NextFrac > MaxFPS)
NextTime++, NextFrac -= MaxFPS;
// have a good sleep if we're running too fast
delta = NextTime - CurrentTime;
if (delta > 0)
Sleep (delta);
// drop frames if we're running too slow
else if (delta < -100)
NextTime = CurrentTime, NextFrac = 0;
}
There’s a catch here that the MinFPS is limited somehow by the computer
speed: if the computer is SO slow that it cannot even run game logic
with MinFPS, the application will run slower then slower then slower and
will finally freeze. If you really want to take into account such slow
computers, there can be additional workarounds implemented.–
Andrew