2016-11-28 10 views
2

Это, как я справиться с игровым циклом:Игра SDL/OpenGL работает слишком быстро на экране 144 Гц; не можешь использовать VSync

while (running) { 
    diff = duration_cast<milliseconds>(end - start).count(); 
    start = clock::now(); 

    dt = diff/(16.0); 

    handleInput(); // get input 
    update(dt); // game logic 
    render(); // render game 

    SDL_GL_SwapWindow(window); // swap frame buffer 

    end = clock::now(); 
} 

Он предназначен, чтобы быть фиксированной временным шаг игры заблокирован 60 кадров в секунду (это переделано эмуляция из игры SNES), однако он работает на 144 timestep на моем экране 144hz, делая это слишком быстро. Vsync не может решить это, так что может?

+3

Возможно, не называть 'update (dt);' на каждой итерации. –

+0

почему я не должен? – Accumulator

+0

Потому что обновление каждые 1/14 секунды слишком быстро! –

ответ

2

Вот краткий пример того, как можно реализовать цикл игры:

int32_t tickInteval = 1000/FPS; // frequency in Hz to period in ms 
uint32_t lastUpdateTime = 0; 
int32_t deltaTime = 0; 
while (running) { // running condition 
    uint32_t currentTime = SDL_GetTicks(); 
    deltaTime = currentTime - lastUpdateTime; 

    int32_t timeToSleep = tickInteval - deltaTime; 
    if(timeToSleep > 0) 
    { 
     SDL_Delay(timeToSleep); // energy saving 
    } 

    update(deltaTime); // game logic 
    lastUpdateTime = currentTime; 
} 

Я бы рекомендовал смотреть близко на эту тему.


UPD.
Возможно, это связано с переполнением uint32_t. И да, это переполнится. После почти двух месяцев непрерывного запуска игры (точнее, 49.7 дней). Что будет тогда? currentTime будет очень маленьким положительным целым числом, lastUpdateTime будет очень большим положительным целым числом. Но вычитание двух не будет переполняться, несмотря ни на что. Более того, если разница не вписывается в int32_t, она будет обернута по модулю UINT_MAX + 1, что приведет к небольшому положительному целому числу, которое будет точным числом тиков, эти два значения отличаются (в отношении неподписанного переполнения одного).

+0

Не является SDL_Delay ненадежным и может длиться дольше, чем ожидалось? – Accumulator

+0

@Omega same with 'std :: this_thread :: sleep_for' -" Блокирует выполнение текущего потока, по крайней мере, для указанного sleep_duration ". Это особенность операционных систем реального времени. – teivaz

+0

Так что я не могу гарантировать, что он не упадет ниже 59/60 FPS? – Accumulator