Function suggestion: SDL_DelayFlip()

I find myself often doing this in my games’ loops:

do
{
last_time = SDL_GetTicks();

... handle events
... manage objects (movement, collisions, etc.)
... blit everybody to the surface

SDL_Flip(screen);

if (SDL_GetTicks() < last_time + (1000 / FPS))
  SDL_Delay(last_time + (1000 / FPS) - SDL_GetTicks());

}
while (!gameover);

What this does is ensure that my game will run at the same framerate on
both my 450Mhz machine, and next year’s 50 GHz computers. :slight_smile:

(Assuming a CPU’s speed is a mistake from the DOS world. Try playing
PacMan meant for a PS/2 on a 486 or a Pentium III.)

I think it’d be nice (and I know I can roll my own here, obviously, but
still, it’d be nice!) if there were a function that handled all of this
at once.

Perhaps something like:

void SDL_FlipDelay(SDL_Surface * screen, int fps)
{
Uint32 current_tick;
SDL_Flip(screen);

current_tick = SDL_GetTicks();

if (current_tick < (screen -> last_flip) + (1000 / fps))
SDL_Delay((screen -> last_flip) + (1000 / fps) - current_tick);

screen -> last_flip = SDL_GetTicks();
}

I don’t know how you thread-using folks feel about this, and I’m not sure
if everyone would agree to adding another member to the SDL_Surface type,
but that’s just one way to do it. (Of course, that memeber would be set to
a suitably low number when the surface gets created.)

I suppose another would be something like:

void SDL_FlipDelay(SDL_Surface * screen, int fps, Uint32 * last_flip)
{
Uint32 current_tick;
SDL_Flip(screen);

current_tick = SDL_GetTicks();

if (current_tick < *last_flip + (1000 / fps))
SDL_Delay(*last_flip + (1000 / fps) - current_tick);

*last_flip = SDL_GetTicks();
}

ie, a pass-by-reference variable which the user has to manage…

SDL_Surface * screen;
Uint32 flip_clock = 0;
int fps = 30;

SDL_FlipDelay(screen, fps, &flip_clock);

Anyway, what does everyone else think of it?

-bill!

PS - Noticing all of the new functions in mixerlib 1.0!
Can’t wait, hint-hint! :wink:

This would be cool. But I guess it’d only be any good if the application called
sleep(). Is that how the current SDL_Delay() call is implemented? Otherwise
it’ll kill your CPU! Also (I have never done speed restrained code before), how
do you calculate a decent FPS on a system? Something may look good at 60FPS but
if you can get away with 70 then that’d be better right?

-Lea.

William Kendrick wrote:> I find myself often doing this in my games’ loops:

do
{
last_time = SDL_GetTicks();

... handle events
... manage objects (movement, collisions, etc.)
... blit everybody to the surface

SDL_Flip(screen);

if (SDL_GetTicks() < last_time + (1000 / FPS))
  SDL_Delay(last_time + (1000 / FPS) - SDL_GetTicks());

}
while (!gameover);

What this does is ensure that my game will run at the same framerate on
both my 450Mhz machine, and next year’s 50 GHz computers. :slight_smile:

(Assuming a CPU’s speed is a mistake from the DOS world. Try playing
PacMan meant for a PS/2 on a 486 or a Pentium III.)

I think it’d be nice (and I know I can roll my own here, obviously, but
still, it’d be nice!) if there were a function that handled all of this
at once.

Perhaps something like:

void SDL_FlipDelay(SDL_Surface * screen, int fps)
{
Uint32 current_tick;
SDL_Flip(screen);

current_tick = SDL_GetTicks();

if (current_tick < (screen -> last_flip) + (1000 / fps))
SDL_Delay((screen -> last_flip) + (1000 / fps) - current_tick);

screen -> last_flip = SDL_GetTicks();
}

I don’t know how you thread-using folks feel about this, and I’m not sure
if everyone would agree to adding another member to the SDL_Surface type,
but that’s just one way to do it. (Of course, that memeber would be set to
a suitably low number when the surface gets created.)

I suppose another would be something like:

