Per-frame updates

Hi,

I’m an experienced programmer, but new to game programming so I figured a good way to start my
climb up the learning curve would be to study the source code for the many example SDL games out
the on the net. One thing I have noticed is that a common technique to have a main loop something
like this:

while(1){
while( event_available ){
process_event();
}
do_game_logic();
}

where the ‘do_game_logic()’ code does things like updating to the next frame in an animation,
moving sprites, scrolling the background a bit, etc. The problem I see is that this ties the
speed of the game to the speed of the computer it’s running on, which could lead to the game being
unplayable on future hardware (if you have ever tried to play your old 10-year old favorites on
your current hardware, you know what I’m talking about). Is my assessment correct, or am I
missing something? I’ve seen this practice even in game book examples.

It seems to me (intuitively, I haven’t written any games yet) that a better way to do this would
be to not have ‘do_game_logic()’ in the main loop at all, but instead use a timer and have the
game logic execute in the callback for that timer. However, I’ve seen a lot of anecdotal comments
on boards and in tutorials that say basically, 'don’t use timers, they will kill your frame rate!'
Is there really a big downside to using timers this way? I can see that if you are developing a
3d FPS or flight sim you would want to get as many frames as possible, and having the game logic
called every frame makes sense for those games, but why do it for 2d sprite games?

TIA for setting a newbie straight :slight_smile:
Todd__________________________________________________
Do you Yahoo!?
The New Yahoo! Search - Faster. Easier. Bingo
http://search.yahoo.com

Todd Klaus wrote:

The problem I see is that this ties the speed of the
game to the speed of the computer it’s running on, which could lead
to the game being unplayable on future hardware (if you have ever
tried to play your old 10-year old favorites on your current
hardware, you know what I’m talking about).

The speed is not necessarily tied to the hardware speed. The
do_game_logic function could be checking the time that it was last
executed and scaling motion accordingly. This way, the game will always
move at approximately the same rate, but will be ‘smoother’ on faster
hardware. Or it could just wait a bit if it was ahead of schedule,
keeping a steady frame rate. Just because neither of these are obvious
from looking at the main loop, doesn’t mean they don’t take place. :slight_smile:

It seems to me (intuitively, I haven’t written any games yet) that a
better way to do this would be to not have ‘do_game_logic()’ in the
main loop at all, but instead use a timer and have the game logic
execute in the callback for that timer. However, I’ve seen a lot of
anecdotal comments on boards and in tutorials that say basically,
‘don’t use timers, they will kill your frame rate!’

Timers often don’t have the kind of resolution you want. Commonly, you
might only get 10ms granularity on them. So this limits you to things
that happen every 10ms (100fps), 20ms (50fps), 30ms (33fps), and so on.
Miss one of the intervals by 1ms and you’re relegated to the next class.

Also bear in mind that they’re only another method of delaying
execution - you’d get the same sort of thing by implementing a delay in
your main loop, so it’s not as different an approach as it sounds.
Personally I think timers and callbacks obscure the program flow, but
perhaps they are more intuitive to people used to event-based systems.–
Kylotan
http://pages.eidosnet.co.uk/kylotan

Hi,

I’m an experienced programmer, but new to game programming so I figured a
good way to start my
climb up the learning curve would be to study the source code for the many
example SDL games out
the on the net. One thing I have noticed is that a common technique to
have a main loop something
like this:

while(1){
while( event_available ){
process_event();
}
do_game_logic();
}

where the ‘do_game_logic()’ code does things like updating to the next
frame in an animation,
moving sprites, scrolling the background a bit, etc. The problem I see is
that this ties the
speed of the game to the speed of the computer it’s running on, which
could lead to the game being
unplayable on future hardware (if you have ever tried to play your old
10-year old favorites on
your current hardware, you know what I’m talking about). Is my assessment
correct, or am I
missing something? I’ve seen this practice even in game book examples.

In the update code, you could take the time since the last update. And then
if a vehicle drives at 60 km/h, multiply that with the time since last
update and your vehicle drives at the same speed on all hardware.

----- Original Message -----
From: tklaus@yahoo.com (Todd Klaus)
To:
Sent: Friday, April 18, 2003 7:37 PM
Subject: [SDL] Per-frame updates

