Improved Timing

I have often downloaded demos that were either running to fast or to slow for my computer. A nice demo that runs so fast that it more looks like a flickering set of images or where the mouse or other controls makes the screen spin out of control is just as annoying as viewing something at 3 fps.

I have therefore written this small article about timing.

To Fast!

Demo's made on a slow computer that are moved to a fast one are often very annoying. Mainly because it is very easy to make a demo run slower, but it is extremely difficult to make it run faster. The easiest way is to time all the control functions. Take a look at the following code:

#include <time.h>
// Timing Variables
clock_t time_now, movement_timer = 0;
// Main Loop
while (running) {
	// Handle Messages…
	time_now = clock();
	if(time_now - movement_timer > CLK_TCK/30) {
		movement_timer = time_now;
		// Update Controls…
	}
	// Drawing…
}

Most programs are built more or less like this. The main procedure typically holds the loop (the "while" loop) where all the handling is done. This loop reads and handles input messages from keys and the mouse. The loop also contains the drawing of the graphics. If you move the handling into a timed statement (the "if" line) you can limit the updating of the game to a specified maximum per second. In this case it will be 30 times per sec.

Note that the message handling is still done outside the "if" statement, so you need to keep the mouse or keys pressed and un-pressed states in some sort of variable.

The update control part is not only the user controls (mouse and keys) it also handles moving monsters, running animations etc, everything that should be timed. The drawing routine may still run at 120 fps, the movement update remains at 30.

To Slow!

This is a much more difficult issue, but I would like to add some ideas. First you spend days on improving and optimizing your demo to get the best performance you can. There are no ideas in this article to magically improve the basic speed. That’s up to you… but:

When you have squeezed all the performance out of your system, you might improve it for the user. You may have the best demo or game ever, but if it runs awful on the end users machine it doesn’t matter.

I have made a flight simulator that I will use as an example. In the simulator there is one factor that greatly influence the performance. This is the view range (i.e. the distance to the horizon). Now this distance can easily be changed. It is in one of my config files and is used as a variable inside the program. If it changes I only have to set a few things like the depth plane, the fog etc and the variable.

Now I have added a small function (in the main loop) just like in the example above;

time_now = clock();
++frames;
if(time_now - last_time > CLK_TCK*2) {
	// Calculate How Many Frames Per Second We Run
	fps = (frames*CLK_TCK)/(time_now-last_time);
	last_time = time_now;
	frames = 0;
	// Depending On The Fps, Change The View Range
	if ((fps>=0) && (fps<24)) { // Running Slow, Lets Improve Performance
		i = (int)(fps-24);
		if (fps>=20) {
			ChangeViewRangeBy(i); // A Small Change When We Run Between 20 And 24 Fps
		} else if (fps>10) {
			ChangeViewRangeBy(-i*i); // A Large Change When We Run Between 10 And 20 Fps
		} else {
			ChangeViewRangeBy(-DepthPlane / 2); // Below 10 Fps, We Half The View Range!
		}
	} else if (fps>40) {
		i = (int)(fps-40);
		ChangeViewRangeBy(i); // Above 40 Fps We Slightly Increase The View Range
	}
}

The effect is noticeable, but it may have side effects. I tried it on a very slow machine and the tip of the plane was almost at the end of the world… however, this may be handled later. If the above code looks like the code normally used to calculate fps you are correct. It is very similar.

In the flight simulator I have added a small view of the world when you load it. Here you can see the plane in the airfield, gently turning around, while the game waits for the user to press a key and start the game. This is where it comes in really handy. This small screen is really measuring the performance of the computer and finding the best view range for the game – before the player starts.

Now not all games and demos have such a nice and easy parameter as the view range, but you can use the method to remove performance requiring effects. I case of "monsters" you can divide the AI into handling them in turns. Like handling half of the "monsters" in one tick and the other half in the second tick. You may even divide them further to allow for more flexibility. If all "monsters" are divided into 100 pools, you may handle them dynamically like the view range above. Run a variable amount of pools per tick based on the fps, just like the view range.

If you download the above mentioned flight simulator (can be found on my website www.dragonslayer.dk or on the NeHe site under "F" in the Downloads section – you need release 1.2), you may press the "d" key to view debug information, and among others you can turn on/off view range adjustment by pressing "v".