Timing with SDL

hello,

I’ve read and re-read the chapter of SDL documentation that deals with
timing but I’m not really sure about what i can do with them.
My purpose is to make a game, (that uses openGL) programmed with SDL,
runs at the same speed on different PCs (a well-known problem :slight_smile:

I believe timing fonctions of SDL can help me in doing this but i’m not
sure about how to use them (SDL’s documentation is poor on this
subject).
I probably need to get the time between each frame drawn and to adjust
the moves.
I saw that SDL_GetTicks() can do this but do I need to have a “callback”
? Do I need to call SDL_SetTimer, and with which “interval” ?

thanks in advance, and thanks a lot to Gautier Portet and to Mattias
Engdeg?rd for their answers to my previous question.

PH.

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

PH-Neutre escribi?:

hello,

I’ve read and re-read the chapter of SDL documentation that deals
with timing but I’m not really sure about what i can do with them.
My purpose is to make a game, (that uses openGL) programmed with
SDL, runs at the same speed on different PCs (a well-known problem
:slight_smile:

I believe timing fonctions of SDL can help me in doing this but i’m
not sure about how to use them (SDL’s documentation is poor on this
subject). I probably need to get the time between each frame drawn
and to adjust the moves. I saw that SDL_GetTicks() can do this but
do I need to have a “callback” ? Do I need to call SDL_SetTimer,
and with which “interval” ?

thanks in advance, and thanks a lot to Gautier Portet and to
Mattias Engdeg?rd for their answers to my previous question.

PH.

What I do to keep my game running at a constant speed in on

different machines is to set a callback. For instance, if I want my
game to run at 20 cicles per second , I use two global int variables:
real_cicles and done_cicles , and this calback function:

Uint32 cicle(Uint32 time){
real_cicles++;
return time; //the function must return the same value it received
to keep the same timing
}

Then I set the callback calling:

SDL_SetTimer(50,cicle); //the callback will be called every 50

miliseconds. That’s twenty times a minute.

I have also two functions (update() and frame(), for example). The

first one updates all data for the next game frame but does nothing
with graphics. The second one blits images, updates surfaces, etc
(shows the next frame). update() also does done_cicles++. Finally,
the code for the main game loop is similar to this:

do{
	int lastcicles;
	lastcicles=done_cicles;
	while(done_cicles<real_cicles) update();
	if(lastcicles!=done_cicles);frame();
}while(exit==0); 

This way the games runs at up to 20fps, and even if it is not able

to show all frames, the game speed will be the same (of course, on a
slow machine the game will look very ugly, cause it will skip may
frames). You could also supress the last if (and the first two
sentences) to avoid setting a limit to the frame rate.

I don't know if this is the usual way, but it seems to work.

Un saludo.

P.S. I think SDL also has a new timer callback system able to
maintain several callbacks running at the same time. I use the old
one because I don’t need more than one callback, and this system is
simpler.


Jes?s Carrete Monta?a ----> KUANTIKO___________________________________________
| .~. |
| /V\ jrcarmon(arroba)teleline.es |
| // \ Linux Registered |
| /( )\ User #158442 |
| ^`~’^ |
|___________________________________________|

Clave p?blica PGP disponible por e-mail.

-----BEGIN PGP SIGNATURE-----
Version: PGP 6.5.1i for non-commercial use http://www.pgpi.com/

iQA+AwUBOWcH61XBzV6UX+HYEQJV+wCXaMtPoxCTtsL2stK81J1dGo0o+wCgwlbh
2NAg+l+kmyvuBrNR+P50oFw=
=pknN
-----END PGP SIGNATURE-----

thanks a lot for your answer !

i have a little question however : why do you set the timer for 20fps,
and not, for instence, for 30fps (callback called every 30ms, 33.3 times
a minute), or even more ?

one more time, thanks, it helps me a lot.

PH.

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

PH-Neutre escribi?:

thanks a lot for your answer !

i have a little question however : why do you set the timer for
20fps, and not, for instence, for 30fps (callback called every
30ms, 33.3 times a minute), or even more ?

It's only an example. I could have done that (you're right, 20 fps

is very slow :)).
I’ve just noticed a stupid mistake in my code. I wrote:

while(exit==0)

Of course, a variable can't be called exit (cause exit is the adress

of exit(), obviously). Sorry.

Un saludo.


Jes?s Carrete Monta?a ----> KUANTIKO___________________________________________
| .~. |
| /V\ jrcarmon(arroba)teleline.es |
| // \ Linux Registered |
| /( )\ User #158442 |
| ^`~’^ |
|___________________________________________|

Clave p?blica PGP disponible por e-mail.

-----BEGIN PGP SIGNATURE-----
Version: PGP 6.5.1i for non-commercial use http://www.pgpi.com/

iQA/AwUBOWdjOFXBzV6UX+HYEQKMagCgjUAbSVXpUWScHV5dLlIOMY4B5vQAn0JT
K73pc0HblUh7t9+2bD1uw37X
=yyvh
-----END PGP SIGNATURE-----

ok, thank you very much !!

PH.> It’s only an example. I could have done that (you’re right, 20 fps

is very slow :)).
I’ve just noticed a stupid mistake in my code. I wrote:

    while(exit==0)

    Of course, a variable can't be called exit (cause exit is the adress

of exit(), obviously). Sorry.

PH-Neutre wrote:

ok, thank you very much !!