Thanks, that makes perfect sense. Scaling the motion by checking the time seems like the optimal
solution, since you could then have different sprites moving at different speeds. It would be
hard to do this with timers since the speed differences would have to be in increments of the
timer resolution.

— Kylotan wrote:> Todd Klaus wrote:

The problem I see is that this ties the speed of the
game to the speed of the computer it’s running on, which could lead
to the game being unplayable on future hardware (if you have ever
tried to play your old 10-year old favorites on your current
hardware, you know what I’m talking about).

The speed is not necessarily tied to the hardware speed. The
do_game_logic function could be checking the time that it was last
executed and scaling motion accordingly. This way, the game will always
move at approximately the same rate, but will be ‘smoother’ on faster
hardware. Or it could just wait a bit if it was ahead of schedule,
keeping a steady frame rate. Just because neither of these are obvious
from looking at the main loop, doesn’t mean they don’t take place. :slight_smile:

It seems to me (intuitively, I haven’t written any games yet) that a
better way to do this would be to not have ‘do_game_logic()’ in the
main loop at all, but instead use a timer and have the game logic
execute in the callback for that timer. However, I’ve seen a lot of
anecdotal comments on boards and in tutorials that say basically,
‘don’t use timers, they will kill your frame rate!’

Timers often don’t have the kind of resolution you want. Commonly, you
might only get 10ms granularity on them. So this limits you to things
that happen every 10ms (100fps), 20ms (50fps), 30ms (33fps), and so on.
Miss one of the intervals by 1ms and you’re relegated to the next class.

Also bear in mind that they’re only another method of delaying
execution - you’d get the same sort of thing by implementing a delay in
your main loop, so it’s not as different an approach as it sounds.
Personally I think timers and callbacks obscure the program flow, but
perhaps they are more intuitive to people used to event-based systems.


Kylotan
http://pages.eidosnet.co.uk/kylotan


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


Do you Yahoo!?
The New Yahoo! Search - Faster. Easier. Bingo
http://search.yahoo.com

It seems to me (intuitively, I haven’t written any games yet) that a better
way to do this would be to not have ‘do_game_logic()’ in the main loop at
all, but instead use a timer and have the game logic execute in the
callback for that timer. However, I’ve seen a lot of anecdotal comments on
boards and in tutorials that say basically, ‘don’t use timers, they will
kill your frame rate!’ Is there really a big downside to using timers this
way? I can see that if you are developing a 3d FPS or flight sim you would
want to get as many frames as possible, and having the game logic called
every frame makes sense for those games, but why do it for 2d sprite games?

You are correct. There are a few reasons not to do your game logic inside the
timer callback. The one that always bites me is that SDL timer callbacks run
in a separate thread (under linux). It is possible to use a timer to
regulate the game logic, what you have to do is decouple the game logic from
the display update. This allows the logic to run at a steady speed, and slow
computers can skip a screen update when necessary while fast computers can
get super high numbers of screen refreshes. The only real downside to this is
that very slow computers will skip every screen update if your game logic
takes too long. But we were trying to future-proof the game for faster
computers, right?
The way I like to handle this is ripped straight from the allegro toolkit FAQ
http://alleg.sourceforge.net/faq.html (with a little modification to work
with SDL):

Q: How can I make my game run at the same speed on any computer?

skip the screen refresh every now and then if the computer is too slow to
keep up. This can be done by installing a timer handler that will increment a
global variable at your game logic speed, eg:

Uint32 speed_counter = 0;
Uint32 increment_speed_counter(Uint32 interval, void *param) {
speed_counter++;
}

void play_the_game() {
SDL_AddTimer(1000/DESIRED_FPS, increment_speed_counter, NULL);
while (!game_over) {
while (speed_counter > 0) {
update_game_logic();
speed_counter–;
}
update_display();
}
}On Friday 18 April 2003 12:37, Todd Klaus wrote:
A:You need to make sure the game logic gets updated at a regular rate, but


Hope that was useful,
Max Watson <@Max_Watson>

Thanks, that makes perfect sense. Scaling the motion by checking the time
seems like the optimal
solution, since you could then have different sprites moving at different
speeds. It would be
hard to do this with timers since the speed differences would have to be
in increments of the
timer resolution.

It’s not the perfect solution.
Your AI might be smarted on faster systems for example.

