7 days of WordPress themes, graphics & videos - for free!* Unlimited asset downloads! Start 7-Day Free Trial
Advertisement
  1. Game Development
  2. Platformer

Grundlegende 2D-Plattformerphysik, Teil 3

Read Time: 11 mins
This post is part of a series called Basic 2D Platformer Physics .
Basic 2D Platformer Physics, Part 2
Basic 2D Platformer Physics, Part 4

German (Deutsch) translation by Alex Grigorovich (you can also view the original English article)

One-Way-Plattformen

Da wir gerade mit der Bodenkollisionsprüfung fertig sind, können wir auch One-Way-Plattformen hinzufügen, wenn wir gerade dabei sind. Sie betreffen ohnehin nur die Bodenkollisionsprüfung. Einweg-Plattformen unterscheiden sich von festen Blöcken dadurch, dass sie ein Objekt nur dann stoppen, wenn es herunterfällt. Außerdem erlauben wir auch, dass ein Charakter von einer solchen Plattform herunterfällt.

Wenn wir von einer Einweg-Plattform aussteigen wollen, wollen wir grundsätzlich die Kollision mit dem Boden ignorieren. Ein einfacher Ausweg hier ist das Einrichten eines Versatzes, nach dem der Charakter oder das Objekt nicht mehr mit einer Plattform kollidiert.

Befindet sich das Zeichen beispielsweise bereits zwei Pixel unter dem oberen Rand der Plattform, sollte es keine Kollision mehr erkennen. In diesem Fall müssen wir, wenn wir die Plattform verlassen möchten, das Zeichen um zwei Pixel nach unten verschieben. Erstellen wir diese Versatzkonstante.

Fügen wir nun eine Variable hinzu, die uns mitteilt, ob sich ein Objekt aktuell auf einer Einwegplattform befindet.

Ändern Sie die Definition der HasGround-Funktion, um auch einen Verweis auf einen Booleschen Wert zu übernehmen, der gesetzt wird, wenn das Objekt auf einer Einwegplattform gelandet ist.

Nachdem wir nun überprüft haben, ob das Feld, auf dem wir uns gerade befinden, ein Hindernis ist, ist dies nicht der Fall. Wir sollten prüfen, ob es sich um eine Einwegplattform handelt.

Wie zuvor erklärt, müssen wir auch sicherstellen, dass diese Kollision ignoriert wird, wenn wir den cOneWayPlatformThreshold unterhalb der Plattform unterschritten haben.

Natürlich können wir den Unterschied zwischen der Oberseite der Kachel und dem Sensor nicht einfach vergleichen, denn es ist leicht vorstellbar, dass wir selbst bei einem Absturz deutlich unter zwei Pixel von der Oberseite der Plattform abfallen. Für die Einwegplattformen zum Anhalten eines Objekts soll der Sensorabstand zwischen der Oberseite der Kachel und dem Sensor kleiner oder gleich dem cOneWayPlatformThreshold plus dem Versatz von der Position dieses Rahmens zur vorherigen sein.

Zum Schluss gibt es noch eine weitere Sache zu beachten. Wenn wir eine Einwegplattform finden, können wir die Schleife nicht wirklich beenden, da es Situationen gibt, in denen sich der Charakter teilweise auf einer Plattform und teilweise auf einem festen Block befindet.

Wir sollten eine solche Position nicht wirklich als "auf einer Einbahnplattform" betrachten, da wir von dort nicht wirklich herunterfallen können - der feste Block hält uns auf. Aus diesem Grund müssen wir zuerst nach einem festen Block suchen. Wenn einer gefunden wird, bevor das Ergebnis zurückgegeben wird, müssen wir onOneWayPlatform ebenfalls auf false setzen.

Wenn wir nun alle Kacheln durchgesehen haben, die wir horizontal überprüfen mussten, und eine Einwegplattform, aber keine festen Blöcke fanden, können wir sicher sein, dass wir uns auf einer Einwegplattform befinden, von der wir herunterfallen können.

Das ist es also, jetzt wollen wir der Charakterklasse eine Option hinzufügen, um die Plattform herunterzufahren. Im Stand- und Run-Status müssen wir den folgenden Code hinzufügen.

Mal sehen, wie es funktioniert.

Alles funktioniert einwandfrei.

Griffkollisionen für die Decke

Wir müssen eine analoge Funktion für HasGround für jede Seite der AABB erstellen. Beginnen wir also mit der Decke. Die Unterschiede sind wie folgt:

  • Die Sensorzeile befindet sich über der AABB und nicht darunter
  • Wir prüfen die Deckenplatte von unten nach oben, während wir nach oben gehen
  • Es müssen keine One-Way-Plattformen verwendet werden

Hier ist die modifizierte Funktion.

Griffkollisionen für die linke Wand

Ähnlich wie bei der Kollisionsprüfung für Decke und Boden, müssen wir auch prüfen, ob das Objekt mit der linken oder der rechten Wand kollidiert. Beginnen wir an der linken Wand. Die Idee hier ist ziemlich gleich, aber es gibt einige Unterschiede:

  • Die Sensorzeile befindet sich auf der linken Seite der AABB.
  • Die innere for-Schleife muss vertikal durch die Kacheln iterieren, da der Sensor jetzt eine vertikale Linie ist.
  • Die äußere Schleife muss horizontal durch Kacheln iteriert werden, um zu sehen, ob wir keine Wand übersprungen haben, wenn wir mit einer großen horizontalen Geschwindigkeit fahren.

Griffkollisionen für die rechte Wand

Schließlich erstellen wir die CollidesWithRightWall-Funktion, die, wie Sie sich vorstellen können, eine sehr ähnliche Funktion wie CollidesWithLeftWall ausführt. Statt jedoch einen Sensor links zu verwenden, verwenden wir einen Sensor auf der rechten Seite des Charakters.

