Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Platformer
Gamedevelopment

Grundlegende 2D-Plattformerphysik, Teil 7: Grundlagen der Steigungen

by
Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called Basic 2D Platformer Physics .
Basic 2D Platformer Physics, Part 6: Object vs. Object Collision Response

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

Final product image
What You'll Be Creating

Demo

Die Demo zeigt das Endergebnis der Steigungsimplementierung. Verwenden Sie WASD, um den Charakter zu verschieben. Mit der rechten Maustaste wird eine Kachel erstellt.  Sie können das Scrollrad oder die Pfeiltasten verwenden, um eine Kachel auszuwählen, die Sie platzieren möchten. Die Schieberegler ändern die Größe des Charakters des Spielers.

Die Demo wurde unter Unity 5.5.2f1 veröffentlicht und der Quellcode ist auch mit dieser Unity-Version kompatibel.

Steigungen

Steigungen erhöhen die Vielseitigkeit eines Spiels, sowohl hinsichtlich möglicher Interaktionen mit dem Gelände des Spiels als auch hinsichtlich der visuellen Varianz. Die Implementierung kann jedoch sehr komplex sein, insbesondere wenn wir eine große Anzahl von Hangsorten unterstützen möchten.

Wie bei den vorherigen Teilen der Serie, werden wir unsere Arbeit von dem Moment an fortsetzen, an dem wir den letzten Teil aufgegeben haben, auch wenn wir einen großen Teil des Codes, den wir bereits geschrieben haben, überarbeiten. Was wir von Anfang an brauchen, ist ein beweglicher Charakter und eine Tilemap.

Sie können die Projektdateien aus dem vorherigen Teil herunterladen und den Code zusammen mit diesem Lernprogramm schreiben.

Änderungen in der Bewegungsintegration

Da es schwierig ist, die Steigung zu arbeiten, ist es schön, wenn wir die Dinge in einigen Aspekten einfacher machen könnten.  Vor einiger Zeit bin ich auf einen Blogbeitrag gestoßen, wie Matt Thorson in seinen Spielen mit der Physik umgeht. Grundsätzlich erfolgt bei dieser Methode die Bewegung immer in 1px-Intervallen.  Wenn eine Bewegung für ein bestimmtes Bild größer als ein Pixel ist, wird der Bewegungsvektor in viele 1px-Bewegungen aufgeteilt, und nach jeder Bewegung werden die Bedingungen für eine Kollision mit dem Gelände geprüft.

Das erspart uns die Kopfschmerzen, wenn wir versuchen, Hindernisse entlang der Bewegungslinie auf einmal zu finden. Stattdessen können wir es iterativ tun. Dies macht die Implementierung einfacher, erhöht aber leider auch die Anzahl der durchgeführten Kollisionsprüfungen, so dass dies für Spiele mit vielen sich bewegenden Objekten ungeeignet sein kann, insbesondere bei Spielen mit hoher Auflösung, bei denen die Geschwindigkeit, mit der sich die Objekte bewegen, natürlich höher ist.  Das Plus ist, dass, obwohl es mehr Kollisionsprüfungen gibt, jede Prüfung viel einfacher ist, da sie weiß, dass sich der Charakter jedes Mal um ein Pixel bewegt.

Steigung-Daten

Beginnen wir mit der Definition der Daten, die zur Darstellung der Steigungen erforderlich sind. Zunächst benötigen wir eine Höhenkarte mit einer Neigung, die die Form bestimmt. Beginnen wir mit einem klassischen 45-Grad-Gefälle.

Slopes Data

Definieren wir auch eine andere Böschungsform. Dieser wird mehr als ein Boden auf dem Boden als alles andere dienen.

Another slope shape

Natürlich werden wir Varianten dieser Steigung verwenden wollen, je nachdem, wo wir sie platzieren möchten. Im Fall unserer definierten 45-Grad-Neigung wird es z. B. gut passen, wenn sich rechts ein fester Block befindet. Wenn sich jedoch der feste Block links befindet, möchten wir eine umgedrehte Version der Kachel verwenden definiert.  Wir müssen in der Lage sein, die Neigungen auf der X-Achse und der Y-Achse umzudrehen und sie um 90 Grad zu drehen, um auf alle Varianten einer vordefinierten Neigung zugreifen zu können.

