please help - inconsistent tick count values

Started by
6 comments, last by jimbogd 16 years, 11 months ago
I'm using SDL_GetTicks() and SDL_Delay() for my game loop timing. I'm trying to snap the game speed/frame rate at 50Hz but I'm getting inconsistent reading from SDL_GetTicks(). My game loop is as follows:

	int iNextUpdateTick = SDL_GetTicks();
	while( !g_bQuit) {
		update();
		render();
		iNextUpdateTick += TICKS_TO_WAIT_FOR_NEXT_GAME_UPDATE;
		iDelayTime = iNextUpdateTick - SDL_GetTicks();
		if( iDelayTime >= 0 ) SDL_Delay( iDelayTime );
	}


It seems when my game first starts for 5 seconds or so I get crazy readings, then after that they settle down a bit, but are still not consistent. When my game first runs, the readings for about 5 seconds are as follows: tick count elapsed fps/game speed 1407 57ms 17Hz 1513 106ms 9Hz 1866 353ms 2Hz 1879 13ms 76Hz 1893 14ms 71Hz 1957 64ms 15Hz 1970 13ms 76Hz 2264 294ms 3Hz 2278 14ms 71Hz 2290 12ms 83Hz 2304 14ms 71Hz 2317 13ms 76Hz 2472 155ms 6Hz 2479 7ms 142Hz 2492 13ms 76Hz 2505 13ms 76Hz 2518 13ms 76Hz 2619 101ms 9Hz 2626 7ms 142Hz 2639 13ms 76Hz 2652 13ms 76Hz 2658 6ms 166Hz ... etc ... Then gradually they settle down to: tick count elapsed fps/game speed 10415 24ms 41Hz 10431 16ms 62Hz 10455 24ms 41Hz 10471 16ms 62Hz 10495 24ms 41Hz 10511 16ms 62Hz 10535 24ms 41Hz 10551 16ms 62Hz 10580 29ms 34Hz 10592 12ms 83Hz 10611 19ms 52Hz 10631 20ms 50Hz 10651 20ms 50Hz 10671 20ms 50Hz 10691 20ms 50Hz 10711 20ms 50Hz 10737 26ms 38Hz 10751 14ms 71Hz 10771 20ms 50Hz 10792 21ms 47Hz 10811 19ms 52Hz 10831 20ms 50Hz ... etc ... I'm running Vista Premium 32-bit but I had a similar problems with WinXPSP2. Is this tick reading behaviour normal? Is it the fault of SDL_GetTicks()? It seems I can't ever get a smooth consistent reading so my game animation/scrolling is always flickering/jumping/tearing in some way. I've even tried using a delta and updating the fps/game-speed as fast as possible (without using SDL_Delay(), but the same inconsistent tick readings occur. Any ideas? (I am writing to back buffer and using SDL_Flip() for rendering). Many thanks jimbogd
Advertisement
If you replace the

iNextUpdateTick += TICKS_TO_WAIT_FOR_NEXT_GAME_UPDATE;
iDelayTime = iNextUpdateTick - SDL_GetTicks();
if( iDelayTime >= 0 ) SDL_Delay( iDelayTime );

with sleep(0) or sleep(1) what happens?

Quote:Original post by Jimmy Valavanis
If you replace the

iNextUpdateTick += TICKS_TO_WAIT_FOR_NEXT_GAME_UPDATE;
iDelayTime = iNextUpdateTick - SDL_GetTicks();
if( iDelayTime >= 0 ) SDL_Delay( iDelayTime );

with sleep(0) or sleep(1) what happens?


Both Sleep(0) and Sleep(1) both seem to have the same effect. Random jerkiness/jumpiness/speed and tearing. It might be quite smooth for a few seconds, then its all jumpy for a few. It looks awful! :(

jimbogd
I'd say this is to be expected when you're sharing the hardware with a load of other processes. You're pretty much guaranteed that the OS will sometimes put your game on hold to go and give everything else on the system a chance to run for a few milliseconds.

The solution is to design your game such that it doesn't require the loop to run at the exact update times. You could do something like this instead:

int iLastUpdate = SDL_GetTicks();while( !g_bQuit) {	while(SDL_GetTicks() >= iLastUpdate + TICKS_TO_WAIT_FOR_NEXT_GAME_UPDATE)	{		update(); // update the game world by a fixed amount proportional to TICKS_TO_WAIT_FOR_NEXT_GAME_UPDATE		iLastUpdate += TICKS_TO_WAIT_FOR_NEXT_GAME_UPDATE;	}	render(); // Do this with VSync turned on to avoid tearing}


Key thing to note there is that update() may be called multiple times before render() gets called.

Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse

OK I've changed my game loop to the way you suggested (thanks!) and in general its smoother (I also added an interpolation function for the rendering to smooth it out even more), but I'm still getting a degree of jerking/jumping at the start and sporadically after that. I guess then its because of all the other processes that windows is running. Just out of interest, how do the latest 3D FPS games avoid this problem, because they seem so smooth!? Do they give the game a higher priority over other tasks?

Also, turning on VSync in my ATI control center doesn't seem to do anything. I think this might be because it only affects 3D applications whereas I'm just using the simple SDL_BlitSurface(). Do you know if its possible to turn on VSync in this case?

Thanks again

jimbogd
Quote:Original post by jimbogd
OK I've changed my game loop to the way you suggested (thanks!) and in general its smoother (I also added an interpolation function for the rendering to smooth it out even more), but I'm still getting a degree of jerking/jumping at the start and sporadically after that. I guess then its because of all the other processes that windows is running.
At this point I'd probably recommend writing or obtaining a profiling tool. Capture data about your game across a number of frames, and see how a non-jerky frame differs from a jerky one. It might be as simple as adding some SDL_GetTicks() calls at points throughout your code, and comparing the deltas between them from frame to frame.

Quote:Just out of interest, how do the latest 3D FPS games avoid this problem, because they seem so smooth!? Do they give the game a higher priority over other tasks?
Messing with thread priorities is generally a bad plan. I can't really speak to how they do it because I'm not entirely sure why you're still seeing this jerkyness.

Quote:Also, turning on VSync in my ATI control center doesn't seem to do anything. I think this might be because it only affects 3D applications whereas I'm just using the simple SDL_BlitSurface(). Do you know if its possible to turn on VSync in this case?
Hmm, SDL doesn't seem to have any direct support for VSync - if you were using full OpenGL then you could set it up (SDL_GL_SWAP_CONTROL), but I take it that you're not.

Oh, are you running in windowed or fullscreen mode?

Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse

Hi,

I'm running in fullscreen mode, and yeah I'm just using SDL for rendering, although I plan at some stage to switch to using OpenGL.

The program I'm writing is actually a comparison of different types of game loops, so when complete/working it should help beginners get to grips with game timing in general. I'll upload the whole source code when I get home. If anyone has the time to look at it, maybe it will help pinpoint the problem.

Thanks

jimbogd
OK, I've uploaded the full program and source code here: -
http://www.bu22.com/files/timetest.zip

It's in one source file to keep things simple. Basically you press the space bar to switch game loops, and the timing info etc is written to the screen and more info is written to stdout.

If anyone could take the time to look over it I'd appreciate it. It would be great to get to the bottom of the inconsistent tick problem, and determine if its the code itself or my machine.

As I said, when finished I plan to release this for beginners to show some examples of popular game loops, so any ideas you have for improving it in any way will be gladly taken on board! :)

cheers

jimbogd

This topic is closed to new replies.

Advertisement