Контроль FPS в игре на SDL

Для контроля FPS (количества кадров выводимое в секунду) необходим таймер.
Принцип контроля очень прост. В цикле ожидания действий пользователя мы рисуем один кадр, после чего проверяем сколько прошло времени при помощи таймера и если времени прошло меньше чем задано в FPS, то ждём "разницу" при помощи SDL_Delay(), которая похожа на sleep() но может ждать время в миллисекундах.

Реализуется єто довольно просто.
Заголовки:

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "SDL/SDL_ttf.h"
#include <string>

Параметры экрана:

const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

Количество кадров в секунду:

const int FRAMES_PER_SECOND = 20;

Класс таймера можно взять по ссылке выше. Переписывать не буду.
Вся структура программы очень схожа с этой.

Функция которая загружает указанное изображение:

SDL_Surface *load_image( std::string filename ){
    SDL_Surface* loadedImage = NULL;
    SDL_Surface* optimizedImage = NULL;
    loadedImage = IMG_Load( filename.c_str() );
    if( loadedImage != NULL )
    {
        optimizedImage = SDL_DisplayFormat( loadedImage );
        SDL_FreeSurface( loadedImage );
        if( optimizedImage != NULL )
        {
            SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF ) );
        }
    }
    return optimizedImage;
}

Рисует изображение в указанном месте поверхности:

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL )
{
    SDL_Rect offset;
    offset.x = x;
    offset.y = y;
    SDL_BlitSurface( source, clip, destination, &offset );
}

Инициализация библиотеки:

bool init(){
    if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 ){
        return false;
    }
    screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );
    if( screen == NULL ) {
        return false;
    }
    if( TTF_Init() == -1 ){
        return false;
    }
    SDL_WM_SetCaption( "Frame Rate Test", NULL );
    return true;
}

Загрузка ресурсов:

bool load_files(){
    background = load_image( "background.png" );
    font = TTF_OpenFont( "lazy.ttf", 50 );
    if( background == NULL ) {
        return false;
    }
    if( font == NULL ){
        return false;
    }
    return true;
}

Чистка:

void clean_up(){
    SDL_FreeSurface( background );
    SDL_FreeSurface( message );
    TTF_CloseFont( font );
    TTF_Quit();
    SDL_Quit();
}

Главная функция. Та в которой всё задействывается:

int main( int argc, char* args[] ){
    bool quit = false;
    int frame = 0;  // количество фреймов
    bool cap = true;  // флаг ограничения частоты кадров
    Timer fps;  // таймер
    if( init() == false ){
        return 1;
    }
    if( load_files() == false ){
        return 1;
    }
    message = TTF_RenderText_Solid( font, "Testing Frame Rate", textColor );

    while( quit == false ){
        fps.start();
        while( SDL_PollEvent( &event ) ){
            if( event.type == SDL_KEYDOWN ){
                if( event.key.keysym.sym == SDLK_RETURN ){  // если нажат Enter
                    cap = ( !cap );  // переключаем флаг ограничителя
                }
            }else if( event.type == SDL_QUIT ){
                quit = true;  // выход
            }
        }
        apply_surface( 0, 0, background, screen ); // рисуем фон
        apply_surface( ( SCREEN_WIDTH - message->w ) / 2, ( ( SCREEN_HEIGHT + message->h * 2 ) / FRAMES_PER_SECOND ) * ( frame % FRAMES_PER_SECOND ) - message->h, message, screen ); // рисуем надпись
        if( SDL_Flip( screen ) == -1 ){  // обновляем экран
            return 1;
        }
        frame++;

        //если хотим ограничить частоту кадров
        if( ( cap == true ) && ( fps.get_ticks() < 1000 / FRAMES_PER_SECOND ) )
        {
            //ждём разницу во времени
            SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps.get_ticks() );
        }
    }
    clean_up();
    return 0;
}

Мы создали программу таким образом, чтобы она могла работать в двух режимах! Первый - ограниченный. Частота кадров в секунду не превышает 20. Второй - неограниченный - программа работает так быстро как может. При этом переключение работает при помощи Enter
На экран будет выведен неподвижный фон и надпись, которая будет "плыть" сверху вниз.
При нажатии по клавише Enter будет изменятся скорость этого движения..

Исходник, шрифт и фон.

Компилировать с библиотеками SDL, SDL_image и SDL_ttf:

g++ lesson14.cpp -o main -lSDL -lSDL_image -lSDL_ttf

Переделка этого: http://lazyfoo.net/SDL_tutorials/lesson14/index.php

Просмотров:   2816

Комментарии

Добавить комментарий

Plain text

  • HTML-теги не обрабатываются и показываются как обычный текст
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Строки и параграфы переносятся автоматически.
CAPTCHA
Введи эти символы. Ато роботы одолели!