Контроль 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

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

 

Похожий код:

Фото аватара
Алексей Петров

Программист, разработчик с 5 летним опытом работы. Учусь на разработчика игр на Unity и разработчика VR&AR реальности (виртуальной реальности). Основные языки программирования: C#, C++.

Оцените автора
Бла, бла код
Добавить комментарий