4

これは私がゲームループを処理する方法です:

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 はこれを解決できません。

4

2 に答える 2

4

以下は、ゲーム ループの実装方法の簡単な例です。

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;
}

このトピックをよく見ることをお勧めします。


アップデート。オーバーフロー
が懸念される場合があります。uint32_tそしてはい、それはあふれます。ゲームをほぼ 2 か月中断せずに実行した後 (正確には 49.7 日)。ではどうなるでしょうか?currentTimeは非常に小さい正の整数にlastUpdateTimeなり、非常に大きな正の整数になります。しかし、2 の減算は何があってもオーバーフローしません。さらに、差が収まらない場合は、これら 2 つの値の正確なティック数となる小さな正の整数になるint32_tモジュロの周りにラップされUINT_MAX + 1ます (1 つの符号なしオーバーフローに関して)。

于 2016-11-28T23:22:06.943 に答える