Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Achieving a constant frame rate in SDL

Tags:

sdl

frame-rate

I'm trying to make an SDL program that runs with a constant frame rate. However I'm finding that even though my program is lagging a lot and skipping a lot of frames (even though it's running at a low frame and isn't rendering much).

Do you guys have any suggestions to make my program run smoother?

#include "SDL.h"
#include "SDL/SDL_ttf.h"

//in milliseconds
const int FPS = 24;
const int SCREENW = 400;
const int SCREENH = 300;
const int BPP = 32;

void apply_surface(int x, int y, SDL_Surface* source, SDL_Surface* destination) {

    SDL_Rect offset;

    offset.x = x;

    offset.y = y;



    if(SDL_BlitSurface(source, NULL, destination, &offset) < 0) {
        printf("%s\n", SDL_GetError());
    }

}

int main(int argc, char* argv[]) {
    //calculate the period
    double period = 1.0 / (double)FPS;
    period = period * 1000;
    int milliPeriod = (int)period;
    int sleep;

    SDL_Init(SDL_INIT_EVERYTHING);
    TTF_Init();

    TTF_Font* font = TTF_OpenFont("/usr/share/fonts/truetype/freefont/FreeMono.ttf", 24);
    SDL_Color textColor = { 0x00, 0x00, 0x00 };

    SDL_Surface* screen = SDL_SetVideoMode(SCREENW, SCREENH, BPP, SDL_SWSURFACE);
    SDL_Surface* message = NULL;

    Uint32 white = SDL_MapRGB(screen->format, 0xFF, 0xFF, 0xFF);

    SDL_Event event;

    char str[15];

    Uint32 lastTick;
    Uint32 currentTick;
    while(1) {
        while(SDL_PollEvent(&event)) {
            if(event.type == SDL_QUIT) {
                return 0;
            }
            else {
                lastTick = SDL_GetTicks();

                sprintf(str, "%d", lastTick);
                message = TTF_RenderText_Solid(font, str, textColor);
                if(message == NULL) { printf("%s\n", SDL_GetError()); return 1; }

                //the actual blitting
                SDL_FillRect(screen, &screen->clip_rect, white);
                apply_surface(SCREENW / 2, SCREENH / 2, message, screen);

                currentTick = SDL_GetTicks();

                //wait the appropriate amount of time
                sleep = milliPeriod - (currentTick - lastTick);
                if(sleep < 0) { sleep = 0; }
                SDL_Delay(sleep);

                SDL_Flip(screen);
            }
        }
    }

    TTF_CloseFont(font);
    TTF_Quit();
    SDL_Quit();

    return 0;
}
like image 956
SDLFunTimes Avatar asked Mar 30 '10 20:03

SDLFunTimes


People also ask

How is SDL FPS calculated?

To calculate frames per second, you just take the number of rendered frames and divide it by the seconds passed.

What is constant frame rate?

Constant Frame Rate (CFR) makes your new video exactly one frame rate throughout. When used with Same as Source , HandBrake will detect the frame rate of your Source and make sure any variable portions are made constant at the same rate.

How do I limit FPS in sdl2?

Capping your FPS is quite simple: just subtract your frame time from your desired time and wait out the difference with SDL_Delay(). However, this function only takes delay in milliseconds—unfortunately, you cannot cap your FPS with very much precision. (At least with SDL—look at std::chrono for more.)

Is constant frame rate better?

2 Prefer CFR - Constant Frame RateVFR is much better than CFR. However, some video editing software such as Adobe Premiere does not support a VFR video. In this case, you have to choose "CFR." If you select "60" FPS with the CFR option, you will normally get a "constant 60FPS video."


2 Answers

There is a small example of how to do this at http://www.libsdl.org/release/SDL-1.2.15/docs/html/guidetimeexamples.html:

#define TICK_INTERVAL    30

static Uint32 next_time;

Uint32 time_left(void)
{
    Uint32 now;

    now = SDL_GetTicks();
    if(next_time <= now)
        return 0;
    else
        return next_time - now;
}


/* main game loop */

    next_time = SDL_GetTicks() + TICK_INTERVAL;
    while ( game_running ) {
        update_game_state();
        SDL_Delay(time_left());
        next_time += TICK_INTERVAL;
    }
like image 157
SamB Avatar answered Sep 30 '22 19:09

SamB


Don't sleep.

Instead, use a linear interpolation function to compute your position given the current time each time through the main loop. Doing this will guarantee that no matter the hardware, space ships arrive at their destinations at the same time (though on a fast machine, you'll see more of the steps in between).

Also there are other interpolation/blending functions (like linear ease in, ease out, quadratic ease in/out, cubic, etc.) for other cool effects.

Check this link out: Frame Rate Independent Linear Interpolation

like image 35
dicroce Avatar answered Sep 30 '22 20:09

dicroce