die Spieleprogrammierer unter euch kennen sicherlich das leidliche Thema mit der Framerate-unabhängigen Programmierung. In den meisten Tutorials, die ich bisher gesehen habe, wird im Grunde folgender Ansatz erklärt:
1. rendern
2. schauen, wie viel Zeit vergangen ist
3. updaten: Spielobjekte bewegen, Zeitunterschied * Geschwindigkeit
4. goto 1
Dies funktioniert zwar, ist aber meiner Meinung nach etwas umständlich und auch fehleranfällig. Wenn beispielsweise eine Figur auf eine Mauer zuläuft, und der nächste Render-Schritt aus irgendeinem Grund sehr lange dauern sollte (z.B. weil der Rechner im Hintergrund gerade Mails abruft etc), dann kann es (je nach Implementierung der Kollisionsabfrage) passieren, daß die Figur sich im nächsten Frame hinter der Mauer befindet - was jedoch eigentlich gar nicht möglich sein dürfte.
Zudem wird viel mit unvorhersehbaren Komma-Werten gearbeitet usw., was auch immer wieder mal zu Problemen führen kann (z.B. auch bei der Fehlersuche).
Der meiner Meinung nach bessere Ansatz ist der, für die Positions-Updates usw. eine fixe Framerate einzuführen, die auf jeden Fall erfüllt wird, und immer nur so oft zu rendern, wie es möglich ist. Da die Updates i.d.R. nur einen Bruchteil der Render-Zeit benötigen, ist es dann auch kein Problem, nach einem etwas längeren Render-Vorgang einfach die verlorenen Updates nachzuholen.
Das sieht dann grob erklärt ungefähr so aus:
1. rendern
2. warten bis bzw. schauen ob Updates fällig sind
3. updaten: Spielobjekte bewegen, und zwar um einen fixen Wert (anhand der Geschwindigkeit)
4. je nach Zeitunterschied Schritt 3 noch ein paar mal aufrufen
5. goto 1
Die GameLoop, die ich momentan verwende, sieht daher in etwa so aus:
Code: Alles auswählen
running = #True
frameTime = ElapsedMilliseconds()
#DELTA_TIME = 1000 / 60 ; wir legen uns fest auf 60 Updates pro Sekunde
While running
currentTime = ElapsedMilliseconds()
If currentTime - frameTime < #DELTA_TIME
Continue ; die Zeit ist noch nicht gekommen
EndIf
While currentTime - frameTime >= #DELTA_TIME
frameTime = frameTime + #DELTA_TIME ; jetzt holen wir alle nötigen Updates nach
controls()
update()
Wend
render() ; und schließlich wird gerendert
Wend
EDIT: Um es nochmals auf den Punkt zu bringen: Die Loop simluiert quasi eine "fixe Framerate", auch wenn das Rendern zu lange (oder zu kurz) dauern sollte. Dadurch kann man als Programmierer seine Objekte so bewegen, wie man es auch sonst mit einer fixen Framerate tun würde.