Schauen wir uns an, wie die Transformationen der 45-Grad-Neigung aussehen.

Transformations of the 45 degree slope

Wie Sie sehen, können wir in diesem Fall alle Varianten mit Flips erhalten. Wir müssen die Steigung nicht wirklich um 90 Grad drehen, aber sehen wir, wie die zweite Steigung aussieht, die wir zuvor definiert haben.

Rotating slopes

Rotierende SteigungenIn diesem Fall ermöglicht die 90-Grad-Rotationstransformation das Anordnen der Neigung an der Wand.

Offsets berechnen

Verwenden Sie unsere definierten Daten, um die Offsets zu berechnen, die auf das Objekt angewendet werden müssen, das sich mit einer Kachel überschneidet. Der Versatz enthält die Informationen über:

  • wie viel ein Objekt nach oben/unten/links/rechts bewegen muss, um nicht mit einer Kachel zu kollidieren
  • wie viel ein Objekt bewegt werden muss, um sich direkt neben der oberen/unteren/linken/rechten Oberfläche einer Neigung zu befinden
Calculating Offsets

Die grünen Teile des obigen Bildes sind die Teile, bei denen das Objekt die leeren Teile der Kachel überlappt, und die gelben Quadrate geben den Bereich an, in dem das Objekt die Neigung überlappt.

Beginnen wir nun mit der Berechnung des Offsets für Fall 1.

Das Objekt kollidiert mit keinem Teil der Steigung. Das bedeutet, dass wir ihn nicht wirklich aus der Kollision herausbewegen müssen, sodass der erste Teil unseres Versatzes auf 0 gesetzt wird.

Wenn Sie möchten, dass der untere Teil des Objekts die Steigung berührt, müssen Sie den zweiten Teil des Versatzes um 3 Pixel nach unten verschieben. Wenn wir wollten, dass die rechte Seite des Objekts die Steigung berührt, müssen wir das Objekt um 3 Pixel nach rechts verschieben.  Damit die linke Seite des Objekts den rechten Rand der Neigung berührt, müssen Sie das Objekt um 16 Pixel nach rechts verschieben. Wenn der obere Rand des Objekts die Steigung berühren soll, müssen wir das Objekt um 16 Pixel nach unten verschieben.

Warum brauchen wir nun die Information, wie weit der Abstand zwischen Objektkante und Steigung ist? Diese Daten sind für uns sehr nützlich, wenn wir möchten, dass ein Objekt an der Steigung haften bleibt.

Angenommen, ein Objekt bewegt sich auf unserer 45-Grad-Steigung nach links. Wenn es sich schnell genug bewegt, landet es in der Luft und fällt schließlich wieder auf den Abhang und so weiter.  Wenn wir möchten, dass er auf der Piste bleibt, wird er jedes Mal, wenn er sich nach links bewegt, nach unten gedrückt, damit er mit der Piste in Kontakt bleibt. Die folgende Animation zeigt den Unterschied zwischen der Aktivierung oder Deaktivierung der Neigung eines Charakters.

Animation of moving down a slope

Animation einer HangabfahrtHier werden viele Daten zwischengespeichert. Grundsätzlich möchten wir für jede mögliche Überlappung mit einer Kachel einen Versatz berechnen. Das bedeutet, dass wir für jede Position und für jede Überlappungsgröße einen schnellen Überblick darüber haben, wie viel ein Objekt verschoben werden soll.  Beachten Sie, dass wir Die endgültigen Offsets können nicht zwischengespeichert werden, da wir keinen Offset für jede mögliche AABB im Cache speichern können. Es ist jedoch einfach, den Offset anzupassen, da die AABB sich mit der Kachel der Steigung überlappt.

Fliesen definieren

Wir definieren alle Steigungsdaten in einer statischen Slopes-Klasse.

Lassen Sie uns zunächst mit den Höhenkarten umgehen. Lassen Sie uns einige davon definieren, die später verarbeitet werden sollen.

