2D-Plattformer: Warum macht man die Physik von der Bildrate abhängig?

12

"Super Meat Boy" ist ein schwieriger Plattformer, der vor kurzem für den PC herausgekommen ist und außergewöhnliche Kontrolle und pixelgenaues Springen erfordert. Der Physikcode im Spiel hängt von der Bildrate ab, die auf 60 fps festgelegt ist. Dies bedeutet, dass, wenn Ihr Computer das Spiel nicht mit voller Geschwindigkeit ausführen kann, die Physik verrückt wird, was (unter anderem) dazu führt, dass Ihr Charakter langsamer rennt und durch den Boden fällt. Außerdem läuft das Spiel extrem schnell, wenn vsync ausgeschaltet ist.

Können diejenigen, die Erfahrung mit 2D-Spielprogrammierung haben, erklären, warum das Spiel auf diese Weise codiert wurde? Wäre eine Physikschleife mit konstanter Geschwindigkeit nicht eine bessere Lösung? (Eigentlich denke ich, dass für Teile des Spiels eine Physikschleife verwendet wird, da sich einige der Einheiten unabhängig von der Bildrate normal weiterbewegen. Ihr Charakter hingegen läuft genau [fps / 60] so schnell.)

Was mich an dieser Implementierung stört, ist der Verlust der Abstraktion zwischen der Spiel-Engine und dem Grafik-Rendering, der von systemspezifischen Dingen wie dem Monitor, der Grafikkarte und der CPU abhängt. Wenn Ihr Computer aus irgendeinem Grund nicht mit vsync umgehen kann oder das Spiel nicht mit genau 60 fps ausführen kann, wird es spektakulär kaputt gehen. Warum sollte der Rendering-Schritt die physikalischen Berechnungen in irgendeiner Weise beeinflussen? (Die meisten Spiele würden heutzutage entweder das Spiel verlangsamen oder Frames überspringen.) Andererseits verstehe ich, dass Plattformer der alten Schule auf dem NES und SNES für einen Großteil ihrer Steuerung und Physik von einer festen Bildrate abhängig waren. Warum ist das so und wäre es möglich, einen Benutzer in diesem Sinne zu erstellen, ohne die Abhängigkeit von der Framerate zu haben? Gibt es notwendigerweise einen Präzisionsverlust, wenn Sie das Grafik-Rendering vom Rest der Engine trennen?

Vielen Dank und sorry, wenn die Frage verwirrend war.

Archagon
quelle
Tangential zu Ihrer Frage. Hier ist ein großartiger Artikel, der genau die Probleme behandelt, die Sie beschreiben, und die "richtige" Art, mit Zeitschritten und Bildraten umzugehen. gafferongames.com/game-physics/fix-your-timestep
num1
Es hat mich wirklich überrascht, dass sie es so machen würden. Ich nehme an, es muss daran liegen, dass es hauptsächlich für Konsolen entwickelt wurde, auf die sich die Bildrate verlassen kann. Enttäuschend!
Iain

Antworten:

7

Warum?

Eine Handvoll Gründe, treffen Sie Ihre Wahl: Sie wussten es nicht besser. Es ist schneller und einfacher zu implementieren. Sie konzentrierten sich mehr auf das Gameplay und weniger auf die Randfälle, die in den meisten Fällen möglicherweise nicht auftauchen.

Sie haben ziemlich gut erklärt, warum nicht. Ich bin sicher, Sie haben bemerkt, dass es viele Themen gibt, die das Thema abdecken . Ich bin mir nicht sicher, ob Sie eine zufriedenstellende Antwort finden werden, die über die von mir aufgelisteten Antworten hinausgeht.

Tetrade
quelle
"Sie wussten es nicht besser" beschreibt, warum ich mit "Jack is a Fool" so vorgegangen bin. Aber - ich habe mich seit dem letzten Frame mit all meiner Logik stark darauf verlassen, das dt aufzurufen. Aber - mit Gleitkommakoordinaten kann es zu seltsamen, schwer zu replizierenden Fehlern kommen
lochok
4

SMB war ursprünglich ein Konsolenspiel, bei dem davon ausgegangen werden kann, dass es auf allen Xbox360-Geräten mit 60 fps (bei einigen PAL-Spielern sogar mit 50 fps) läuft. Angenommen, ein fester Zeitschritt vereinfacht den Code ein gutes Stück.

Während es einfach ist, eine Menge Dinge mit einem variablen Zeitschritt zu skalieren - 'pos + = velocity * timestep', wird es ziemlich schwierig, es richtig zu machen, wenn Sie mit Beschleunigungen, Änderungsraten der Beschleunigung usw. zu tun haben.

Das Entkoppeln von Gameplay und Rendering ist theoretisch eine gute Lösung , aber eine gute Implementierung (mit guter Interpolation) ist recht schwierig und es kann leicht zu Problemen kommen. Es ist ziemlich ungewöhnlich, dass diese Technik in echten Spielen verwendet wird (obwohl einige große Spiele dies tun, insbesondere RTS-Spiele, aber mehr für die Netzwerkspielsynchronisation).

Wenn Sie sowohl eine feste Bildschirmauflösung als auch eine feste Bildwiederholfrequenz festlegen, können Sie das Scrollen noch etwas reibungsloser gestalten. Sie können sicherstellen, dass das Spiel einen Bildlauf mit einer ganzen Anzahl von Pixeln pro Bild durchführt. Vermeiden Sie ein „Subpixel-Wackeln“, indem Sie einen Teil der Pixel pro Bild durchlaufen.

