Fixed Rate Game Logic / Position Interpolation

Hello, I am working on porting my game to a fixed rate logic
model. It’s an R-Type style 2D game. I already have a
very playable game with all sorts of SDL goodiess and
effects, but it plays like crapola due to d-time style
sprite position interpolation.

What I am presenting here is two paragraphs of pseudo-code,
the first of which is my d-time model, and the second is
what I have so far in my Fixed Rate Logic model, but I
really don’t know what to do next, so I’d appreciate any
input from anyone! Including you, Mr. Olofson – you seem
to really have this topic down to a science!

I have rendered the following pseudo-code from my actual C++
source.

while(true)
{
check_keys_and_adjust_player_velocity();
/// sprite movement is based on d-time
/// so game runs fine at any framerate
advance_sprites_based_on_dtime();

if(create_new_enemy_timer.has_completed())
{

add_new_enemy();
create_new_enemy_timer.reset();
create_new_enemy_timer.start();
}

// Throttle framerate at 50 fps
// so it doesn’t bog down game logic
// and so it doesn’t cause game to hog
// all of CPU
if(screen.framerate() < 50)
{
screen.clear(BLACK);
background_picture.draw(screen);
sprite_manager.draw_all_sprites(screen);
weapon_and_shield_panel.draw(screen);
Game::mouse.draw(screen);

screen.update();
}

}

So I’m taking this model and trying to make a Fixed Rate
Logic model. This is all I can think of so far:

Uint32 logic_frequency = 100; // 100 Hz

// 1/100th of a second per logic frame
Timer logic_frame_period_timer;
logic_frame_period_timer.set(1 / logic_frequency);
logic_frame_period_timer.start();

while(true)
{

if(logic_frame_period_timer.is_done())
{
advance_game_logic_by_one_frame();
logic_frame_period_timer.reset();
logic_frame_period_timer.start();
}

/// ??? how do I incorporate the game render frame
/// routine???
///
/// ??? what if the game render framerate drops below
/// 30 fps???

}

Should I do my interpolation of sprite coordinates between
logic_frames based on the number of render_frames that
occur between one logic frame?

Or should I interpolate the coordinates based on the average
render_framerate in comparison to the number of
rendered_frames so far in one game logic cycle? If that
makes any sense?

Kindly Appreciated,

Paul Lowe

SITE TEMPORARILY UNAVAILABLE

CONTACT AFFORDABLEHOST.COM

Any ideas?On Saturday 11 December 2004 06:05 am, blynel at mip.sdu.dk wrote:

I didn’t read through your code, but you might consider
a hybrid approach making the modelrate independent of
the framerate:

http://www.jmckell.com/modelrate.html

The framrate can then vsync which should give you the
best result. If the modelrate is higher than the framrate
you might not need to do any interpolation at all.
Otherwise, before drawing the frame, update the model
with the dt since the last modelupdate. If the modelrate
really needs to be fixed do this update (or
interpolation) on a copy of the model and draw the frame.

Did that make any sense :wink:


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

I didn’t read through your code, but you might consider
a hybrid approach making the modelrate independent of
the framerate:

http://www.jmckell.com/modelrate.html

The framrate can then vsync which should give you the best
result. If the modelrate is higher than the framrate you
might not need to do any interpolation at all. Otherwise,
before drawing the frame, update the model with the dt since
the last modelupdate. If the modelrate really needs to be
fixed do this update (or interpolation) on a copy of the model
and draw the frame.

Did that make any sense :wink:

Yep, you made sense :). Couldn’t you add a little note/link on this to
the SDL wiki FAQ?

/OlofOn Sat, 11 Dec 2004 15:05:38 +0100, blynel at mip.sdu.dk wrote:

I didn’t read through your code, but you might consider
a hybrid approach making the modelrate independent of
the framerate:

http://www.jmckell.com/modelrate.html

The framrate can then vsync which should give you the best
result. If the modelrate is higher than the framrate you
might not need to do any interpolation at all. Otherwise,
before drawing the frame, update the model with the dt since
the last modelupdate. If the modelrate really needs to be
fixed do this update (or interpolation) on a copy of the model
and draw the frame.

Did that make any sense :wink:


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

[…]

So I’m taking this model and trying to make a Fixed Rate
Logic model. This is all I can think of so far:

Uint32 logic_frequency = 100; // 100 Hz

// 1/100th of a second per logic frame
Timer logic_frame_period_timer;
logic_frame_period_timer.set(1 / logic_frequency);
logic_frame_period_timer.start();

