Для контроля 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