Fügen wir die Testkacheltypen für die definierten Steigungen hinzu.

Lassen Sie uns auch eine weitere Aufzählung für Fliesenkollisionstypen erstellen. Dies ist hilfreich, wenn Sie verschiedenen Steinen den gleichen Kollisionstyp zuweisen möchten, beispielsweise eine grasbewachsene Neigung von 45 Grad oder eine Steigung von 45 Grad.

Nun erstellen wir ein Array, das alle Heightmaps der Kacheln enthält. Dieses Array wird von der TileCollisionType-Enumeration indiziert.

Bearbeitung der Steigungen

Bevor wir mit der Berechnung der Offsets beginnen, wollen wir unsere Heightmaps in vollständige Kollisionsbitmaps entfalten.  Das macht es leicht zu bestimmen, ob eine AABB mit einer Kachel kollidiert, und ermöglicht auch komplexere Kachelformen, wenn dies erforderlich ist. Erstellen wir ein Array für diese Bitmaps.

Nun erstellen wir eine Funktion, die die Höhenkarte in die Bitmap erweitert.

Nichts hier kompliziert - wenn eine bestimmte Position auf der Kachel fest ist, setzen wir sie auf 1; Wenn nicht, wird es auf 0 gesetzt.

Jetzt erstellen wir unsere Init-Funktion, die schließlich alle Caching-Aufgaben erledigt, die wir auf den Steigungen erledigen müssen.

Lassen Sie uns hier die Container-Arrays erstellen.

Lassen Sie uns nun jeden Fliesenkollisionstyp auf die entsprechenden zwischengespeicherten Daten zeigen.

Versatzstruktur (Offset Structure)

Jetzt können wir unsere Versatzstruktur definieren.

Wie zuvor erläutert, entsprechen die Variablen freeLeft, freeRight, freeDown und freeUp dem Offset, der angewendet werden muss, damit das Objekt nicht mehr mit der Steigung kollidiert, während collidingLeft, collidingRight, collidingTop und collidingBottom der Abstand des Objekts sind muss verschoben werden, um die Steigung zu berühren, ohne sie zu überlappen.

Es ist an der Zeit, unsere Hochleistungs-Caching-Funktion zu erstellen, aber bevor wir dies tun, erstellen wir einen Container, der all diese Daten enthält.

Und erstellen Sie das Array in der Init-Funktion.

Speicherprobleme

Wie Sie sehen, hat dieses Array viele Dimensionen, und für jeden neuen Kacheltyp ist tatsächlich viel Speicher erforderlich. Für jede X-Position in der Kachel, für jede Y-Position in der Kachel, für jede mögliche Breite in der Kachel und für jede mögliche Höhe gibt es eine separate Berechnung des Offsetwerts.

Da die verwendeten Kacheln 16 x 16 sind, bedeutet dies, dass die für jeden Kacheltyp benötigte Datenmenge 16 * 16 * 16 * 16 * 8 Byte beträgt, was 512 kB entspricht. Dies ist eine Menge von Daten, die jedoch immer noch überschaubar sind. Wenn das Zwischenspeichern dieser Informationsmenge nicht möglich ist, müssen wir entweder auf die Berechnung der Offsets in Echtzeit umstellen, wahrscheinlich mit einer effizienteren Methode als der, die wir verwenden zum Zwischenspeichern verwenden oder unsere Daten optimieren.

Wenn die Kachelgröße in unserem Spiel größer wäre, beispielsweise 32x32, würde jeder Kacheltyp 8 MB belegen, und wenn wir 64x64 verwenden, wären es 128 MB.  Diese Beträge scheinen viel zu groß zu sein, um nützlich zu sein, vor allem, wenn wir einige Hangtypen im Spiel haben möchten.  Eine sinnvolle Lösung dafür scheint die Aufteilung der großen Kollisionsplättchen in kleinere zu sein. Beachten Sie, dass nur für jede neu definierte Steigung mehr Speicherplatz erforderlich ist. Die Umwandlungen verwenden dieselben Daten.

Kollisionen innerhalb einer Kachel prüfen

