Okay, das ist ein Problem, das ich schon seit einiger Zeit herauszufinden versuche. Meins ist ein 2D-Plattformspiel mit einer Welt aus (normalerweise) unbeweglichen Kacheln und mobilen Sprites, die beide AABBs verwenden, um ihre Hitboxen darzustellen. Dieses Spiel ist aufgrund einiger Komplikationen beim Verschieben von Kachelebenen NICHT gitterbasiert.
Ich kann Kollisionen erkennen und die Tiefe der Kollision leicht herausfinden. Ich verwende die "Methode der flachsten Achse", um zu bestimmen, wie eine Kollision zwischen dem Sprite und der Kachel gelöst werden kann. Wenn das Sprite horizontal tiefer als vertikal ist, ist die aufzulösende Richtung entweder oben oder unten. Wenn das Sprite vertikal tiefer als horizontal ist, ist die aufzulösende Richtung entweder links oder rechts.
Das ist einfach genug und funktioniert ziemlich gut. Das heißt, bis ein Sprite mit mehr als einer Kachel kollidiert. Da von Natur aus jede Kollision separat überprüft werden muss, können unterschiedliche Kollisionen unterschiedliche Auflösungsrichtungen haben. Wenn beispielsweise ein Sprite versucht, über eine Reihe von Kacheln zu laufen, schneiden sie für einen Frame die nächste Kachel wie z dass die horizontale Tiefe kürzer als die vertikale Tiefe ist. Wenn die Kollision "links auflösen" lautet, wird sie zurückgeschoben und bleibt an der Ecke hängen.
Ich habe über dieses Problem schon seit einiger Zeit nachgedacht, und es sind mehrere Lösungen zu mir gekommen, aber alle haben Mängel. Ich könnte bestimmte Seiten als nicht erreichbar markieren, aber ohne eine gitterbasierte Engine ist die Bestimmung der "Nichterreichbarkeit" bemerkenswert komplex, insbesondere wenn sich bewegende Kachelschichten immer möglich sind.
Eine andere mögliche Methode wäre, Kollisionen vorherzusagen, bevor sie auftreten, und die Bewegung bis zum Punkt der Kollision "zurückzuarbeiten", nehme ich an, aber ich bin mir nicht sicher, wie die Mathematik dafür funktioniert.
Ich habe das Gefühl, dass mir etwas unglaublich Offensichtliches fehlt, zumal Spiele aus den 80ern dieses Problem bereits gelöst haben.
Antworten:
Das Problem
Das Problem liegt in Ihrer Methode zur Kollisionsauflösung. Ihre Methode lautet wie folgt:
Das Problem dabei ist, dass es den Spieler leicht in die falsche Richtung bewegen kann. Wie dies passieren kann, sehen Sie im Bild unten:
Da sich der Spieler nach rechts unten bewegt und sich über dem Boden befindet, würde man erwarten, dass der Spieler auf dem Boden landet (neben dem grünen Kästchen). Stattdessen wird es nach links aus dem Boden geschoben (dargestellt durch das rote Kästchen). Dies kann ein Problem sein, wenn der Spieler versucht, von einer Plattform zur anderen zu springen, da der Spieler aufgrund eines schlechten Kollisionscodes möglicherweise zu Tode fällt.
Die Lösung
Die Lösung für dieses Problem ist eigentlich ziemlich einfach. Anstatt die obige Methode zu verwenden, lösen Sie die Kollision folgendermaßen auf:
Jetzt hoffe ich, dass Sie Ihren Tiefenprüfcode nicht weggeworfen haben, da Sie ihn für die Schritte 3 und 6 noch benötigen.
Um die Kollision zwischen Kacheln auf einer der beiden Achsen (nach dem Bewegen des Spielers) aufzulösen, erhalten Sie zuerst die Tiefe der Kollision. Sie nehmen dann die Tiefe der Kollision und subtrahieren diese von den Achsen, die Sie gerade auf Kollision prüfen. Beachten Sie, dass die Tiefe negativ sein sollte, wenn Sie sich nach links bewegen, damit sich der Spieler in die richtige Richtung bewegt.
Mit dieser Methode müssen Sie sich nicht nur nicht um Kollisionsfehler wie im Szenario im obigen Bild kümmern, sondern diese Kollision kann auch mit Kollisionen mit mehreren Kacheln umgehen.
Beispielcode:
quelle
float
s zum Speichern meiner Koordinaten verwendete. Es verursachte also ein Zittern. Die Lösung bestand darin, die Koordinaten abzurunden, wenn ich die Kollision gelöst hatte.Sie überdenken das Problem und bringen ein paar Probleme zusammen. Aber das ist okay, denn wie Sie sagten, ist dies ein sehr gelöstes Problem mit vielen tollen Antworten.
Lassen Sie es uns zusammenfassen:
Tilemaps . Ihr erstes Beispiel ist ein Sprite, der über eine Reihe horizontal angelegter Kacheln läuft (oder eine vertikal angelegte Kachelwand hinuntergleitet, sie sind isomorph). Eine sehr elegante Lösung hierfür besteht darin, die Kanten von Kacheln, an die ein Sprite nicht gelangen kann, einfach nicht zu überprüfen, z. B. Kanten, die "unterirdisch" sind, oder Kanten, die an eine andere vollständig feste Kachel grenzen.
Sie haben Recht, dass das Sprite aufgrund der Schwerkraft abfällt, sich dann seitlich bewegt und dann stecken bleibt ... aber die Antwort ist, sich nicht um den linken oder rechten Rand der unterirdischen Kacheln zu kümmern . Auf diese Weise bewegt Ihre Kollisionsauflösungsroutine das Sprite nur vertikal - und Ihr Sprite kann seinen fröhlichen Weg fortsetzen.
In den Metanet-Kachel-Tutorials finden Sie eine schrittweise Erklärung. Sie sagen in Ihrer Frage, dass Sie keine herkömmliche Tilemap verwenden, aber das ist auch in Ordnung: Statische Kacheln befinden sich in der Tilemap und werden wie oben aktualisiert, während Plattformen verschoben werden und Updates wie die Nummer 2 unten.
Andere AABBs . Sie werden nur dann auf ein Problem stoßen, wenn sich Ihr Sprite in einem einzigen Frame um eine Strecke bewegen kann, die größer ist als die Breite / Höhe der meisten AABBs in Ihrem Spiel. Wenn dies nicht möglich ist, sind Sie goldrichtig: Lösen Sie die Kollisionen nacheinander, und es funktioniert einwandfrei.
Wenn sich die AABBs in einem einzelnen Frame sehr schnell bewegen können , sollten Sie die Bewegung bei der Überprüfung auf Kollisionen "fegen": Teilen Sie die Bewegung in kleinere Brüche auf und überprüfen Sie sie bei jedem Schritt auf Kollisionen.
quelle