void SDL_FlipDelay(SDL_Surface * screen, int fps, Uint32 * last_flip)
{
Uint32 current_tick;
SDL_Flip(screen);

current_tick = SDL_GetTicks();

if (current_tick < *last_flip + (1000 / fps))
SDL_Delay(*last_flip + (1000 / fps) - current_tick);

*last_flip = SDL_GetTicks();
}

ie, a pass-by-reference variable which the user has to manage…

SDL_Surface * screen;
Uint32 flip_clock = 0;
int fps = 30;

SDL_FlipDelay(screen, fps, &flip_clock);

Anyway, what does everyone else think of it?

-bill!

PS - Noticing all of the new functions in mixerlib 1.0!
Can’t wait, hint-hint! :wink:

This would be cool. But I guess it’d only be any good if the application called
sleep(). Is that how the current SDL_Delay() call is implemented? Otherwise
it’ll kill your CPU!

I assume so. (Most likely, “usleep()”, at least under Linux).
It definitely DOESN’T eat CPU.

Also (I have never done speed restrained code before), how
do you calculate a decent FPS on a system? Something may look good at 60FPS but
if you can get away with 70 then that’d be better right?

No. :slight_smile: Not necessarily.

-bill!

This would be cool. But I guess it’d only be any good if the application
called
sleep(). Is that how the current SDL_Delay() call is implemented? Otherwise
it’ll kill your CPU!

I assume so. (Most likely, “usleep()”, at least under Linux).
It definitely DOESN’T eat CPU.

Also (I have never done speed restrained code before), how
do you calculate a decent FPS on a system? Something may look good at 60FPS
but
if you can get away with 70 then that’d be better right?

No. :slight_smile: Not necessarily.

-bill!

Actually, the most Posix portable way is to use select() with an empty
file descriptor set and a timeout value equal to what you’d use in usleep().
This is because not all unixes implement the usleep() call. I believe from
my last time reading the code that this is what SDL uses as well.

–friar

In a Previous thread, Sam mentioned that it was implemented using a
select() delay under linux, I believe.

Of course, there is always the SDL source code, if you really need to
know. :)–
Brian

On Wed, 8 Dec 1999, William Kendrick wrote:

This would be cool. But I guess it’d only be any good if the application called
sleep(). Is that how the current SDL_Delay() call is implemented? Otherwise
it’ll kill your CPU!

I assume so. (Most likely, “usleep()”, at least under Linux).
It definitely DOESN’T eat CPU.

Also (I have never done speed restrained code before), how
do you calculate a decent FPS on a system? Something may look good at 60FPS but
if you can get away with 70 then that’d be better right?

No. :slight_smile: Not necessarily.

-bill!

Lea Anthony wrote:

Also (I have never done speed restrained code before), how do you calculate
a decent FPS on a system? Something may look good at 60FPS but if you can
get away with 70 then that’d be better right?

It depends on the game actually, but the strategy we use here is using a
game “heartbeat”, set to, for example, 100 Hz. What happen is that we
try to run the game logic 100 times per second without any drawing, and
we do a redraw/flip whenever we’re “on top of it”.

That is, we are “late” when the actual time is larger than the time we
would be supposed to have the heartbeat, and when we have time left
before the next heartbeat, we’re “on top of it”, so we launch a redraw.

The best way to see this is that time (the heartbeat) is just another
event, like a keypress or a network packet. When you get it, you execute
the game logic. Video updates are something you do as fast as possible,
but doesn’t matter (much) if you do it less often.–
Pierre Phaneuf
Ludus Design, http://ludusdesign.com/
“First they ignore you. Then they laugh at you.
Then they fight you. Then you win.” – Gandhi

William Kendrick wrote:

I find myself often doing this in my games’ loops:

do
{
last_time = SDL_GetTicks();

... handle events
... manage objects (movement, collisions, etc.)
... blit everybody to the surface

SDL_Flip(screen);

if (SDL_GetTicks() < last_time + (1000 / FPS))
  SDL_Delay(last_time + (1000 / FPS) - SDL_GetTicks());

}
while (!gameover);