Bevor wir mit der Berechnung der Offsets beginnen, müssen wir wissen, ob ein Objekt an einer bestimmten Position mit den festen Teilen der Kachel kollidiert. Lassen Sie uns zuerst diese Funktion erstellen.

Die Funktion übernimmt die Kollisionsbitmap, die Position der Überlappung und die Überlappungsgröße. Die Position ist das untere linke Pixel des Objekts und die Größe ist die 0-basierte Breite und Höhe.  Mit 0 meine ich, dass eine Breite von 0 bedeutet, dass das Objekt tatsächlich 1 Pixel breit ist, und eine Breite von 15 bedeutet, dass das Objekt 16 Pixel breit ist.  Die Funktion ist sehr einfach: Wenn sich die Pixel eines Objekts mit einer Steigung überlappen, wird true zurückgegeben, andernfalls false.

Berechnen Sie die Offsets

Beginnen wir nun mit der Berechnung der Offsets.

Um den Versatz zu berechnen, benötigen wir das Kollisionsbitmap, die Position und die Größe der Überlappung. Beginnen wir mit der Deklaration der Offset-Werte.

Lassen Sie uns nun berechnen, um wie viel wir das Objekt verschieben müssen, damit es nicht mit der Steigung kollidiert.Um das zu erreichen, müssen wir, während das Objekt mit der Steigung kollidiert, es weiter nach oben bewegen und auf Kollision prüfen, bis es keine Überlappung mit den festen Teilen der Kachel gibt.

No overlaps

Keine ÜberlappungenOben sehen Sie, wie wir den Versatz berechnen. Im ersten Fall müssen Sie, da das Objekt die obere Begrenzung der Kachel berührt, nicht nur es nach oben verschieben, sondern auch seine Höhe verringern.  Wenn sich ein Teil der AABB außerhalb der Kachelgrenzen befindet, interessiert uns das nicht mehr. In ähnlicher Weise werden Offsets für alle anderen Richtungen berechnet. Für das obige Beispiel wären die Offsets also:

  • 4 für den Aufwärtsversatz
  • -4 für den linken Versatz
  • -16 für den Abwärtsversatz - das ist die maximale Entfernung, denn wenn wir das Objekt nach unten verschieben, müssen wir es ganz aus den Grenzen der Kachel heraus bewegen, um die Kollision mit der Steigung zu beenden
  • 16 für den richtigen Versatz

Beginnen wir damit, die temporäre Variable für die Höhe des Objekts zu deklarieren. Wie oben erwähnt, ändert sich dies abhängig davon, wie hoch das Objekt bewegt wird.

Jetzt ist es Zeit für die Hauptbedingung. Solange sich das Objekt nicht aus den Kachelgrenzen herausbewegt hat und mit den festen Teilen der Kachel kollidiert, müssen wir die offsetUp erhöhen.

Schließlich passen wir die Größe des überlappenden Bereichs der Objektkachel an, wenn sich das Objekt außerhalb der Kachelgrenzen befindet.

Jetzt machen wir dasselbe für den linken Versatz. Beachten Sie, dass wir die Position nicht wirklich ändern müssen, wenn wir das Objekt nach links verschieben und das Objekt aus den Kachelgrenzen herausbewegt wird. Stattdessen ändern wir nur die Breite der Überlappung.  Das ist auf der rechten Seite der Animation dargestellt und veranschaulicht die Offsetberechnung.

Da hier jedoch der freeLeft-Versatz nicht verschoben wurde, da wir die Breite verringert haben, müssen wir die reduzierte Größe in den Versatz konvertieren.

Jetzt machen wir dasselbe für die Abwärts- und Rechtsversätze.

In Ordnung, wir haben den ersten Teil des Versatzes berechnet - das ist, wie viel wir das Objekt bewegen sollten, damit es nicht mehr mit der Steigung kollidiert. Nun ist es an der Zeit, die Offsets herauszufinden, die das Objekt direkt neben den festen Teilen der Kachel bewegen sollen.

Beachten Sie, dass wir das bereits tun, wenn wir das Objekt aus der Kollision herausbewegen müssen, da wir unmittelbar nach der Kollision aufhören.

