5

Visual C++ 2008 Express と Ogre3D SDK を使用してゲームをプログラミングしています。

私のコア ゲームプレイ ロジックは、1 秒あたり 100 回実行するように設計されています。簡単にするために、'gamelogic()' というメソッドとします。これは時間ベースではないため、ゲーム時間を 1 秒「進める」には、「gamelogic()」を 100 回呼び出す必要があります。「gamelogic()」は、ゲームの画面レンダリングに比べて軽量です。

Ogre には、フレームを描画しようとしているときとフレームの描画を終了したときにコードに通知する「リスナー」ロジックがあります。フレーム レンダリングの直前に「gamelogic()」を呼び出すと、ゲームプレイは画面のレンダリング速度に大きく影響され、5 fps から 120 fps まで変化する可能性があります。

頭に浮かぶ簡単な解決策は次のとおりです。最後にレンダリングされたフレームからの経過時間を計算し、次のフレームの前に「gamelogic()」をこの回数だけ呼び出します: 100 * timeElapsedInSeconds

ただし、それを行う「正しい」方法はマルチスレッドを使用することだと私は主張します。「gamelogic()」を毎秒 100 回実行する別のスレッドがあります。

問題は、これをどのように達成するか、および 2 つの別々のスレッド間で競合が発生した場合に何ができるかです。Ogre が同時に画面をレンダリングしている間にゲームロジックが画面コンテンツ (3D オブジェクト座標) を変更します。

よろしくお願いします。

4

3 に答える 3

7

これが初めてのゲームアプリケーションである場合、マルチスレッドを使用して結果を達成することは、最初のゲームで実際に取り組む必要があるよりも多くの作業になる可能性があります。ゲームループとレンダリングループを異なるスレッドで同期することは、簡単に解決できる問題ではありません。

正しく指摘しているように、レンダリング時間はゲームの「速度」に大きく影響する可能性があります。ゲームロジックを設定されたタイムスライス(つまり、1/100秒)に依存させないことをお勧めします。現在のフレーム時間に依存させます(現在のフレームのレンダリングにかかる​​時間がわからないため、最後のフレーム時間です)。

通常、私は以下のようなものを書きます(私が書いたものは非常に単純化されています):

float Frametime = 1.0f / 30.0f;
while(1) {
    game_loop(Frametime);      // maniuplate objects, etc.
    render_loop();             // render the frame
    calculate_new_frametime();
}

ここで、Frametimeは、現在のフレームが取った計算されたフレーム時間です。ゲームループを処理するときは、前のフレームのフレームタイムを使用しています(したがって、初期値を1/30秒や1/15秒などの妥当な値に設定します)。前のフレームタイムで実行すると、必要な結果を得るのに十分に近いです。その時間枠を使用してゲームループを実行してから、コンテンツをレンダリングします。一定の時間間隔を想定しないようにゲームループのロジックを変更する必要があるかもしれませんが、一般的にこれらの種類の修正は非常に簡単です。

非同期のゲーム/レンダリングループは最終的に必要なものかもしれませんが、それは解決するのが難しい問題です。これには、オブジェクトとその関連データのスナップショップを取得し、それらのスナップショットをバッファーに入れてから、バッファーをレンダリングエンジンに渡すことが含まれます。そのメモリバッファは、レンダリングループがメモリバッファから読み取っているときにゲームループに書き込まれないように、クリティカルセクションの周囲で正しく分割する必要があります。レンダリングループに渡す前に、関連するすべてのデータをバッファにコピーするように注意する必要があります。さらに、どちらかが完了するのを待っている間、ゲームまたはレンダリングループのいずれかを停止するロジックを作成する必要があります。

この複雑さから、最初にもっと連続した方法で書くことをお勧めします(経験がない限り)。その理由は、最初に「簡単な」方法で実行すると、コードの動作、レンダリングエンジンの動作、レンダリングエンジンに必要なデータの種類などについて学習する必要があるためです。複雑なゲーム開発では、マルチスレッドの知識が絶対に必要です。最近では、それをうまく行う方法を知るには、ゲームシステムが互いにどのように相互作用するかについての深い知識が必要です。

于 2009-05-28T14:16:54.880 に答える
1

プレイヤーが応答するよりもコア ゲーム ロジックを高速に実行しても、それほど多くのメリットはありません。これが本当に役立つのは、物理シミュレーションの場合だけです。物理シミュレーションでは、高速で固定された時間ステップで実行すると、シミュレーションの動作がより一貫したものになります。

それとは別に、フレームごとに 1 回ゲーム ループを更新し、固定の時間デルタに頼るのではなく、可変の時間デルタを渡します。マルチスレッドを実行することで得られるメリットは、特にこれが初めてのゲームである場合は、コストに比べて最小限です。

于 2009-09-05T09:13:45.377 に答える
0

レンダリング可能なオブジェクトをダブル バッファリングすることは、検討できるアプローチです。つまり、レンダリング コンポーネントは、すべてのゲーム アクションが 2 番目のバッファー内の関連オブジェクトを更新したときに更新される 1 つのバッファーを使用しています。

しかし、個人的には気に入らないので、私は Mark のアプローチを採用したいと思っています (そして頻繁に採用しています)。

于 2009-09-05T09:05:35.503 に答える