Halbfester oder vollständig festgelegter Zeitschritt?

15

Ich mache ein iPhone-Shmup und versuche zu entscheiden, welche Art von Spieleschleife verwendet werden soll. Ich möchte entweder einen halbfesten Zeitschritt oder einen vollständig festen Zeitschritt verwenden.

Mit einem halbfesten Zeitschritt werde ich null oder mehr Aktualisierungsaufrufe (FIXED_INTERVAL) ausführen, gefolgt von einem Aktualisierungsaufruf (dt), wobei dt <= FIXED_INTERVAL pro Spielschleife. Soweit ich weiß, sind die Nachteile dieser Methode, dass meine Physik-Aktualisierungslogik (dt) schwieriger zu programmieren sein wird, da ich grundsätzlich für jedes Update eine Variable dt annehmen muss. Und dann habe ich auch gehört, dass jeder Durchgang meines Spiels etwas anders sein wird, da die Gleitkommawerte nicht jedes Mal gleich sind.

Dann mache ich mit einem vollständig festgelegten Zeitschritt null oder mehr Aktualisierungsaufrufe (FIXED_INTERVAL), gefolgt von einem Interpolationsaufruf (dt / FIXED_INTERVAL), wobei dt <FIXED_INTERVAL pro Spielschleife.

Die große Entscheidung, die ich treffen muss, scheint also zu sein: Möchte ich die Herausforderung der Implementierung eines Updates (dt) mit einer Variablen dt angehen, oder möchte ich die Herausforderung der Implementierung der Interpolation angehen?

Nach dem, was ich gelesen habe, sagen die meisten Leute, dass sie die Interpolation vollständig fixieren und durchführen sollen. Aber wenn ich über die Implementierung der Interpolation nachdenke, scheint es mir viel komplexer zu sein als ein Update (dt) mit der Variablen dt. Dies liegt daran, dass ich mich sowohl an den vorherigen als auch an den aktuellen Zustand erinnern muss, wenn ich Interpolation verwende. Wenn ich Interpolation verwenden möchte, muss ich eine zusätzliche Indirektionsebene entwickeln, die ganze einzelne Spielzustände abstrahiert. Während bei semi-festen Zeitschritten, bei denen ich keine Interpolation verwenden muss, keine Spielzustandsabstraktion erstellt werden muss, da es immer nur einen Spielzustand gibt und es einfach die "globalen Arrays" sind, die meine Feinde und den Feind darstellen Kugeln usw.

Also, was ist die praktischere Wahl: Implementiere ich es halbfest in dem Wissen, dass meine Physik-Updates mit der Variablen dt kompliziert werden könnten? Oder verwende ich vollständig fixiert und versuche, eine Spielzustandsabstraktion zu erstellen, damit ich den vorherigen Zustand und den aktuellen Zustand verfolgen kann, um eine Interpolation durchzuführen?

Ryan
quelle
Hier ziemlich ausführlich behandelt: gamedev.stackexchange.com/questions/1589/…
michael.bartnett
1
Ich habe diese Diskussion und die Links dort mehrmals gelesen. Genau so bin ich zu diesem Beitrag gekommen. Meine Frage hat hauptsächlich damit zu tun, wie Spielzustände implementiert werden, um eine Interpolation zu erreichen - was in dieser Diskussion überhaupt nicht behandelt wird.
Ryan

Antworten:

12

Vollständig behoben

Sie verlieren die meisten Vorteile eines festen Zeitschritts, wenn Sie einmal pro Bild einen variablen Schritt ausführen.

Noel Lopis hat einen tollen Überblick darüber , wie er in seinem Spiel Casey's Contraptions einen festen Zeitschritt implementiert hat . Als Bonus für Sie ist er ein iPhone-Entwickler, obwohl seine Technik nicht iPhone-spezifisch ist.

Einige Highlights aus dem Artikel

  • Verwenden Sie einen Zeitspeicher.
  • Verwenden Sie eine physikalische Frequenz von 120 Hz für eine Bildfrequenz von 60 Hz.
  • Simulieren Sie einen festen Schritt in die Zukunft und verwenden Sie die verbleibende Zeit, um den Zeichnungscode zwischen dem aktuellen Physikzustand und dem zukünftigen Physikzustand zu wechseln.
  • verschiedene Fallstricke
deft_code
quelle
2

Was Sie beziehen sich auf als „halbfeste“ und „voll fixed“ Zeitschritt sind, in meinem Kopf, beide festen Zeitschritt - die dt , dass Sie Ihren sind vorbei updateAnruf zwischen Rahmen nicht ändert.

Ihre Frage lautet also tatsächlich: "Möchte ich Interpolation zum Rendern implementieren?" Die Antwort lautet: wahrscheinlich nicht .

Interpolation ist etwas, das Sie nur dann tun möchten, wenn sich Ihr fester updateZeitschritt deutlich von Ihrem Zielzeitschritt renderunterscheidet. Es ist nicht ungewöhnlich, dass Spiele eine anstrengende updatePhase haben, in der sie beispielsweise nur update10 Hz aufrufen, aber mit voller Framerate rendern.

Da Sie ein iPhone-Shmup schreiben, sind weder Ihre updatenoch Ihre renderAnforderungen besonders rechenintensiv. Sie können Ihre Framerate problemlos auf 30 Hz oder 60 Hz einstellen, ohne sich um die Implementierung kümmern zu müssen, und haben dennoch ein flüssiges Spiel.

Blair Holloway
quelle
Ich verstehe es nicht. Sie sagen, ich kann das große Dt, das ich in meiner Spieleschleife berechnen würde, sperren - das meine Physik verbraucht? Wie mache ich das? Kann ich das mit CADisplayLink machen? Ich meine, wie viel Prozent der CPU nehmen Sie an, dass ich benutze? Sollte man wirklich von Locked Game Loop dt ausgehen?
Ryan
Das, was ich sage, läuft wirklich darauf hinaus, das Unkomplizierteste zu tun, was funktionieren würde.
Blair Holloway
1
Ausarbeitung: Die Verwendung einer Variablen dtfür updateund renderist das Einfachste, was funktionieren würde, wird jedoch im Allgemeinen vermieden, wenn Physik-Engines für die dadurch verursachte Instabilität verwendet werden. Daher ist das Aufrufen updatemit einer festen dtRate und das Rendern mit derselben Rate (beim Löschen von Frames, wenn Ihre updateAusführung lang ist) im Allgemeinen die einfachste Sache, die funktionieren würde. Das Schreiben von Code zum Interpolieren von Objekten zwischen updateAufrufen erhöht die Komplexität des Codes. Komplexität, die Sie hinzufügen, um kein Problem zu lösen.
Blair Holloway