Wie kann in einem 2D-Plattformspiel sichergestellt werden, dass sich der Spieler reibungslos über abschüssiges Gelände bewegt?

18

Ich entwickle eine Physik-Engine für ein 2D-Plattformspiel. Ich verwende den Satz der Trennachse für die Kollisionserkennung. Die Bodenfläche besteht aus ausgerichteten Begrenzungsrahmen, wobei der Spieler als achsenausgerichteter Begrenzungsrahmen fungiert. (Speziell verwende ich den Algorithmus aus dem Buch "Realtime Collision Detection", der eine Swept Collision Detection für OBBs mittels SAT durchführt.) Ich verwende in der Kollisionsreaktion einen relativ kleinen Wiederherstellungskoeffizienten (nahe Null), um sicherzustellen, dass die dynamischen Objekte nicht in die Umgebung eindringen.

Der Motor funktioniert größtenteils einwandfrei. Ich mache mir nur Sorgen über einige Randfälle, die möglicherweise auftreten könnten. Zum Beispiel sind in dem Diagramm A, B und C die Bodenoberfläche. Der Spieler bewegt sich links entlang B in Richtung A. Es scheint mir, dass sich die Spielerbox aufgrund von Ungenauigkeiten etwas unterhalb der Box B befinden könnte, wenn sie weiter nach oben und links geht. Wenn es also A erreicht, könnte die untere linke Ecke des Spielers mit der rechten Seite von A kollidieren, was unerwünscht wäre (da der Spieler sich sanft über A bewegen soll). Es scheint, dass ein ähnliches Problem auftreten könnte, wenn sich der Spieler oben auf Feld C befindet und sich nach links in Richtung B bewegt - der äußerste Punkt von B könnte mit der linken Seite des Spielers kollidieren, anstatt dass die untere linke Ecke des Spielers nach oben und links rutscht über B.

Box2D scheint dieses Problem zu lösen, indem es Konnektivitätsinformationen für seine Kantenformen speichert, aber ich bin mir nicht sicher, wie es diese Informationen verwendet, um das Problem zu lösen, und nach dem Betrachten des Codes verstehe ich nicht wirklich, was es tut.

Anregungen wäre sehr dankbar.

Nick Kovac
quelle
Eine allgemeine Physik-Engine eignet sich hervorragend für Effekte und Fallboxen und all das, aber nicht für die Charakterphysik, wie im Antwortabschnitt beschrieben. Erwägen Sie, "statische" Physik für Ihren Charakter zu schreiben, damit Sie 100% die Kontrolle haben und für den Rest die richtig simulierte Dynamik verwenden können.
Domi

Antworten:

14

Plattform und Physik

Diese Randfälle sind zahlreich. Gute, lustige Plattformer verhalten sich in keiner Weise physisch korrekt, und die Kontrolle und das Verhalten, die Spieler nach Jahren "perfekter" Plattformer wie Mario erwarten, sind mit allgemeinen Techniken, wie sie mit Box2D oder anderen Physik-Engines möglich sind, unglaublich schwierig zu implementieren. Die meisten guten Plattformer verwenden keine generische Physik oder Kollisionsreaktion in ihren Player-Controllern.

Rümpfe erzeugen

Bezüglich Ihrer spezifischen Frage ist es die beste Lösung, keine Boxen mehr als Grundlage zu verwenden. Verwenden Sie eine Reihe verbundener Liniensegmente (einen Rumpf). Dadurch kann sich die Kollisionserkennungs-Engine nur auf die tatsächlich begehbaren Flächen konzentrieren und nicht auf die "gefälschte" Kante zwischen AB und BC. Genau das macht Box2D. Die Formen werden verwendet, um die äußeren Oberflächen zu erzeugen, die miteinander verbunden sind, um einen Rumpf zu bilden.

Sie benötigen dies auch in kachelbasierten Spielen oder in Situationen, in denen zwei AABB-Objekte nebeneinander als Boden fungieren. Die Kollisionsmaschine nimmt diese vertikalen Kanten auf und veranlasst den Spieler, sie einzufangen. Es gibt Hacks, die helfen können, aber das Problem nicht beseitigen. Die Lösung besteht darin, nur ein einziges Liniensegment zu haben, das die Oberfläche darstellt, und nicht eine vollständige 2D-Box.

Sie können die Rümpfe im generischen Fall generieren, indem Sie die Polygone gegeneinander abschneiden und die Schnittpunkte zu einer Kantenliste zusammenfügen.

Schräge Flächen

