Domanda

Forse sono solo un idiota, ma ho cercato di implementare un ciclo di gioco tutto il giorno e non è solo clic. Ho letto letteralmente ogni articolo che ho potuto trovare su Google, ma il problema è che tutti usano diversi meccanismi di sincronizzazione, che li rende difficili da applicare alla mia situazione particolare (alcuni millisecondi uso, altri di uso zecche, ecc).

In sostanza, ho un oggetto Clock che aggiorna ogni volta che il gioco esegue ciclo.

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);
    }
}

I basa la maggior parte di quello sul GameClock XNA, ma è molto semplificato. Poi, ho una classe Time che detiene varie volte che i metodi Update e Draw bisogno di sapere.

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;
    }
}

La mia classe principale mantiene una singola istanza di Time, che deve costantemente aggiornare durante il ciclo di gioco. Finora, ho questo:

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

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

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

Le proprietà in tempo reale della classe tempo rivelarsi grande. Ora mi piacerebbe ottenere un aggiornamento adeguato / disegnare ciclo di lavoro in modo che lo stato viene aggiornato un numero variabile di volte per fotogramma, ma ad un passo temporale fisso. Allo stesso tempo, il Time.TotalVirtualTime e Time.ElapsedVirtualTime dovrebbero essere aggiornati di conseguenza. Inoltre, ho intenzione per questo di supporto multiplayer in futuro, nel caso in cui fa alcuna differenza per la progettazione del ciclo di gioco.

Le eventuali consigli o esempi su come potrei andare sull'implementazione di questo (a parte i collegamenti agli articoli)?

È stato utile?

Soluzione

L'approccio utilizzato principalmente in XNA è chiamare Update() ad un certo tasso fisso, e chiamata Draw() tanto quanto possibile, fino a un certo limite. Nel metodo Update(), ci si aggiorna solo le variabili in modo da riflettere il mondo in questo nuovo momento nel tempo, e quando Draw() viene chiamato, si disegna solo sullo schermo.

Per ottenere Update() di funzionare a un tasso fisso, si potrebbe desiderare di utilizzare voi timer o una tempistica ancora più accurato utilizzando:

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

Poi si potrebbe utilizzare un altro (più lento) timer che chiede Invalidate() sull'oggetto si usa per dipingere il tuo gioco (la tela). Nella tela Paint-evento, si chiama Draw(). In questo modo, il vostro mondo viene redatto ogni volta che il sistema Deems necessario (quando si invalida il vostro tela) o non appena si ha la possibilità di farlo una volta che hai chiamato Invalidate().

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top