What this does is ensure that my game will run at the same framerate on
both my 450Mhz machine, and next year’s 50 GHz computers. :slight_smile:

(Assuming a CPU’s speed is a mistake from the DOS world. Try playing
PacMan meant for a PS/2 on a 486 or a Pentium III.)

I think it’d be nice (and I know I can roll my own here, obviously, but
still, it’d be nice!) if there were a function that handled all of this
at once.

Perhaps something like:

void SDL_FlipDelay(SDL_Surface * screen, int fps)
{
Uint32 current_tick;
SDL_Flip(screen);

current_tick = SDL_GetTicks();

if (current_tick < (screen -> last_flip) + (1000 / fps))
SDL_Delay((screen -> last_flip) + (1000 / fps) - current_tick);

screen -> last_flip = SDL_GetTicks();
}

I don’t know how you thread-using folks feel about this, and I’m not sure
if everyone would agree to adding another member to the SDL_Surface type,
but that’s just one way to do it. (Of course, that memeber would be set to
a suitably low number when the surface gets created.)

I suppose another would be something like:

void SDL_FlipDelay(SDL_Surface * screen, int fps, Uint32 * last_flip)
{
Uint32 current_tick;
SDL_Flip(screen);

current_tick = SDL_GetTicks();

if (current_tick < *last_flip + (1000 / fps))
SDL_Delay(*last_flip + (1000 / fps) - current_tick);

*last_flip = SDL_GetTicks();
}

ie, a pass-by-reference variable which the user has to manage…

SDL_Surface * screen;
Uint32 flip_clock = 0;
int fps = 30;

SDL_FlipDelay(screen, fps, &flip_clock);

Anyway, what does everyone else think of it?

-bill!

PS - Noticing all of the new functions in mixerlib 1.0!
Can’t wait, hint-hint! :wink:

Well depending on what you want to do, maintaining frame rate may not
be what you want to do. In many cases it is better to take time as a
fraction of second from the last time your loop ran, and multiply that
fraction by your movement speed, so that all your objects will move at
the same rate on any system, just “smoother” on faster systems.

In simpler words, if your system is really fast, you want to move the
objects in finer movements, these finer movements are determined by
how fast your entire main loop ran for its last iteration. If it ran
really fast, therefore giving you a small value in milliseconds, say
10ms, then you could multiply that value by the movement and move them
slower on a faster system, utitilizing the full speed of the system.

For example:

