2016-11-28 81 views
2

這是我如何處理遊戲循環:SDL/OpenGL遊戲在144Hz屏幕上運行速度太快;不能使用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(); 
} 

它的目的是成爲一個固定的時間步長的比賽鎖定到60FPS(它是一個SNES遊戲的重新制作仿真),但是它運行我的144hz屏幕上有144個時間步,這太快了。 Vsync無法解決這個問題,那麼可以做什麼?

+3

也許在每次迭代時都不要調用update(dt);' –

+0

爲什麼我不應該? – Accumulator

+0

因爲每秒更新一次/ 144秒就太快了! –

回答

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與'std :: this_thread :: sleep_for'相同 - 「」阻止當前線程執行至少指定的sleep_duration「。這是非實時操作系統的特徵。 – teivaz

+0

所以我不能確保它不會突然下降到59/60 FPS以下? – Accumulator