PH.
There is an alternative method, which I prefer. The method described
previously has two problems, on slow machines that cannot preform at the
set framerate the gameplay is too slow, and faster machines cannot
achieve higher framerates. You can solve both these functions using the
following method. At the beginning of each frame find the amount of
time that has elapsed between the time you started drawing the last
frame and the present. Then calculate the new world state based on this
time change. For instance if 1/10 of a second passed, and you have a
projectile moving at 5 meters/second, it would move 5 * .1 = .5 meters.
This method allows the game to run at the maximum possible framerate on
the given computer while keeping the speed of the gameplay constant.–
Stuart O. Anderson

This is my first post to the SDL list and I want to say ‘Hello’ and
thank you all for contributing to this great project.On Fri, 28 Jul 2000 02:52:44 -0400, Stuart Anderson wrote:

At the beginning of each frame find the amount of
time that has elapsed between the time you started drawing the last
frame and the present. Then calculate the new world state based on this
time change. For instance if 1/10 of a second passed, and you have a
projectile moving at 5 meters/second, it would move 5 * .1 = .5 meters.
This method allows the game to run at the maximum possible framerate on
the given computer while keeping the speed of the gameplay constant.

Except when you have lengthy side-effects such as disk swapping (Windows)
or my favorite, S3TC texture decompression.

It took me days to figure out why “NFS: Porsche Unleashed” stops, wait
up to one second and then displays next frame of me ending up dead in
a ditch 500m away. This happened every time truck, car or anything else
containing unique textures got rendered for the first time. When I
turned it off using S3Tweak game was playable again.

That’s because they used quoted method and v=s/t formula, and have not
limited DeltaTime (i.e. time elapsed between two frames) to some max
value (i.e. set minimum frame rate)

BTW, all SDL samples are unable to initialize hardware accelerated GL
modes on my ELSA Winner2 (S3 Savage4), they always fall back to
Microsoft Generic software renderer which is awfully slow. I have some
programs that can do it so I will try to fix it myself…


Srdjan Dakic
Game Programmer, Legus3D LLC
http://www.Legus3D.com/

Srdjan Dakic schrieb am 28 Jul 2000:

At the beginning of each frame find the amount of
time that has elapsed between the time you started drawing the last
frame and the present. Then calculate the new world state based on this
time change. For instance if 1/10 of a second passed, and you have a
projectile moving at 5 meters/second, it would move 5 * .1 = .5 meters.
This method allows the game to run at the maximum possible framerate on
the given computer while keeping the speed of the gameplay constant.

Except when you have lengthy side-effects such as disk swapping (Windows)
or my favorite, S3TC texture decompression.

That’s rather a bug in the application (by missing to clamp delta_time, as
you pointed out).

Other things that can go wrong using the mentioned approach from above:
You might still get frame-rate dependent behaviour if you time-resolution
dependend behaviour (example: your moon rotates around the planet due to
gravity: if you compute the moons infrequently, you get a rather funny
orbit). One approach to move around this is to “guarantee” a minimum
frame rate for your physics. I do the following:

dt = thistime - lasttime;
while(dt > MAX_DT) {
physics(MAX_DT);
dt -= MAX_DT;
}
physics(dt);

That guarantees that your physics engine runs at least at 1000 / MAX_DT Hz.

BTW, all SDL samples are unable to initialize hardware accelerated GL
modes on my ELSA Winner2 (S3 Savage4), they always fall back to
Microsoft Generic software renderer which is awfully slow. I have some
programs that can do it so I will try to fix it myself…

Two shots in the dark:

Except when you have lengthy side-effects such as disk swapping (Windows)
or my favorite, S3TC texture decompression.
Hmm. Time clamping would cause problems in network games. I’d suggest
trying to load the image in a separate thread / having the load function
load the image in chunks over several frames. Of course this creates
problems if you need to draw the texture in the current frame. Any
thoughts?

Other things that can go wrong using the mentioned approach from above:
You might still get frame-rate dependent behaviour if you time-resolution
dependend behaviour (example: your moon rotates around the planet due to
gravity: if you compute the moons infrequently, you get a rather funny
orbit). One approach to move around this is to “guarantee” a minimum
frame rate for your physics.
Hmm. This would work, but a cleaner solution, IMO, would be to do the
full integration over delta_time. That way you get an answer that is
exact (to the limits of your datatype) no matter how short/long/variable
your time delta is.–
Stuart O. Anderson

BTW, all SDL samples are unable to initialize hardware accelerated GL
modes on my ELSA Winner2 (S3 Savage4), they always fall back to
Microsoft Generic software renderer which is awfully slow. I have some
programs that can do it so I will try to fix it myself…

Two shots in the dark:

  • Do these programs dynamically load a MiniGL and bypass the ICD mechanism?

I have managed to get acceleration by putting these before
SDL_SetVideoMode call. I still don’t have acceleration in fullscreen
modes…

SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);

Now those NeHe samples look great!On Fri, 28 Jul 2000 16:42:59 +0200, “Andreas Umbach” wrote:


There is a bug in file

sdl/src/video/wincommon/sdl_wingl.c,
WIN_GL_SetupWindow, line 69, version 1.1.3

GL_pfd.cColorBits = this->gl_config.depth_size;

GL_pfd.cDepthBits = this->gl_config.depth_size;

ColorBits is rendering buffer depth, DepthBits is Z-Buffer depth !!!
First line should state:

GL_pfd.cColorBits = this->gl_config.buffer_size;

since this is the value set by SDL_GL_SetAttribute

WIN_GL_GetAttribute() in the same file is also broken.
For SDL_GL_BUFFER_SIZE it should return pfd.cColorBits, and for
SDL_GL_DEPTH_SIZE it should return pfd.cDepthBits


  • You do use GLsetup, don’t you?

No, it always seems to install broken driver.

After a lot of search and reinstalling, I have found one (called “ggghhh”)
that works and I stick to it.


Dale