Move the object out of collision

Bewegen Sie das Objekt aus der KollisionIm rechten Fall ist der Aufwärtsversatz 4, aber es ist auch der Versatz, den wir benötigen, um das Objekt zu verschieben, damit der untere Rand auf einem festen Pixel liegt. Gleiches gilt für die anderen Seiten.

Nun ist der Fall links, wo wir die Offsets selbst finden müssen. Wenn Sie den collidingBottom-Versatz dort finden möchten, müssen Sie das Objekt um 3 Pixel nach unten verschieben. Die Berechnungen, die hier benötigt werden, ähneln den vorherigen, aber stattdessen werden wir suchen, wann das Objekt mit der Neigung kollidiert und dann verschoben wird, während der Versatz um eins verringert wird, so dass die durchgehenden Pixel kaum berührt werden, anstatt sie zu überlappen.

Wenn freeUp gleich 0 ist, muss free down gleich 0 sein, sodass wir die Berechnungen für collidingTop unter denselben Klammern angeben können. Diese Berechnungen sind wiederum analog zu dem, was wir bisher gemacht haben.

Machen wir dasselbe für den linken und den rechten Versatz.

Daten zwischenspeichern

Nachdem nun alle Offsets berechnet wurden, können wir den Offset für diesen bestimmten Datensatz zurückgeben.

Erstellen Sie einen Container für alle unsere zwischengespeicherten Daten.

Initialisieren Sie das Array.

Erstellen Sie schließlich die Caching-Funktion.

Die Funktion selbst ist sehr einfach, daher ist es sehr einfach zu sehen, wie viele Daten zwischengespeichert werden, um unsere Anforderungen zu erfüllen!

Stellen Sie jetzt sicher, dass die Offsets für jeden Fliesenkollisionstyp zwischengespeichert werden.

Und damit ist unsere Haupt-Caching-Funktion beendet!

Berechnung des Weltraumversatzes

Lassen Sie uns nun die zwischengespeicherten Daten verwenden, um eine Funktion zu erstellen, die einen Versatz für ein Zeichen zurückgibt, das in einem Weltraum existiert.

Der Offset, den wir zurückgeben, ist nicht derselbe Struktur, die wir für die zwischengespeicherten Daten verwendet haben, da die Weltraumoffsets letztendlich größer sein können als die Grenzen des einzelnen Bytes. Die Struktur ist im Grunde dasselbe, aber es werden Ganzzahlen verwendet.

Die Parameter lauten wie folgt:

  • das Weltraumzentrum der Fliese
  • die linke, rechte, untere und obere Kante der AABB, für die wir den Versatz erhalten möchtendie Art der Fliese, für die wir 
  • den Versatz erhalten möchten

Zuerst müssen wir herausfinden, wie sich die AABB mit einer Neigungskachel überlappt. Wir müssen wissen, wo die Überlappung beginnt (die untere linke Ecke) und auch, wie stark sich die Überlappung über die Kachel erstreckt.

Um das zu berechnen, lassen Sie uns zuerst die Variablen deklarieren.

Lassen Sie uns nun die Kanten der Kachel im Weltraum berechnen.

Das sollte jetzt ganz einfach sein. Es gibt zwei Hauptkategorien von Fällen, die wir hier finden können. Erstens ist die Überlappung innerhalb der Kachelgrenzen.

Das dunkelblaue Pixel ist die Position der Überlappung und die Höhe und Breite sind mit den blauen Kacheln markiert. Hier ist alles recht einfach, so dass die Berechnung der Position und der Größe der Überlappung keine zusätzlichen Aktionen erfordert.

Die zweite Kategorie von Fällen sieht wie folgt aus, und im Spiel beschäftigen wir uns hauptsächlich mit diesen Fällen:

Sehen wir uns eine Beispielsituation an, die oben abgebildet ist. Wie Sie sehen, erstreckt sich die AABB weit über die Kachel hinaus. Wir müssen jedoch die Position und Größe der Überlappung innerhalb der Kachel selbst ermitteln, sodass wir unseren zwischengespeicherten Versatzwert abrufen können.  Im Moment kümmern wir uns nicht wirklich um alles, was außerhalb der Fliesengrenzen liegt. Das erfordert, dass wir die Überlappungsposition und -größe an die Grenzen der Fliese klemmen.