Bluescrn
quelle
1

Die naheliegende Lösung besteht darin, zwei Loops parallel laufen zu lassen - das Rendern alle 1/60 Sekunde und das Spielen alle 1/60 Sekunde.

Aufgrund meiner Erfahrung mit Flash (AS3, in dem Super Meat Boy mit ziemlicher Sicherheit entwickelt wurde) ist der Scheduler jedoch nicht immer sehr genau. Die Genauigkeit hängt auch stark von der Umgebung ab. Im Standalone-Flash-Player kann die Auflösung unter Millisekunden liegen. Bei einigen Webbrowsern wird die Genauigkeit jedoch zur Bildrate.

Der beste Weg, um die Rendering- und Game-Logik-Loops zu entkoppeln, besteht darin, dass alle Bewegungen zeitbasiert sind (und dass jeder Frame basierend auf der Zeit ausgeführt wird, die seit dem letzten Frame vergangen ist). Dies kann zu etwas komplizierteren mathematischen Problemen führen (z. B. wenn die Schwerkraft kontinuierlich angewendet wird, anstatt die Geschwindigkeit eines Objekts in festgelegten Intervallen zu erhöhen). Da das Spiel für eine Sekunde verzögert werden kann und sich Ihr Player in einem Schritt um 200 Pixel bewegt, können die Erkennung und Reaktion von Kollisionen noch komplizierter werden. Wenn der Programmierer eine rahmenbasierte Kollisionserkennung durchführen würde (bei jedem Zeitschritt auf eine Kollision prüfen würde), müsste er ebenfalls auf eine zeitbasierte Kollisionserkennung umschalten. Und wenn sie wollten, dass es sich natürlich anfühlt, müssten sie die oben beschriebene Schwerkraftmethode anwenden, die bewirkt, dass die Objektbewegung eine Kurve ist (im Gegensatz zu einer Linie).

Ponkadoodle
quelle
2
Der ursprüngliche Meat Boy war ein Flash-Spiel. Super Meat Boy ist ein C ++ - Spiel.
Archagon
0

Ich denke nicht, dass es zu viel ist, nach 2D-PC-Spielen zu fragen, die mit 60 fps wiedergegeben werden können. Sogar die meisten 2D-Spiele sind jetzt hardwarebeschleunigt, sodass ich mir persönlich keine Sorgen über die FPS-Anforderungen machen würde.

Die eigentliche Frage ist, warum Sie kein pixelbasiertes System verwenden, denn Spiele stecken voller Cheats und Shortcuts.

Wenn Sie ein physikbasiertes Spiel machen (vielleicht ein Vogelwurf?), Liegt die Antwort auf der Hand, aber ein Super-Mario-Klon? zeitbasierte Bewegung könnte ein bisschen viel sein.

PhilCK
quelle
Es ist nicht schwer, sie mit 60 fps wiederzugeben, aber Bildschirme mit systemeigenen Bildwiederholfrequenzen von 50 Hz, 70 bis 85 Hz und 120 Hz sind immer noch leicht zu finden.
0

Um seltsames Verhalten in der von ihnen verwendeten 2D-Physik zu vermeiden?

Ehrlich gesagt kann ich nur raten. Ich werde eine Erklärung versuchen:

Das Herzstück des Spiels ist die Hauptspielschleife. Was grundsätzlich so aussieht:

while(gameRunning)
{
  updateGame(timestep);
  renderGame(timestep);
}

updateGame aktualisiert den gameState: Überprüft die Spielereingaben, wendet die Spielereingaben auf die Spielwelt an und führt die Physiksimulation aus usw.

renderGame zeichnet und animiert das Spiel.

Dies koppelt das Physik-Update mit dem Rendering. Wenn Sie es entkoppeln möchten, müssen Sie Threads verwenden und jeden Datenzugriff des Renderings und des gameUpdate-Threads ordnungsgemäß mit freigegebenen Daten synchronisieren, z. B. der Position des Spielers. Das kann gemacht werden.

Ein weiteres Problem könnte sein, dass die Physiksimulation einen konstanten Zeitschritt benötigt, um stabil zu laufen. Dies hängt davon ab, wie Supermeatboy die Bewegung berechnet (Auch hier können wir nur raten, wie sie es gemacht haben;)).

Ein naiver Ansatz wäre (den ich in meinem Spiel verwende * seufz *):

position=position+speed*timestep;
speed=speed+acceleration*timestep;

Dies nennt man Euler-Integration und wird allgemein als schlechte Idee angesehen. Wenn der Zeitschritt nicht konstant ist, treten Berechnungsfehler auf, die die Simulation instabiler machen. Das Objekt bewegt sich möglicherweise zu schnell oder nicht vollständig oder fliegt durch die Wände vom Bildschirm weg. Auch wenn der Zeitschritt konstant ist, führt die Euler-Integration zu geringfügigen Rechenfehlern. Verwenden Sie besser eine andere Integrationsmethode wie RK4 oder eine Physik-Engine.

Abgesehen davon kann es zu Problemen bei der Kollisionserkennung kommen, wenn der Zeitschritt zu groß wird. Da Kollisionen zwischen zwei gameUpdates nicht überprüft werden, können Objekte Hindernisse passieren.

Stephen
quelle