Я использую SDL 1.2 и VS2008 для меньшего игрового приложения. Недавно я (после получения некоторых идей из других постов на SO, которые я не могу найти сейчас, извините, если вы считаете, что я должен был связать ваш вопрос для справки) переписал мой цикл игры, чтобы не использовать Sleep или SDL_Delay для синхронизации. Вместо этого я называю свою игровую логику с известной частотой и вычисляю расстояния и местоположения на основе фактического временного шага.
Когда я делал это, я ожидал, что FPS будет ограничен SDL_Flip частотой кадров экрана (vsynch?), Но в результате я получил примерно 300 FPS на моей машине с Windows 7. Что может быть причиной этого? Можете ли вы запустить весь игровой цикл (включая SDL_Flip) несколько раз между vsynchs монитора? Может быть, поведение на разных машинах отличается или SDL_Flip никогда не должен синхронизироваться с vsynch? Я не вижу никаких мерцаний или других эффектов несинхронного обновления экрана, которые я ожидал бы.
Вот мой игровой цикл для справки:
void GraphicsFramework::run()
{
Uint32 last_input_check = 0;
Uint32 last_logics_check = 0;
while(true)
{
Uint32 now = SDL_GetTicks();
if(now - last_input_check > 10) // Every 10 millisecond
{
if(!processEvents())
{
return;
}
last_input_check = now;
}
if(now - last_logics_check > 20) // Every 20 milliseconds
{
handleGameLogics();
last_logics_check = now;
}
draw(); // No FPS limitation
m_Window.flipSurface(); // Calls SDL_Flip(surface)
m_ActualFrameTime = SDL_GetTicks() - now;
}
}
Редактировать:
Фиксированный FPS с занятым ожиданием выглядел бы так. замещать
m_ActualFrameTime = SDL_GetTicks() - now;
с
do
{
m_ActualFrameTime = SDL_GetTicks() - now;
} while ((Uint32)(1000/m_ActualFrameTime) > getDesiredFPS());
Это дает более стабильный результат, чем использование SDL_Delay или Sleep, для которого вы получаете несколько изменяющийся FPS, по крайней мере, на моей машине. И то и другое, конечно, нарушает синхронизацию processEvents () в примере.
Также добавляем вариант SDL_Delay для полноты:
Sint32 timeToSleep = (Uint32)(1000/getDesiredFPS()) - m_ActualFrameTime;
if(timeToSleep > 0)
{
SDL_Delay((Uint32)timeToSleep);
}
SDL_Flip просто выталкивает то, что у вас есть на поверхности, на экран. Это не имеет ничего общего с FPS. И нет, вы не должны использовать SDL_Flip несколько раз в одном и том же цикле, вы должны сделать это после того, как обновите свою поверхность и будете готовы показать ее на экране.
Я думаю, что лучше всего управлять fps SDL_Delay (который просто вызывает сон).