Position x ist gleich dem Abstand zwischen der linken Kante der AABB und der linken Kante der Kachel. Wenn sich AABB links von der linken Kante der Kachel befindet, muss die Position auf 0 geklemmt werden. Um die Überlappungsbreite zu erhalten, müssen wir die rechte Kante der AABB von der x-Position der Überlappung subtrahieren, die wir bereits berechnet haben.Die

 Werte für die Y-Achse werden auf dieselbe Weise berechnet.

Jetzt können wir die zwischengespeicherten Versätze für die Überlappung abrufen.

Passen Sie den Offset an

Bevor wir den Versatz zurückgeben, müssen wir ihn möglicherweise anpassen. Betrachten Sie die folgende Situation.

Mal sehen, wie unser zwischengespeicherter Offset für eine solche Überlappung aussehen würde. Beim Zwischenspeichern waren wir nur über die Überlappung innerhalb der Kachelgrenzen besorgt. In diesem Fall wäre der Aufwärtsversatz gleich 9.  Sie können sehen, dass der Überlappungsbereich innerhalb der Kachelgrenzen um 9 Pixel nach oben verschoben würde mit der Steigung kollidieren, aber wenn wir die gesamte AABB verschieben, bewegt sich der Bereich, der sich unterhalb der Kachelgrenzen befindet, in die Kollision.

Grundsätzlich müssen wir hier den Aufwärtsversatz um die Anzahl der Pixel anpassen, die die AABB unterhalb der Kachelgrenzen erstreckt.

Für alle anderen Offsets - links, rechts und unten - muss dasselbe getan werden, mit der Ausnahme, dass wir die linke und rechte Offsets auf diese Weise jetzt überspringen, da das nicht notwendig ist.

Sobald wir fertig sind, können wir den angepassten Offset zurückgeben. Die fertige Funktion sollte so aussehen.

Natürlich ist es noch nicht vollständig fertig. Später werden wir auch die Kachelumwandlungen hier behandeln, sodass der Versatz entsprechend zurückgegeben wird, je nachdem, ob die Kachel auf den XY-Achsen gedreht oder um 90 Grad gedreht wurde.  Im Moment spielen wir jedoch nur mit den nicht transformierten Plättchen.

Ein-Pixel-Schrittphysik implementieren

Überblick

Wenn Sie die Objekte um ein Pixel verschieben, ist es sehr einfach, viele Dinge zu handhaben, insbesondere bei Kollisionen mit Neigungen für schnelle Objekte. Obwohl wir jeden Pixel, auf den wir uns bewegen, auf Kollision prüfen, sollten wir uns in einem bestimmten Muster bewegen Genauigkeit gewährleisten.  Dieses Muster hängt von der Objektgeschwindigkeit ab.

Checking 1-pixel collisions

Auf dem Bild oben können Sie sehen, dass, wenn wir das Objekt zunächst blind bewegen, alle Pixel, die es horizontal bewegen muss, und danach der Pfeil mit einem festen Block kollidieren würde, der nicht wirklich auf Kurs ist. Die Reihenfolge der Bewegung sollte auf dem Verhältnis der vertikalen zur horizontalen Geschwindigkeit basieren. Auf diese Weise wissen wir, wie viele Pixel wir für jedes horizontal bewegte Pixel vertikal verschieben müssen.

Definieren Sie die Daten

Gehen wir zu unserer Klasse für sich bewegende Objekte und definieren Sie einige neue Variablen.

Zunächst enthält unsere mPosition-Hauptvariable nur die Ganzzahl, und wir behalten eine andere Variable mit dem Namen mRemainder, um den Wert nach dem Fließkomma zu behalten.

Als Nächstes fügen wir ein paar neue Positionsstatusvariablen hinzu, um anzuzeigen, ob sich der Charakter aktuell auf der Steigung befindet. An diesem Punkt ist es gut, wenn wir den gesamten Positionsstatus in eine einzige Struktur packen.