void objectMovement(float *x, float *y, float time_fraction,
float *vel_x, float *vel_y, float obj_speed,
float angle;
{
float x_ang_component;
float y_ang_component;

// Get compoenents for the angle the object is facing
get_ang_components(angle,&x_ang_component, &y_ang_component);

(*vel_x)+=(time_fraction*obj_speed*x_ang_component);
(*vel_y)+=(time_fraction*obj_speed*y_ang_component);

(*x)+=vel_x;
(*y)+=vel_y;

}

int main(…)
{
float time_fraction=0;
float timer_start;

for all objects {

    timer_start=get_system_time_in_milliseconds();

    getInput();
    doNetwork();
    objectMovement(time_fraction);

    // This gives us the time it took to do everything and render one

frame
// 1/time_fraction, is our frames per second for the entire loop and
can
// now be used to normalize object movement
time_fraction=get_system_time_in_millieconds()-timer_start;
}

-Alan Carr
http://www.denizengames.com

> Well depending on what you want to do, maintaining frame rate may not > be what you want to do. In many cases it is better to take time as a > fraction of second from the last time your loop ran, and multiply that > fraction by your movement speed, so that all your objects will move at > the same rate on any system, just "smoother" on faster systems.

I’ve also seen this suggested. A friend is writing a pong game that works
like this.

The only problem I could see with this is the process jumping to 100% CPU
usage. (This has happened in loops where I forgot to do any kind of
delay.)

-bill!

Wow! I didn’t know we were friends!!! :slight_smile: heheheOn Wed, 8 Dec 1999, William Kendrick wrote:

I’ve also seen this suggested. A friend is writing a pong game that works
like this.

The only problem I could see with this is the process jumping to 100% CPU
usage. (This has happened in loops where I forgot to do any kind of
delay.)

-bill!

Well, he hasn’t worked on it yet. He was suppose to do the network code,
but he’s been busy with other stuff right now… The game right now is all
from me and sam. :slight_smile:

see yaOn Wed, 8 Dec 1999, William Kendrick wrote:

Wow! I didn’t know we were friends!!! :slight_smile: hehehe

Lemme guess, you’re the guy who’s working with Mike Machado (who IS one
of my friends, I’d like to think… I know him through SacLUG) on a
Pong game, huh?

:slight_smile:

-bill!

On Wed, 8 Dec 1999, William Kendrick wrote:

I’ve also seen this suggested. A friend is writing a pong game that works
like this.

Ok. I clear this up… I wrote ALL of my pong game. :)On Wed, 8 Dec 1999, Sam Lantinga wrote:

Well, he hasn’t worked on it yet. He was suppose to do the network code,
but he’s been busy with other stuff right now… The game right now is all
from me and sam. :slight_smile:

see ya

Oh, Sam’s in on this, too, eh? :slight_smile:

Uhhhh, no. :slight_smile:
I just gave a little debugging advice.

-Sam Lantinga (slouken at devolution.com)

Lead Programmer, Loki Entertainment Software

“Any sufficiently advanced bug is indistinguishable from a feature”
– Rich Kulawiec

Geeze… Don’t you read the SDL Game page??? :slight_smile:

www.addell.com

get the cvs version. hehe… I’ve seen your pong game too. it’s pretty
cool…On Wed, 8 Dec 1999, William Kendrick wrote:

Ok. I clear this up… I wrote ALL of my pong game. :slight_smile:

Well, let’s see it, then! :wink:

-bill!
PS - Check out my 3D vector-based pong game written in Xlib
http://www.newbreedsoftware.com/3dpong/
I’m eventually gonna port it to OpenGL… or maybe fake the 3D and do
it entirely in SDL. Hmm!

Wow! I didn’t know we were friends!!! :slight_smile: hehehe

Lemme guess, you’re the guy who’s working with Mike Machado (who IS one
of my friends, I’d like to think… I know him through SacLUG) on a
Pong game, huh?

:slight_smile:

-bill!> On Wed, 8 Dec 1999, William Kendrick wrote:

I’ve also seen this suggested. A friend is writing a pong game that works
like this.

Well, he hasn’t worked on it yet. He was suppose to do the network code,
but he’s been busy with other stuff right now… The game right now is all
from me and sam. :slight_smile:

see ya

Oh, Sam’s in on this, too, eh? :slight_smile:

-bill!

Well, he hasn’t worked on it yet. He was suppose to do the network code,
but he’s been busy with other stuff right now… The game right now is all
from me and sam. :slight_smile:

see ya

Oh, Sam’s in on this, too, eh? :slight_smile:

Uhhhh, no. :slight_smile:
I just gave a little debugging advice.

-Sam Lantinga				(slouken at devolution.com)

Lead Programmer, Loki Entertainment Software–
“Any sufficiently advanced bug is indistinguishable from a feature”
– Rich Kulawiec

Ok. I clear this up… I wrote ALL of my pong game. :slight_smile:

Well, let’s see it, then! :wink:

-bill!
PS - Check out my 3D vector-based pong game written in Xlib
http://www.newbreedsoftware.com/3dpong/
I’m eventually gonna port it to OpenGL… or maybe fake the 3D and do
it entirely in SDL. Hmm!

William Kendrick wrote:

> Well depending on what you want to do, maintaining frame rate may not > be what you want to do. In many cases it is better to take time as a > fraction of second from the last time your loop ran, and multiply that > fraction by your movement speed, so that all your objects will move at > the same rate on any system, just "smoother" on faster systems.

I’ve also seen this suggested. A friend is writing a pong game that works
like this.

The only problem I could see with this is the process jumping to 100% CPU
usage. (This has happened in loops where I forgot to do any kind of
delay.)

-bill!

For a client this is probably okay, for a server you probably want
a sleep time between world ticks.

-Alan Carr
http://www.denizengames.com