3

基本的に画面を (一人称で) 走り回ることができる学習目的で (C++ で gl/glut を使用して) プログラムを作成しました。シーンの周りにいくつかの立体があります。別のコンピューターで実行しようとしましたが、速度がまったく異なるため、件名で検索したところ、現在次のようなことを行っています。

アイドル機能:

    start = glutGet (GLUT_ELAPSED_TIME);
    double dt = (start-end)*30/1000;

    <all the movement*dt>

    glutPostRedisplay ();

    end = glutGet (GLUT_ELAPSED_TIME);

表示機能:

    <rendering for all objects>

    glutSwapBuffers ();

私の質問は次のとおりです。これは適切な方法ですか?アイドル機能後のシーンが表示されていますよね?

end = glutGet (GLUT_ELAPSED_TIME) を glutSwapBuffers () の前に配置しようとしましたが、何の変化にも気づきませんでしたが、glutSwapBuffers () の後に配置すると、かなり遅くなり、時々停止することさえあります。

編集:私が考えている方法では、end-start は、すべての描画が完了してから動きの更新の前に経過した時間になるはずであることに気付きました。ここで考慮されていない唯一の時間は、コンピューターがすべての動きを実行するのにかかる時間です。(ほとんど何もないはずですか?)

これが紛らわしすぎる場合は申し訳ありません..

前もって感謝します。

4

7 に答える 7

4

「Glut」が何であるかはわかりませんが、ゲーム開発の一般的なルールとして、コンピューターがディレクティブを処理できる速度に基づいて移動速度を決定することは決してありません。それが彼らが 80 年代後半に行ったことであり、古いゲームをプレイすると物事が光の速さで動くのはそのためです。

私はタイマーを設定し、明確で特定の時間イベントに基づいてすべての動きを行いました.

于 2010-03-03T15:56:33.913 に答える
1

タイマーは使いません。PCが遅すぎたり、忙しすぎて必要な速度で実行できない場合は、問題が発生したり、イベントが積み重なったりする可能性があります。ループを可能な限り高速に実行し、毎回経過時間を計算して、これを移動/ロジックの計算に入れます。

内部的には、実際には小さな固定時間のサブステップを実装する場合があります。これは、可変のタイムステップですべてを正しく機能させることは、x + = v*dtほど単純ではないためです。

このようなものについてはgamedev.netを試してください。たくさんの記事と忙しいフォーラム。

于 2010-03-03T16:59:28.663 に答える
1

「正しい」方法でそれを行う方法についてはたくさんの答えがありますが、GLUT を使用しており、GLUT は単純さとプラットフォームの独立性を維持するために「正しい」方法を犠牲にすることがあります。GLUT の方法は、タイマー コールバック関数を glutTimerFunc() に登録することです。

static void timerCallback (int value)
{
    // Calculate the deltas

    glutPostRedisplay(); // Have GLUT call your display function
    glutTimerFunc(elapsedMilliseconds, timerCallback, value);
}

lapseMilliseconds を 40 に設定すると、この関数は 1 秒間に 25 回弱呼び出されます。コンピューターがデルタ計算コードを処理するのにかかる時間によって異なります。そのコードをシンプルに保つと、各システムが表示関数を 40 ミリ秒未満で処理できる限り、アニメーションはすべてのシステムで同じ速度で実行されます。柔軟性を高めるために、コマンド ライン オプションを使用するか、インターフェイスにコントロールを追加することで、実行時にフレーム レートを調整できます。

初期化プロセスを呼び出して、タイマー ループを開始しglutTimerFunc(elapsedMilliseconds, timerCallback, value);ます。

于 2010-03-04T14:23:58.733 に答える
1

必要なすべての情報を提供するゲーム ループに関する完璧な記事があります。

于 2010-03-04T13:21:50.787 に答える
1

高解像度タイマー (Windows の QueryPerformanceCounter など) を設定し、すべてのフレーム間の時間を測定します。この時間は、デルタ時間 (dt) と呼ばれ、すべての移動計算で使用する必要があります。フレームごとに、オブジェクトの位置を次のように設定します。

obj.x += 100.0f * dt; // to move 100 units every second

dt の合計は常に 1 秒で 1 になるため、上記のコードは、フレームレートに関係なく、x を 1 秒ごとに 100 ずつ増やします。時間とともに変化するすべての値に対してこれを行う必要があります。このようにして、コンピューターがロジックを処理する速度 (フレームレートに依存) に依存するのではなく、すべてのマシンで同じ速度 (フレームレートに依存しない) でゲームが進行します。これは、フレームレートが低下し始めた場合にも役立ちます。ゲームが突然スローモーションで実行されるのではなく、レンダリングの頻度が減るだけで、同じ速度で進行し続けます。

于 2010-03-03T16:46:59.367 に答える
0

これは非常に難しい質問です。

最初に自分自身を確認する必要があるのは、アプリケーションを実際に同じ速度で実行したいのか、それとも単に同じ速度で実行しているように見せたいのかということです。99% の場合、同じ速度で実行されているように見せたいだけです。

アプリケーションの高速化と低速化という 2 つの問題があります。

現在の速度に合わせて動的な LOD を調整する必要があるため、アプリケーションを高速化することは非常に困難です。これは、グラフィックスだけでなく、すべての LOD を意味します。

アプリケーションを遅くするのはかなり簡単です。スリープまたは「ビジー待機」の 2 つのオプションがあります。基本的に、シミュレーションのターゲット フレーム レートによって異なります。シミュレーションが 50 ミリ秒などをはるかに上回っている場合は、スリープできます。問題は、スリープ中はプロセス スケジューラに依存し、平均的なシステムで 10 ミリ秒の粒度で動作することです。

忙しいゲームでは、待つことはそれほど悪い考えではありません。シミュレーションを更新してフレームをレンダリングしてから、次のフレームに時間アキュムレータを使用します。シミュレーションなしでフレームをレンダリングする場合は、状態を補間して滑らかなアニメーションを取得します。この件に関する非常に優れた記事がhttp://gafferongames.com/game-physics/fix-your-timestep/にあります。

于 2010-03-04T13:16:30.363 に答える
0

私はゲームプログラマーであり、これを何度も行ってきました。

ほとんどのゲームは、たとえば 60hz のように一定の時間単位で AI を実行します。また、画面のティアリングを避けるためにほとんどがモニターの更新に同期されるため、マシンが非常に高速で 1000 fps を実行できる場合でも、最大レートは 60 になります。そのため、マシンの速度が遅く、20 fps で実行されている場合、レンダリングごとに AI の更新関数を 3 回呼び出すことになります。このようにすることで、小さい値の丸め誤差の問題が解決され、AI の更新レートがマシンの速度から分離されるため (オンライン マルチプレイヤー ゲームに必要)、複数のマシン間で AI が決定論的になります。

于 2010-03-03T18:20:44.837 に答える