Ich habe gelesen, dass die Geschwindigkeit von Spielobjekten nicht durch FPS behindert werden sollte, sondern auf der Zeit basieren sollte. Wie kann ich den Aktualisierungs- / Zeichnungscode trennen, um die Leistung zu maximieren, ohne die Zeichnungsrate zu begrenzen, und eine konstante logische Aktualisierungsrate basierend auf der Zeit bereitstellen?
Mein aktueller Pseudocode lautet wie folgt
loop
{
draw();
if (ticksElapsed() > 100)
{
update();
ticks+= ticksElapsed();
}
}
Das Problem ist, dass der Zeichnungscode die Leistung der update () -Rate beeinträchtigt. Und es verbraucht 100% CPU, denn wenn der Schlaf aktiviert wird, werden beide Zeichen- / Logikfunktionen deaktiviert.
Ich verwende auch SDL und es scheint keine vsync-Option zu geben. Ich habe auch von den Begriffen feste und variable Zeitschritte gehört, bin mir aber nicht sicher, wie das mit sleep gemacht werden kann ()
quelle
Antworten:
In Ihrem Code-Snippet sieht es so aus, als würden Sie versuchen, Ihr Spiel im Schrittmodus mit fester Zeit auszuführen, indem Sie warten, wenn das Zeichnen und Aktualisieren weniger als 15 ms (60 fps) gedauert hat. Dies ist möglich und Sie haben richtig geraten, dass dies nicht mit einem Schlafanruf möglich ist, da Sie nicht genau wissen, wie lange Sie schlafen gehen. Die Besetzt-Warteschleife ist die gute Lösung.
Betrachten Sie jedoch den Fall, in dem Ihre Aktualisierung und Zeichnung 15 ms überschreitet, haben Sie jetzt das Zeichnen und Aktualisieren des Spiels zu langsam. Sie können jetzt zwei Dinge tun: diesen Status erkennen und Frames löschen (Zeichnung überspringen und direkt mit der Aktualisierung fortfahren, bis Sie wieder synchron sind). Wenn der Computer jedoch nur zu langsam ist, holt er nie auf.
Eine andere Lösung besteht darin, Ihre Aktualisierungslogik zeitunabhängig zu machen. Sie benötigen dafür keinen separaten Thread, sondern müssen nur erneut festlegen, wie schnell sich die Dinge bewegen sollen. Anstelle von 5 Pixeln pro Tick sollten Sie 50 Pixel pro Sekunde verwenden. Sie benötigen einen hochpräzisen Timer, um dies zu erreichen, und Ihre gesamte Aktualisierungslogik sollte auf den Timer zugreifen können, um zu sehen, wie viel Zeit seit der letzten Aktualisierung vergangen ist.
Grundsätzlich gehen Sie von:
Zu
quelle