Average Frames Per Second Measurement

To measure the frame rate, you need to measure how long each frame takes to render. You do this by using SDL_GetTicks before rendering each frame and subtracting that value with the last value. Normally this method will create inconsistent values due to the way your operating system and cpu work.

A nicer way is to average out the last couple (or so) values. This is done by putting all the values into an array and working out the average frame rendering time. The example is shown below:

#include "SDL.h"

// How many frames time values to keep
// The higher the value the smoother the result is...
// Don't make it 0 or less :)
#define FRAME_VALUES 10

// An array to store frame times:
Uint32 frametimes[FRAME_VALUES];

// Last calculated SDL_GetTicks
Uint32 frametimelast;

// total frames rendered
Uint32 framecount;

// the value you want
float framespersecond;

// This function gets called once on startup.
void fpsinit() {

        // Set all frame times to 0ms.
        memset(frametimes, 0, sizeof(frametimes));
        framecount = 0;
        framespersecond = 0;
        frametimelast = SDL_GetTicks();

}

void fpsthink() {

        Uint32 frametimesindex;
        Uint32 getticks;
        Uint32 count;
        Uint32 i;

        // frametimesindex is the position in the array. It ranges from 0 to FRAME_VALUES.
        // This value rotates back to 0 after it hits FRAME_VALUES.
        frametimesindex = framecount % FRAME_VALUES;

        // store the current time
        getticks = SDL_GetTicks();

        // save the frame time value
        frametimes[frametimesindex] = getticks - frametimelast;

        // save the last frame time for the next fpsthink
        frametimelast = getticks;

        // increment the frame count
        framecount++;

        // Work out the current framerate

        // The code below could be moved into another function if you don't need the value every frame.

        // I've included a test to see if the whole array has been written to or not. This will stop
        // strange values on the first few (FRAME_VALUES) frames.
        if (framecount < FRAME_VALUES) {

                count = framecount;

        } else {

                count = FRAME_VALUES;

        }

        // add up all the values and divide to get the average frame time.
        framespersecond = 0;
        for (i = 0; i < count; i++) {

                framespersecond += frametimes[i];

        }

        framespersecond /= count;

        // now to make it an actual frames per second value...
        framespersecond = 1000.f / framespersecond;

}

int main() {

        SDL_Init(0);

        // put this as close as possible to the start of the loop (before it starts!)
        fpsinit();

        while (1) {

                // render stuff here
                // draw();
                SDL_Delay(500); // 500 should make 2 frames per second.

                fpsthink();
                printf("%f\n", framespersecond);

        }

        SDL_Quit();

        return 0;

}

Weighted averaging

Another method uses weighted averaging of the current measurement with the previous estimate. This has the advantage of being easy to implement, and of using all previous measurements. Of course, the disadvantage is that it uses all previous measurements...

float alpha = 0.2;  // Change at will. Lower means smoother, but higher values respond faster.
Uint32 getticks, frametimedelta, frametimelast;
float frametime, framespersecond;

getticks = SDL_GetTicks();
frametimedelta = getticks - frametimelast;
frametimelast = getticks;

// This is the important part:
frametime = alpha * frametimedelta + (1.0 - alpha) * frametime;

framespersecond = 1000.0 / frametime;

Initializing the variables with sensible values is good, but not that important. Any inaccurate measurements will eventually be flattened out.

Last-Second FPS

This is a pretty simple FPS method, which updates the FPS every second with the average over that period. (I have made it so you can adjust it to more or less than a second, if you want). This is a fragment, you will need the SDL initialisation, includes etc.

#define FPS_INTERVAL 1.0 //seconds.

Uint32 fps_lasttime = SDL_GetTicks(); //the last recorded time.
Uint32 fps_current; //the current FPS.
Uint32 fps_frames = 0; //frames passed since the last recorded fps.

// you would initalise these in a main method, really.

In your paint loop (if you have a separate one, otherwise just your game loop):

void loop()
{
   //YOUR PAINTING STUFF HERE...
   //********//

   fps_frames++;
   if (fps_lasttime < SDL_GetTicks() - FPS_INTERVAL*1000)
   {
      fps_lasttime = SDL_GetTicks();
      fps_current = fps_frames;
      fps_frames = 0;
   }
}

SDL_Average_FPS_Measurement (last edited 2008-04-17 08:18:16 by localhost)