2

プログラムで固定ステップ ループを作成しようとしていますが、何らかの理由で正しく動作しないようです。基本的に私が必要とするのはループです:

while(!over) {
    Update(elapsedtime);
    Draw(elapsedtime);
}

または同様のもので、. Thread.Sleep を使用してみましたが、実際に固定されたステップ ループが得られたかどうかはわかりません。このWeb サイトでソリューションを実装しようとしたときに、方法が見つからないために問題が発生しました。ループの影響を受けるオブジェクトの状態を保存します。これにより、その部分を除外せざるを得なくなり、ループ内に多くのオブジェクトがあると速度が低下しました。

ループ内のすべてのオブジェクトの状態を常に保存しなくても、固定ステップ ループを取得するにはどうすればよいですか?

4

3 に答える 3

1

ゲーム エンジンで作業している場合、Timer はおそらくうまく機能しません。タイマーには、固定ステップ ループを処理して規則的に保つのに十分な精度がありません。

高精度タイマーを使用してこれを実装する必要があります。この場合、Stopwatch クラスを使用する必要があります。 これにより、経過時間を正確に追跡するのに十分な精度が得られます。

どのくらいの頻度で更新するか (ティック単位) を追跡し、ストップウォッチを使用して各更新にかかる時間を測定するだけです。その後、Sleep() 呼び出しを使用してブロックできる可能性がありますが、0 ミリ秒または 1 ミリ秒しかスリープしない場合でも、ほとんどのシステムでスリープの精度は 14 ~ 15 ミリ秒しかないことに注意してください。これによりループが遅くなりすぎる可能性があるため、スピンロックなどを実装する必要がある場合があります (while (waiting) { do something })。Sleep() は、可能であれば CPU を節約できるので便利です。スピン ロックは、待機中に CPU サイクルを消費しますが、精度は向上します。

于 2009-03-15T16:25:03.113 に答える
1

基本的にnティックごとに実行されるループを求めていますか? これはTimerのように聞こえます。BCL にはいくつかのタイマーがあります。サーバー用のタイマーまたはWindow Forms 用のタイマー。

これらの線に沿ってそれらを使用できます。以下は擬似コードであり、これがどのように行われるかを一般的に示すことを意図しています。つまり、コピーして貼り付けるだけではおそらくコンパイルされません。

public class RepeatingTask
{
    public MyObjectState _objectState;

    public RepeatingTask(Timespan interval)
    {
       Timer timer=new Timer(Timer_Tick); //This assumes we pass a delegate. Each timer is different. Refer to MSDN for proper usage
       timer.Interval=interval;
       timer.Start();

    }
    private DateTime _lastFire;
    private void Timer_Tick()
    {
       DateTime curTime=DateTime.Now();
       DateTime timeSinceLastFire = curTime-lastFireTime;
       _lastFire=DateTime.Now(); //Store when we last fired...

       accumulatedtime+=timeSinceLastFire
       while(accumulatedtime>=physicsInterval)
       {
          Update(physicsInterval);
          accumulated-=physicInterval;
       }

               }

}

クロージャーを使用して、タイマーが定義されているメソッドの状態をラップすることもできます。

編集

記事を読み、問題を理解しました。ただし、タイマーを使用することもできますが、彼が示すように、物理エンジンを設定した間隔ごとにエンジンを呼び出すように関数を設定する必要があります。

WPF を使用していますか? doign アニメーションの安定した速度で発生すると思われるイベントがいくつかあります。

編集

私の解釈を示すためにコード サンプルを更新しましたが、基本的に行うことは、物理エンジンの間隔を定義することです。次に、「ループ/タイマーは何でも」を通過するたびに行う必要があるのは、それ以降に経過したリアルタイム時間を決定することです。最後の反復。次に、そのデルタをアキュマレーターに保存します。これを使用して、最後に呼び出してから逃したすべての間隔で物理エンジンを呼び出すまでカウントダウンします。

私が苦労しているのは、ここでタイマーを使用する方が良い場合、専用スレッドをスリープ状態にするか、その他の実装を行うことです。

于 2009-03-15T15:43:17.787 に答える
0

Thread.Sleep は固定ステップ ループを提供するわけではありません。プログラムを続行する前に、指定された時間待機するだけです。実際の頻度は、睡眠がどれほど正確であるか、およびプログラムが各ステップで同じ量の壁時計時間を実行するのにどれだけ一貫しているかによって異なります。ただし、多少のドリフトに対応できる場合は、これで十分であり、確かに最も簡単です。

実際の固定ステップ ループを取得するには、タイマーの有効期限が切れたときにコールバックを介してコードを実行するインターバル タイマーが必要です。もはや実際にはループではありませんが、コードは定期的に実行されることに注意してください。これは、あなたが望むものだと思います。繰り返しになりますが、多少のドリフトが発生する可能性があるため、さらに精度が必要な場合は、次のイベントが適切なタイミングで発生するように、各ステップで間隔を調整する必要がある場合があります。完全に正確にすることは実際には不可能です.ハードウェアベースのインターバルタイマーでさえ精度があります.

于 2009-03-15T15:44:19.313 に答える