2

私はただの馬鹿かもしれませんが、一日中ゲームループを実装しようとしていて、クリックしていません。私は文字通り、Google で見つけたすべての記事を読みましたが、問題は、それらがすべて異なるタイミング メカニズムを使用しているため、特定の状況に適用するのが難しいことです (ミリ秒を使用するものもあれば、ティックを使用するものもあります)。

基本的にClock、ゲーム ループが実行されるたびに更新されるオブジェクトがあります。

internal class Clock {
    public static long Timestamp {
        get { return Stopwatch.GetTimestamp(); }
    }

    public static long Frequency {
        get { return Stopwatch.Frequency; }
    }

    private long _startTime;
    private long _lastTime;
    private TimeSpan _totalTime;
    private TimeSpan _elapsedTime;

    /// <summary>
    /// The amount of time that has passed since the first step.
    /// </summary>
    public TimeSpan TotalTime {
        get { return _totalTime; }
    }

    /// <summary>
    /// The amount of time that has passed since the last step.
    /// </summary>
    public TimeSpan ElapsedTime {
        get { return _elapsedTime; }
    }

    public Clock() {
        Reset();
    }

    public void Reset() {
        _startTime = Timestamp;
        _lastTime = 0;
        _totalTime = TimeSpan.Zero;
        _elapsedTime = TimeSpan.Zero;
    }

    public void Tick() {
        long currentTime = Timestamp;

        if (_lastTime == 0)
            _lastTime = currentTime;

        _totalTime = TimestampToTimeSpan(currentTime - _startTime);
        _elapsedTime = TimestampToTimeSpan(currentTime - _lastTime);
        _lastTime = currentTime;
    }

    public static TimeSpan TimestampToTimeSpan(long timestamp) {
        return TimeSpan.FromTicks(
            (timestamp * TimeSpan.TicksPerSecond) / Frequency);
    }
}

そのほとんどは XNA に基づいていGameClockますが、大幅に単純化されています。次に、メソッドとメソッドが知る必要がTimeあるさまざまな時間を保持するクラスがあります。UpdateDraw

public class Time {
    public TimeSpan ElapsedVirtualTime { get; internal set; }
    public TimeSpan ElapsedRealTime { get; internal set; }
    public TimeSpan TotalVirtualTime { get; internal set; }
    public TimeSpan TotalRealTime { get; internal set; }

    internal Time() { }

    internal Time(TimeSpan elapsedVirtualTime, TimeSpan elapsedRealTime,
            TimeSpan totalVirutalTime, TimeSpan totalRealTime) {
        ElapsedVirtualTime = elapsedVirtualTime;
        ElapsedRealTime = elapsedRealTime;
        TotalVirtualTime = totalVirutalTime;
        TotalRealTime = totalRealTime;
    }
}

私のメイン クラスは の 1 つのインスタンスを保持しTime、ゲーム ループ中に常に更新する必要があります。これまでのところ、私はこれを持っています:

private static void Loop() {
    do {
        Clock.Tick();

        Time.TotalRealTime = Clock.TotalTime;
        Time.ElapsedRealTime = Clock.ElapsedTime;

        InternalUpdate(Time);
        InternalDraw(Time);
    } while (!_exitRequested);
}

時間クラスのリアルタイム プロパティは非常に優れています。ここで、状態がフレームごとに可変回数更新されるように、適切な更新/描画ループが機能するようにしたいと思いますが、タイムステップは固定です。同時に、それに応じてTime.TotalVirtualTimeTime.ElapsedVirtualTimeを更新する必要があります。さらに、ゲームループの設計に違いが生じた場合に備えて、将来的にマルチプレイヤーをサポートする予定です。

これを実装する方法に関するヒントや例はありますか (記事へのリンクは別として)?

4

1 に答える 1

2

XNA で主に使用されるアプローチはUpdate()、一定のレートで呼び出しDraw()、可能な限り多くの呼び出しを行うことです。このUpdate()メソッドでは、新しい瞬間の世界を反映するように変数のみを更新し、Draw()が呼び出されたときにそれを画面に描画するだけです。

一定の速度で実行するUpdate()には、タイマーを使用するか、以下を使用してさらに正確なタイミングを使用することをお勧めします。

[DllImport("kernel32.dll")]
public static extern long GetTickCount();

Invalidate()次に、ゲーム (キャンバス) のペイントに使用するオブジェクトを呼び出す別の (より遅い) タイマーを使用できます。キャンバスの Paint イベントで、 を呼び出しますDraw()。このようにして、システムが必要と判断するたびに (キャンバスが無効になったとき)、または を呼び出す機会があればすぐに、世界が描画されますInvalidate()

于 2010-04-04T11:13:01.297 に答える