スリープを使用して単一スレッドでロジック/更新コードをレンダリング/描画コードから分離する


9

私は、ゲームオブジェクトの速度はFPSによって妨げられるべきではなく、時間に基づくべきであると読みました。更新/描画コードを分離して、描画速度を制限せずにパフォーマンスを最大化し、時間に基づいて一定のロジック更新速度を提供するにはどうすればよいですか?

私の現在の疑似コードは次のとおりです

loop
{
    draw();
    if (ticksElapsed() > 100)
    {
        update();
        ticks+= ticksElapsed();
    }        
}

問題は、描画コードがupdate()レートのパフォーマンスを妨げていることです。また、スリープ状態になると、描画機能とロジック機能の両方が使用できなくなるため、CPUが100%消費されます。

私もSDLを使用していますが、vsyncオプションがないようです。固定および可変時間ステップという用語も聞いたことがありますが、sleep()でそれをどのように行うことができるかわかりません。


1
待機するためだけに100%のCPUパワーを浪費する必要はありません。ticksElapsed()<100の場合は、whileループの最後にsleep(0)を配置します。他にスレッドがない場合、OSはすぐにスレッドに戻ります実行したいです。しかし、もはや100%のCPUパワーを無駄にしていません。
Maik Semder、2011

ただし、このような1スレッドセットアップの最善の解決策は、vsyncを使用することです。vsyncができない場合は、ターゲットフレームレートに達するまでループでsleep(0)を呼び出し、更新して描画します
Maik Semder

回答:


3

コードスニペットでは、描画と更新に15ミリ秒(60fps)未満かかった場合にビジー待機して、固定時間ステップモードでゲームを実行しようとしているようです。これは可能であり、スリープする時間を正確に把握していないため、sleep呼び出しを使用してこれを実行することはできないと推測しました。ビジー待機ループは良い解決策です。

ただし、更新と描画が15msを超える場合を考えてみてください。これで、ゲームの描画と更新が遅くなります。この状態を検出してフレームをドロップする(描画をスキップし、再び同期するまで直接更新する)ことができますが、コンピューターの速度が低下するだけの場合は、追いつきません。

他の解決策は、更新ロジックを固定時間に依存しないようにすることです。このために別のスレッドは必要ありません。物事の移動速度を再指定する必要があります。1ティックあたり5ピクセルではなく、1秒あたり50ピクセルを使用する必要があります。これを実現するには高精度のタイマーが必要です。すべての更新ロジックがタイマーにアクセスして、最後の更新から経過した時間を確認できる必要があります。

基本的には次の場所から行きます:

void UpdatePlayer()
 player.x += 10;

void UpdatePlayer(float elapsedSeconds) //the total seconds elapsed since last update
 player.x += walkspeed * elapsedSeconds;

だから私のエンジンは常に100%を消費し、それについて私が本当にできることは何もないのですか?
Oskenso Kashi 2011

1
スケジューラーが許可する限りのサイクルを消費しますが、ゲームをプレイしている間は他の多くのことを実際に行うことができないため、それは実際には問題ではありません:)。
ロイT.

@Oskensoただし、複数のスレッドを使用する場合は問題です。メインスレッドでは、他のスレッドを最大限に実行できず、whileループで大量の計算能力を浪費します。スリープを考慮する必要があります
Maik Semder

@Maik Semder:sleep(x)が正確でないという解決策はありますか?スリープ間隔が経過すると、スレッドを実行する準備が整います。ただし、準備ができたスレッドがすぐに実行されるとは限りません。それはスケジューラ次第です。2つのスレッドを使用している場合、他の解決策があります。そのためには、この優れた記事を参照してください。altdevblogaday.com
Roy T.

1
@Roy sleep(0)が解決策です。実行したいスレッド(Sleep WinAPI)がない場合はすぐに戻り、他のスレッドに実行の機会を与えます。他のスレッドがメインスレッドに代わりに実行する機会を与えない場合は、スレッド化の問題がありますが、そもそもsleepを呼び出さないことで他のすべてをブロックすると、事態はさらに悪化し、ほとんど解決策にはなりません。重要なのは、sleep(0)を呼び出して、目標の固定フレームレートに達するまでの経過時間をテストすることです。これにより、待機のためだけに100%のCPUを無駄にしないでください。
Maik Semder、2011
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.