Da Ihr Beispiel eine Neigung enthält und Sie die Wiederherstellung und andere physikalische Eigenschaften erwähnen, werde ich auf einige andere Probleme hinweisen, die Sie bald bemerken werden. Dies zeigt weiter, warum die generische Kollisionserkennung und -reaktion für Plattformfahrer nicht gut funktioniert. Versuchen Sie zunächst, auf der abgewinkelten Plattform zu stehen, aufzuspringen und dann zu landen. Sie werden wahrscheinlich bemerken, dass der Charakter bei der Landung etwas "rutscht". Das Problem ist, dass die Kontaktnormale, die Sie erzeugen, normalerweise von der abgewinkelten Oberfläche ausgeht. Bei der Lösung der Kollision wird der Spieler dann in diese Richtung hinausgeschoben. Obwohl der Charakter gerade heruntergefallen ist, wird er bei der Landung nach oben und ein wenig nach rechts geschoben, was zum Rutschen führt. Dies kann gehackt werden, indem die relativen Geschwindigkeiten berücksichtigt werden,

Das zweite Problem, das Sie bemerken werden und das viel schwerer zu beheben ist, ist das, was passiert, wenn Sie versuchen, schnell eine Rampe hinunter zu rennen. Der Spieler "hüpft" die Rampe hinunter. Dies ist selbst in den meisten heutigen AAA-Spielen sehr gut sichtbar. Es sieht nicht nur albern aus, aber wenn Ihr Spiel erfordert, dass der Spieler auf dem Boden steht, um zu springen, ist es schwierig, eine Rampe herunterzulaufen und auf halber Höhe herunterzuspringen, da der Spieler die Rampe nur während eines kleinen Abschnitts der Rampe berührt Zeit damit verbracht, es runterzugehen. Eine einfachere Lösung besteht darin, einfach einige Strahlenschläge auszuführen, wenn sich der Spieler bewegt, und die Spielerposition auf die nächstgelegene Oberfläche (wenn sie sich sehr nahe am Spieler befindet) abzusenken, wenn der Spieler nicht springt und zuvor auf dem Boden war.

Sie können auch feststellen, dass der Spieler beim Hochfahren einer Rampe in die Luft startet, wenn Sie versuchen, Geschwindigkeit, Reibung und Rückstellung auf dem Spieler so zu modellieren, als ob er ein normaler starrer Körper wäre. Die Bewegung des Spielers sollte auf horizontale Bewegungen beschränkt sein, es sei denn, er fällt oder springt. Wenn Sie mit älteren Plattformspielern aus dem Goldenen Zeitalter spielen, stellen Sie möglicherweise fest, dass die Horizontalgeschwindigkeit des Spielers zwischen horizontalen und geneigten Oberflächen häufig konstant ist. Dies muss auch beim Auf- und Absteigen berücksichtigt werden.

Es wird auch eine Reihe anderer seltsamer Fälle geben, denen Sie irgendwann begegnen werden. Wenn Sie versuchen, einen guten Plattformer zu entwickeln, ist es wirklich das Beste, einen Platformer-Player-Controller zu implementieren, der von der Physik getrennt ist und das gewünschte Bewegungs- und Steuerverhalten fest codiert, anstatt sich auf allgemeine Physik und Kollisionsreaktionsalgorithmen zu verlassen.

Sean Middleditch
quelle
Danke für deine Antwort. Ich hatte überlegt, die Kästchen, die den Boden darstellen, in Linien zu zerlegen, aber ich glaube nicht, dass dies das Problem an sich lösen wird. Wenn es sich bei den Bodenfeldern jetzt beispielsweise um Linien handelt und der Spieler in Linie C steht und nach links in Richtung B fährt, ist es aufgrund von Ungenauigkeiten möglich, dass sich das Spielerfeld geringfügig unter Linie C befindet. Dann der linke Rand des Spielerfelds könnte immer noch mit der Linie B kollidieren und diese unerwünschte Kollision verursachen,
Nick Kovac
es sei denn, es gibt einen anderen Mechanismus, um dies zu verhindern. Es ist nicht die Tatsache, dass Box2D Linien anstelle von Kästen verwendet, um das Problem zu beheben, sondern, dass Box2D eine Kettenform verwendet, die Verbindungsinformationen zwischen den Liniensegmenten verwendet, um zu verhindern, dass Kollisionen auftreten. Das Hauptproblem im Moment ist, dass ich die Details dessen, wie genau es das macht, nicht ganz verstehe.
Nick Kovac
Sie haben einige andere wirklich gute Punkte zu den Problemen angesprochen, die mit der Übernahme von Ideen aus generischen Physik-Engines und deren Anwendung auf Plattformspiele verbunden sind. Ich habe ähnliche Motoren gesehen, die die von Ihnen diskutierten Ideen umsetzen (Ändern der Kollisionsnormalen für Steigungen und Aufsaugen des Spielers auf die Steigung), so dass zumindest diese Probleme ziemlich leicht lösbar sind. Der wichtigste Knackpunkt für mich sind die kniffligen Randfälle, die mit numerischen Fehlern zusammenhängen.
Nick Kovac
@Kovsa: Wiederum verschwinden diese besonderen Fehler, wenn Sie die Kanten entfernen, die überhaupt nicht Teil der Kollision sein sollten. Verketten Sie die Kanten zu einer durchgehenden Form. Beim Entwerfen Ihrer Ebene würde ich auch empfehlen, die Scheitelpunkte zusammenzurasten, damit Sie keine kleinen Spalten in den Oberflächen haben. Eigentlich nicht anders als das Entwerfen des Levels in einem 3D-Mesh-Editor.
Sean Middleditch
Hmm ... ich glaube nicht, dass ich folge. Wenn ich in meinem Diagramm die Kanten miteinander verkette, um eine ununterbrochene Form zu erhalten, würde ich eine Form erhalten, die aus drei Liniensegmenten besteht: der Oberseite der Felder A, B und C, richtig? Auch wenn es sich um eine einzelne Form handelt, müsste ich dennoch die Kollisionserkennung für Linie A, dann B, dann C separat durchführen, nicht wahr? Es sei denn, Sie meinen einen Algorithmus, der eine Kollision zwischen der Box und dieser kombinierten Form erkennen kann? Ich nehme an, es wäre dann kein SAT, da eine Reihe von Kanten konkav sein könnte.
Nick Kovac
5