This “Timer” thing should not deal with real time, but with
virtual/logic time. The only place where real time gets involved is
when you’re about to render a frame. What you do at that point is:

  1. Check the current real time.

  2. Calculate the corresponding logic time.

  3. Advance the game logic so that the last two
    frames are the ones right before and right
    after the logic time corresponding to the
    frame time. (Yes, linear interpolation adds
    one logic frame of latency.)

  4. Interpolate coordinates between those last
    two frames, using the fractional part of
    the calculated logic time for weight.

  5. Render!

while(true)
{

if(logic_frame_period_timer.is_done())

This has to be a loop, or you can’t handle the rendering frame rate
dropping below the logic frame rate. That is, you must be able to
advance more than one logic frame at a time.

{
advance_game_logic_by_one_frame();
logic_frame_period_timer.reset();
logic_frame_period_timer.start();
}

/// ??? how do I incorporate the game render frame
/// routine???

Either just pick the last set of coordinates available from the logic
engine whenever it’s time to render a frame, or keep the last two
sets of coordinates for interpolation.

With a sufficiently high logic frame rate (a few hundred Hz or
something), you may get away without interpolation and still have
pretty smooth animation.

///
/// ??? what if the game render framerate drops below
/// 30 fps???

See above; you need a loop around the “advance one logic frame” stuff.

}

Should I do my interpolation of sprite coordinates between
logic_frames based on the number of render_frames that
occur between one logic frame?

Sort of, but I think it’s easier to just think of the rendered frames
as samples from a stream of logic frames. The logic engine generates
a steady stream of frames at a fixed rate (*), and the rendering loop
picks the ones closest in time to the frames to render, or
interpolates between the two closest frames.

(*) Not really. The logic engine actually runs in bursts, once for
each rendered frame, advancing zero or more frames.

Or should I interpolate the coordinates based on the average
render_framerate in comparison to the number of
rendered_frames so far in one game logic cycle? If that
makes any sense?

Averages (and filters and the like) tend to break and make things
worse in many situations… The method that usually works best is to
just check the current time when you’re about to start rendering a
frame. Provided rendering time doesn’t vary too much, that’s pretty
close to sampling the actual frame display time. (Which is what we
really want, but cannot do on any common platforms.)

The step from a real time timestamp to logic time is as simple as
calculating the number of logic frames that should have elapsed
((timestamp - start_time) / ms_per_logic_frame, or something), and
advance until you’re there. The fractional part of that calculation
(that would be (timestamp - start_time) % ms_per_logic_frame) can be
used for interpolation.

You may want to use deltas for the actual calculations, at least if
your game, intro and everything keeps running without ever resetting
the logic time. 32 bits and milliseconds means wrap every 49 days and
17 hours, approximately. Calculate the deltas in ms and add them to a
double or Uint64 “current time” variable, or something…

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Friday 10 December 2004 11.02, Paul Lowe wrote:

/// ??? how do I incorporate the game render frame
/// routine???
///
/// ??? what if the game render framerate drops below
/// 30 fps???

I have the same problem but in another way… in linux I can have a frame
rate above 39 fps, instead in windows with the same code, I have 119 fps…
why?
tnx

/// ??? how do I incorporate the game render frame
/// routine???
///
/// ??? what if the game render framerate drops below
/// 30 fps???

I have the same problem but in another way… in linux I can have a frame
rate above 39 fps, instead in windows with the same code, I have 119 fps…
why?

Could be lots of different reasons. You need to tell us the specs of the
the two computers. You need to tell us the specs of the video cards. You
need to tell us if you are using OpenGL or not. The most likely reasons
(IMHO) are

  1. The Linux computer is half the speed of the windows computer.

  2. The pixels in your art are all X bits wide, which happens to be the
    same as a video mode supported by the video card on the windows computer
    but not on the Linux computer. If the depth you ask for is not supported
    by the video card on your computer SDL gives you a fake buffer and then
    converts the pixels to something the card does support at run time. So,
    the program works, but slowly.

  3. You are not using OpenGL, but only SDL’s blit functions. Those
    functions are (usually) hardware accelerated on Windows and are
    (usually) not hardware accelerated on Linux.

  4. You are using OpenGL and you have a very nice video card in the
    windows computer and a relatively crappy one in the Linux computer.

  5. You have a lot more memory in the windows computer than you do in the
    Linux computer.

And there are even more possible reasons.

	Bob PendletonOn Sat, 2004-12-11 at 21:17, NighTiger wrote:

tnx


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

±-------------------------------------+