Bei 60 Updates pro Sekunde fällt nicht auf, dass das Spiel zwischen zwei Schritten stehen bleibt. Mit einer Logikrate von 5 sieht man es sofort. Genau dafür ist die Demo gedacht.
Klick wechselt die Rate auf 5, 10, 20 und 60 Schritte pro Sekunde. Das orange Quadrat wird an der Position des letzten Logik-Schritts gezeichnet und springt. Das türkise wird zwischen den letzten zwei Schritten interpoliert und gleitet.
Der Rest im Topf
Aus Update Loop kennst du den Accumulator: Nach den Logik-Schritten bleibt meistens etwas Zeit übrig, weniger als ein ganzer Schritt. Dieser Rest sagt, wie weit das Bild zwischen zwei Schritten schon ist. Teilst du ihn durch die Schrittzeit, kommt alpha zwischen 0 und 1 heraus:
const float alpha = accumulator / step; const float drawX = prevX + (curX - prevX) * alpha;
Gezeichnet wird dann nicht der neueste Zustand, sondern ein Punkt zwischen dem vorletzten und dem letzten. Das kostet etwas: Das Bild hängt immer bis zu einen Logik-Schritt hinter dem Spiel her. Bei 60 Schritten sind das 16 Millisekunden, bei 5 Schritten sind es 200, und die merkt man in der Demo.
Hänger abfangen
Mit der Taste S schiebt die Demo eine halbe Sekunde künstlich in die Frame-Zeit, als hätte das Spiel kurz gehangen. Ohne Klemme würde der Accumulator bei 60 Schritten pro Sekunde 30 Schritte nachholen, bei komplexer Logik dauert das selbst wieder lange und der nächste Frame hat noch mehr nachzuholen. Die Demo klemmt die Frame-Zeit auf 0,25 Sekunden, also höchstens 15 Schritte pro Frame bei 60 Schritten pro Sekunde. Dafür geht in dem Moment etwas Spielzeit verloren, das Spiel läuft kurz langsamer. Die Zeile steps this frame unten zeigt dir, wie viele Schritte gerade nachgeholt wurden.
Wie die Schleife im Ganzen aussieht, steht in Update Loop, warum nicht einfach die Frame-Zeit als Schrittweite reicht, in Delta Time.
Den Code findest du im Repo unter fixed-timestep. Alle Demos der Serie sammelt das Projekt Game Dev Snippets.