0

これは私のゲームループコードです:

        while (shouldUpdate)
        {
            timeSinceLastUpdate = 0;
            startTime = clock();

                while (timeAccumulator >= timeDelta)
                {
                    listener.handle();
                    em.update();
                    timeAccumulator -= timeDelta;
                    timeSinceLastUpdate += timeDelta;
                }

            rm.beginRender();
                _x->draw();
            rm.endRender();

            timeAccumulator += clock() - startTime;
        }

ほぼ完全に実行されますが、_x の代わりに 1 秒に数回 (更新で行うテスト エンティティは x++ だけです)、1 ピクセル右に移動し、実際には 2 ピクセル右に移動し、いくつかのジッターがあります。これは顕著なラグ/ジッター効果です。私は clock() が十分に正確ではないと推測しています。では、このゲーム ループを改善するにはどうすればよいでしょうか?

問題がある場合は、SDL と SDL_image を使用します。

編集:時計よりも正確なことをした後、何も変わりませんでした。しかし、私が理解したことは、すべて timeDelta のおかげだということです。これは、この投稿を作成したときに timeDelta が定義された方法です。

double timeDelta = 1000/60;

しかし、いじりながら別のものとして定義すると...

double timeDelta = 16.666666;

ゲームが始まって最初の数秒間、バターのようにスムーズだったことに気づきました。しかし、ほんの数秒後、ゲームは大きく途切れてからスムーズに戻り、そのようなことを繰り返しました. 追加した 6 の数 (または . の後の何か) が多いほど、ゲームは最初はスムーズでしたが、遅延が発生しにくくなりました。フローティングエラーが攻撃しているようです。それで、私は何ができますか?

EDIT2:私はあまりにも多くのことを試しましたが、今では面白くありません...誰かがループの数学の部分で私を助けてくれますか? それが原因なので・・・

編集 3: テスト プログラムを何人かの人に送りました。ここでテストしたい人は、(src): https://www.mediafire.com/?vfpy4phkdj97q9j

EDIT4:ソース コードへのリンクを変更しました

4

1 に答える 1

7

それはほぼ間違いなく、clock()

std::chronoまたはを使用SDL_GetTicks()して、エポックからの時間を測定します。

C++ API を好むという理由だけで使用することをお勧めしstd::chronoます。以下に例を示します。

int main(){
    using clock = std::chrono::high_resolution_clock;
    using milliseconds = std::chrono::milliseconds;
    using std::chrono::duration_cast;

    auto start = clock::now(), end = clock::now();
    uint64_t diff;


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

        // do time difference related things

        end = clock::now();
    }
}

指定されたデルタの後にのみ更新するには、次のようにループを実行します。

int main(){
    auto start = clock::now(), end = clock::now();
    uint64_t diff = duration_cast<milliseconds>(end - start).count();

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

        if(duration_cast<nanoseconds>(clock::now() - accum_start).count() >= 16666666){
            // do render updates every 60th of a second
            accum_start = clock::now();
        }

        end = clock::now();
    }
}

startとは両方とも、以前に として定義されendたタイプstd::chrono::time_point<clock>になります。clockstd::chrono::high_resolution_clock

time_point2の差はstd::chrono::duration、ナノ秒、ミリ秒、またはその他の好きな単位にすることができます。それをミリ秒にキャストし、 を取得しcount()て に割り当てますuint64_t。必要に応じて、他の整数型を使用できます。

diffはあなたがあなたのを計算する方法ですtimeDelta。定数として設定しないでください。それが正しいと確信していても、あなたは間違っています。1 秒未満の最小値であっても、フレームごとに異なるデルタが発生します。

一定のフレーム差を設定したい場合は、SDL_GL_SetSwapIntervalを使用して垂直同期を設定します。

編集

あなたのために、この例の git リポジトリを作成しました。フレームごとに調整された差を取得するためmain.cppに乗算する場所に注意してください。diffこの調整 (または調整の欠如) は、あなたのぎくしゃくしたところです。

于 2015-07-16T03:59:37.790 に答える