Lassen Sie uns nun eine Instanz der Struktur für das Objekt deklarieren.

Eine andere Variable, die wir brauchen, ist das Hängenbleiben.

Grundlegende Implementierung

Beginnen wir mit dem Erstellen der grundlegenden Funktionen zur Kollisionsprüfung. Diese werden die Pisten noch nicht bewältigen können.

Kollisionsprüfungen

Beginnen wir mit der rechten Seite.

Die hier verwendeten Parameter sind die aktuelle Position des Objekts, seine oberen rechten und unteren linken Ecken sowie der Positionsstatus. Zuerst berechnen wir die obere rechte und obere linke Kachel für unser Objekt.

Lassen Sie uns nun alle Kacheln entlang der rechten Kante des Objekts durchlaufen.

Abhängig von der Kollisionsplatte reagieren wir jetzt entsprechend.

Wie Sie sehen können, überspringen wir zunächst die Pisten. Wir möchten nur die grundlegenden Einstellungen vornehmen, bevor wir uns näher damit befassen.

Insgesamt sollte die Funktion jetzt so aussehen:

Wir werden dasselbe für alle anderen drei Richtungen tun: links, oben und unten.

Funktionen verschieben

Nun, da wir uns damit befasst haben, können wir zwei für die Bewegung verantwortliche Funktionen erstellen. Einer wird die Bewegung horizontal und ein anderer die vertikale Bewegung ausführen.

Die Argumente, die wir in dieser Funktion verwenden, sind die aktuelle Position, ein Boolescher Wert, der angibt, ob wir auf dem Weg ein Hindernis finden oder nicht, ein Versatz, der angibt, wie viel wir bewegen müssen, ein Schritt, bei dem wir das Objekt verschieben Bei jeder Iteration die unteren linken und oberen rechten Eckpunkte der AABB und schließlich der Positionsstatus.

Im Grunde wollen wir das Objekt so oft um einen Schritt verschieben, dass sich die Schritte auf den Versatz summieren.Wenn wir auf ein Hindernis stoßen, müssen wir natürlich auch aufhören, uns zu bewegen.

Bei jeder Iteration subtrahieren wir den Schritt vom Versatz, so dass der Versatz schließlich zu Null wird und wir wissen, dass wir so viele Pixel verschoben haben, wie wir benötigen.

Mit jedem Schritt möchten wir prüfen, ob wir mit einer Kachel kollidieren. Wenn wir uns nach rechts bewegen, wollen wir prüfen, ob wir rechts mit einer Wand kollidieren. Wenn wir uns nach links bewegen, wollen wir links nach Hindernissen suchen.

Wenn wir kein Hindernis gefunden haben, können wir das Objekt verschieben.

Nachdem wir uns bewegt haben, überprüfen wir schließlich, ob Kollisionen auf und ab auftreten, da wir direkt unter oder über einen Block rutschen könnten. Das ist nur zum Aktualisieren des Positionsstatus, um genau zu sein.

Die MoveY-Funktion funktioniert ähnlich.

Konsolidieren Sie die Bewegung

Da wir nun Funktionen haben, die für die vertikale und horizontale Bewegung zuständig sind, können wir die Hauptfunktion für die Bewegung erstellen.

Die Funktion berechnet den Wert, um den das Objekt bewegt werden soll, die aktuelle Geschwindigkeit des Objekts, seine aktuelle Position zusammen mit dem Gleitkomma-Rest, der AABB des Objekts und dem Positionsstatus.

Das erste, was wir hier tun werden, ist den Versatz zum Rest hinzuzufügen, so dass wir im Rest den vollen Wert haben, wie viel sich unser Charakter bewegen sollte.

Da wir die MoveX- und MoveY-Funktionen von hier aus aufrufen, müssen wir die oberen rechten und unteren linken Ecken der AABB übergeben, also lassen Sie uns diese jetzt berechnen.

Wir müssen auch den Schrittvektor erhalten. Es wird als eine Richtung verwendet, in der wir unser Objekt bewegen werden.