Der andere Unterschied besteht darin, dass wir die Kacheln nicht von rechts nach links prüfen, sondern von links nach rechts, da dies die angenommene Bewegungsrichtung ist.

Bewegen Sie das Objekt aus der Kollision

Alle unsere Kollisionserkennungsfunktionen sind fertig. Lassen Sie uns damit die Kollisionsreaktion gegen die Tilemap vervollständigen. Bevor wir das tun, müssen wir jedoch die Reihenfolge herausfinden, in der wir die Kollisionen überprüfen. Betrachten wir die folgenden Situationen.

In beiden Situationen sehen wir, dass sich der Charakter mit einer Kachel überschneidet, aber wir müssen herausfinden, wie wir die Überschneidung auflösen sollten.

Die Situation auf der linken Seite ist ziemlich einfach - wir können sehen, dass wir direkt nach unten fallen, und deshalb sollten wir definitiv auf dem Block landen.

Die Situation auf der rechten Seite ist etwas komplizierter, da wir in Wirklichkeit ganz in der Ecke der Kachel landen könnten, und den Charakter nach oben zu schieben, ist genauso vernünftig wie nach rechts zu schieben. Lassen Sie uns die horizontale Bewegung priorisieren. Es ist nicht wirklich wichtig, welche Ausrichtung wir zuerst machen möchten. Beide Optionen sehen richtig aus.

Gehen wir zu unserer UpdatePhysics-Funktion und fügen Sie die Variablen hinzu, die die Ergebnisse unserer Kollisionsabfragen enthalten.

Beginnen wir nun damit, ob wir das Objekt nach rechts verschieben sollen. Die Bedingungen hier sind die:

  • die horizontale Geschwindigkeit ist kleiner oder gleich Null
  • Wir kollidieren mit der linken Wand
  • Im vorherigen Frame haben wir uns nicht mit der Kachel auf der horizontalen Achse überlappt - eine Situation, die der rechts im Bild oben ähnelt

Die letzte ist eine notwendige Bedingung, denn wenn sie nicht erfüllt ist, haben wir es mit einer Situation zu tun, die der im linken Bild links dargestellten Situation ähnelt, in der wir den Charakter sicher nicht nach rechts bewegen sollten.

Wenn die Bedingungen erfüllt sind, müssen wir die linke Seite unserer AABB an der rechten Seite der Kachel ausrichten, sicherstellen, dass wir uns nicht mehr nach links bewegen und uns links neben der Wand markieren.

Wenn eine der Bedingungen außer der letzten falsch ist, müssen Sie mPushesLeftWall auf false setzen. Das liegt daran, dass die letzte Bedingung, die falsch ist, nicht notwendigerweise bedeutet, dass der Charakter die Wand nicht drückt, sondern umgekehrt, dass er bereits im vorherigen Frame mit ihm zusammengestoßen ist. Aus diesem Grund ist es am besten, mPushesLeftWall nur dann in false zu ändern, wenn eine der ersten beiden Bedingungen ebenfalls falsch ist.

Lassen Sie uns nun die Kollision mit der rechten Wand überprüfen.

Wie Sie sehen, ist es die gleiche Formel, die wir zur Überprüfung der Kollision mit der linken Wand verwendet haben, jedoch gespiegelt.

Wir haben bereits den Code, um die Kollision mit dem Boden zu überprüfen, und danach müssen wir die Kollision mit der Decke überprüfen. Auch hier nichts Neues, und wir müssen keine zusätzlichen Überprüfungen durchführen, außer dass die vertikale Geschwindigkeit größer oder gleich Null sein muss und wir tatsächlich mit einem über uns liegenden Feld kollidieren.

Runden Sie die Ecken auf

Bevor wir testen, ob die Kollisionsantworten funktionieren, ist noch etwas wichtiger, die Eckenwerte zu runden, die wir für die Kollisionsprüfungen berechnen. Wir müssen das tun, damit unsere Überprüfungen nicht durch Fließkommafehler zerstört werden, die sich aus einer merkwürdigen Kartenposition, einem Zeichenmaßstab oder nur einer komischen AABB-Größe ergeben können.

Lassen Sie uns zu Ihrer Erleichterung zunächst eine Funktion erstellen, die einen Vektor von Schwebekörpern in einen Vektor von abgerundeten Schwebekörpern umwandelt.

Jetzt nutzen wir diese Funktion bei jeder Kollisionsprüfung. Lassen Sie uns zunächst die HasCeiling-Funktion korrigieren.

Weiter ist OnGround.

PushesRightWall.

Und zum Schluss PushesLeftWall.

Das sollte unsere Probleme lösen!

Überprüfen Sie die Ergebnisse

Das wird es sein. Lassen Sie uns testen, wie unsere Kollisionen jetzt funktionieren.

Zusammenfassung

Das war es für diesen Teil! Wir haben ein voll funktionsfähiges Set von Tilemap-Kollisionen, das sehr zuverlässig sein sollte. Wir wissen, in welcher Position sich das Objekt momentan befindet: Ob es sich am Boden befindet, eine Kachel links oder rechts berührt oder eine Decke anstößt. Wir haben auch die One-Way-Plattformen implementiert, die in jedem Plattformspiel ein sehr wichtiges Werkzeug sind.

Im nächsten Teil werden wir eine Leistengreifende Mechanik hinzufügen, die die möglichen Bewegungen der Figur noch weiter erhöht. Bleiben Sie also dran!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Game Development tutorials. Never miss out on learning about the next big thing.
Advertisement
Scroll to top
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.