I guess the fundamental thing is to decouple the screen updates from the rest of the game logic.
That’s what I was missing from the abstract examples in books, they usually just lump everything
together in one ‘game logic’ function, I was just assuming that the two were tied together.
Thanks for the clarification.

Todd

— Max Watson wrote:> On Friday 18 April 2003 12:37, Todd Klaus wrote:

It seems to me (intuitively, I haven’t written any games yet) that a better
way to do this would be to not have ‘do_game_logic()’ in the main loop at
all, but instead use a timer and have the game logic execute in the
callback for that timer. However, I’ve seen a lot of anecdotal comments on
boards and in tutorials that say basically, ‘don’t use timers, they will
kill your frame rate!’ Is there really a big downside to using timers this
way? I can see that if you are developing a 3d FPS or flight sim you would
want to get as many frames as possible, and having the game logic called
every frame makes sense for those games, but why do it for 2d sprite games?

You are correct. There are a few reasons not to do your game logic inside the
timer callback. The one that always bites me is that SDL timer callbacks run
in a separate thread (under linux). It is possible to use a timer to
regulate the game logic, what you have to do is decouple the game logic from
the display update. This allows the logic to run at a steady speed, and slow
computers can skip a screen update when necessary while fast computers can
get super high numbers of screen refreshes. The only real downside to this is
that very slow computers will skip every screen update if your game logic
takes too long. But we were trying to future-proof the game for faster
computers, right?
The way I like to handle this is ripped straight from the allegro toolkit FAQ
http://alleg.sourceforge.net/faq.html (with a little modification to work
with SDL):

Q: How can I make my game run at the same speed on any computer?

A:You need to make sure the game logic gets updated at a regular rate, but
skip the screen refresh every now and then if the computer is too slow to
keep up. This can be done by installing a timer handler that will increment a
global variable at your game logic speed, eg:

Uint32 speed_counter = 0;
Uint32 increment_speed_counter(Uint32 interval, void *param) {
speed_counter++;
}

void play_the_game() {
SDL_AddTimer(1000/DESIRED_FPS, increment_speed_counter, NULL);
while (!game_over) {
while (speed_counter > 0) {
update_game_logic();
speed_counter–;
}
update_display();
}
}


Hope that was useful,
Max Watson


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


Do you Yahoo!?
The New Yahoo! Search - Faster. Easier. Bingo
http://search.yahoo.com

Todd Klaus wrote:

Hi,

I’m an experienced programmer, but new to game programming so I figured a good way to start my
climb up the learning curve would be to study the source code for the many example SDL games out
the on the net. One thing I have noticed is that a common technique to have a main loop something
like this:

while(1){
while( event_available ){
process_event();
}
do_game_logic();
}

where the ‘do_game_logic()’ code does things like updating to the next frame in an animation,
moving sprites, scrolling the background a bit, etc. The problem I see is that this ties the
speed of the game to the speed of the computer it’s running on, which could lead to the game being
unplayable on future hardware (if you have ever tried to play your old 10-year old favorites on
your current hardware, you know what I’m talking about). Is my assessment correct, or am I
missing something? I’ve seen this practice even in game book examples.

It seems to me (intuitively, I haven’t written any games yet) that a better way to do this would
be to not have ‘do_game_logic()’ in the main loop at all, but instead use a timer and have the
game logic execute in the callback for that timer. However, I’ve seen a lot of anecdotal comments
on boards and in tutorials that say basically, 'don’t use timers, they will kill your frame rate!'
Is there really a big downside to using timers this way? I can see that if you are developing a
3d FPS or flight sim you would want to get as many frames as possible, and having the game logic
called every frame makes sense for those games, but why do it for 2d sprite games?

TIA for setting a newbie straight :slight_smile:
Todd

Many games I’ve seen use a timer. That is you get the elapsed time
since last frame, and calculate the position of things based on that.

Others use game ticks. Then make sure that the game ticks are in
constant time. Eg. with a frame rate of 40 each tick is 1 second. This
can simplify some game code, as the time steps are constant.

You don’t have to update some things every frame if you don’t want to.
A common optimization is to only update the game entities in the
immediate area.

I think you’ll find drawing to be the major slow down not timing code.
So go with what ever method makes more sense to you.

Have the fun!