Nun wollen wir sehen, wie viele Pixel wir wirklich bewegen müssen. Wir müssen den Rest abrunden, da wir uns immer um eine ganze Zahl bewegen und dann diesen Wert vom Rest abziehen müssen.

Jetzt teilen wir die Bewegung in vier Fälle auf, abhängig von unseren Bewegungsvektorwerten. Wenn die x- und y-Werte des Bewegungsvektors gleich 0 sind, ist keine Bewegung vorzunehmen, sodass wir einfach zurückkehren können.

Wenn nur der y-Wert 0 ist, bewegen wir uns nur horizontal.

Wenn nur der x-Wert 0 ist, bewegen wir uns nur vertikal.

Wenn wir uns sowohl auf der x- als auch auf der y-Achse bewegen müssen, müssen wir uns in einem Muster bewegen, das zuvor beschrieben wurde. Lassen Sie uns zunächst das Drehzahlverhältnis berechnen.

Lassen Sie uns auch den vertikalen Akkumulator erklären, der enthält, wie viele Pixel wir mit jeder Schleife vertikal bewegen müssen.

Die Bedingung zum Anhalten der Bewegung ist die, dass wir entweder auf einer der Achsen ein Hindernis getroffen haben oder das Objekt durch den gesamten Bewegungsvektor bewegt wurde.

Lassen Sie uns nun berechnen, um wie viele Pixel wir das Objekt vertikal verschieben sollen.

Für die Bewegung bewegen wir uns zunächst einen Schritt horizontal.

Und danach können wir uns vertikal bewegen. Hier wissen wir, dass wir das Objekt um den im vertAccum enthaltenen Wert verschieben müssen, aber bei Ungenauigkeiten, wenn wir uns auf der X-Achse ganz bewegen, müssen wir uns auch auf der Y-Achse bewegen.

Alles in allem sollte die Funktion so aussehen:

Jetzt können wir die Funktionen verwenden, die wir erstellt haben, um unsere Hauptfunktion UpdatePhysics zusammenzustellen.

Erstellen Sie die Physik-Aktualisierungsfunktion

Zuallererst möchten wir den Positionsstatus aktualisieren, so dass alle Daten des vorherigen Frames zu den entsprechenden Variablen gehen und die Daten des aktuellen Frames zurückgesetzt werden.

Lassen Sie uns nun den Kollisionszustand unseres Objekts aktualisieren. Wir tun dies, damit wir, bevor wir unser Objekt bewegen, Daten aktualisiert haben, ob es sich auf dem Boden befindet oder andere Kacheln schiebt.  Normalerweise wären die Daten des vorherigen Rahmens immer noch auf dem neuesten Stand, wenn das Gelände nicht veränderbar wäre und andere Objekte dieses Objekt nicht verschieben könnten. Hier wird jedoch davon ausgegangen, dass dies passieren könnte.

CollidesWithTiles ruft einfach alle Kollisionsfunktionen auf, die wir geschrieben haben.

Dann die Geschwindigkeit aktualisieren.

Und aktualisieren Sie die Position. Lassen Sie uns zunächst den alten speichern.

Berechnen Sie die neue.

Berechnen Sie den Abstand zwischen den beiden.

Wenn der Versatz nicht Null ist, können wir unsere Verschiebungsfunktion aufrufen.

Aktualisieren Sie schließlich die AABB des Objekts und den Positionsstatus.

Das ist es! Dieses System ersetzt jetzt das ältere, die Ergebnisse sollten die gleichen sein, obwohl die Art und Weise, wie wir sie ausführen, ein bisschen anders ist.

Zusammenfassung

Das ist es, um die Grundlagen für die Pisten zu schaffen. Was bleibt, ist, diese Lücken in unseren Kollisionsüberprüfungen zu füllen! Wir haben hier den Großteil unserer Caching-Arbeit geleistet und viele geometrische Komplexitäten durch die Implementierung der Einpixel-Bewegungsintegration beseitigt.

Das macht die Implementierung der Piste zu einem Kinderspiel, verglichen mit dem, was wir sonst tun müssten. Wir werden den Job im nächsten Teil der Serie beenden.

Danke fürs Lesen!

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.