Ich denke, beide Probleme könnten gelöst werden, indem Ihre Boxen für Kollisionsreaktionszwecke so behandelt werden, als ob sie abgerundete Ecken hätten (mit einem ähnlichen Radius wie Ihr numerischer Fehler). Dadurch wird die effektive kombinierte Oberfläche der Meeting-Ecken zwischen A und B sowie B und C glatter.

Wenn also der sich nach links bewegende SPIELER die Ecke von A berührt, ist die Kollisionsnormale eher diagonal als rein nach rechts, so dass die Bewegung nach links und oben fortgesetzt werden kann.


Eine typischere Lösung für die Überprüfung der mir bekannten Platformer-Physik ist jedoch, den Spieler in eine stärker abgerundete Form zu bringen und das Terrain in Ruhe zu lassen. Überlegen Sie sich insbesondere, ob Sie die Form des Spielers als Kapsel (gedehnt im mittleren Kreis (2D) / Kugel (3D)) definieren möchten - dann sind Ihre Kollisionsnormalen naturgemäß nahezu vertikal, sodass keine Probleme beim Auffangen auftreten.

Sie sagen, Sie verwenden einen Kollisionsalgorithmus speziell für OBBs, sollten aber dennoch in der Lage sein, nach dem Auffinden einer OBB-OBB-Kollision einen weiteren Test gegen eine Form durchzuführen, die sich vollständig innerhalb des OBB befindet.

Kevin Reid
quelle
Hmm, interessante Idee ... wie würden Sie es umsetzen? Dies widerspricht allerdings etwas der Einfachheit der Verwendung von Boxen: (Ich stimme zu, dass es ein allgemeines Problem mit einer endgültigen Lösung zu sein scheint, aber ich kann wirklich keine Berichterstattung darüber finden ... abgesehen davon, was gerade getan wird in Box2D. Ich habe eine ähnliche Frage in ihrem Forum gepostet, um hoffentlich mehr Einblick zu bekommen.
Nick Kovac
Ich habe keine Implementierungsdetails, sorry - ich bin kein Experte für diese Art von Physik-Engine-Code. Ich hatte jedoch eine bessere Idee für eine Lösung, die nicht auf Fudge-Faktoren basiert - siehe meine Bearbeitung.
Kevin Reid
1
Beachten Sie, dass abgerundete Formen zwar funktionieren, mathematisch jedoch komplexer sind und für Plattformfahrer zu einem nicht optimalen Verhalten führen können. Die Spieler erwarten eine nahezu pixelgenaue Kontrolle über Charaktere, die beispielsweise auf Vorsprüngen stehen, was abgerundete Formen mehr oder weniger unmöglich macht und Charaktere unerwartet von den Vorsprüngen rutschen.
Sean Middleditch
Ledges: Oh! OK, nicht so einfach wie ich dachte.
Kevin Reid
Ja, nachdem ich darüber nachgedacht habe, scheint der Kapselansatz eher für ein 3D-Spiel als für einen 2D-Plattformer geeignet zu sein. Die pixelgenaue Steuerung hat für mich definitiv Priorität (wie bei all den alten 2D-Plattformspielern). Aber es muss eine Lösung geben, mit der Boxen verwendet werden können!
Nick Kovac