Java 2D Platformer - Kollisionserkennung bei "schräger" Kollision

Jack159

Lieutenant
Registriert
Dez. 2011
Beiträge
766
Hallo,

Gegeben sei das folgende Beispiel (Es handelt sich hier im Screenshot um 2 direkt aufeinander folgende Frames!):

collision4.png

- Das Blaue Rechteck ist die Spielfigur.
- Das schwarze Viereck ist Teil der Umgebung (also eine Art Stein, Wand o.ä.), durch welche der Spieler nicht hindurchgehen können soll.
- Die Roten Vierecke/Rechtecke sind Rectangles, welche für die Kollisionserkennung benutzt werden. Die Spielfigur besitzt 4 Rectangles (oben, unten, rechts, links) und das schwarze Viereck nur 1 Rectangle, welcher von der Größe her identisch mit dem schwarzen Viereck an sich ist.

Bei der Spielfigur werden die 4 Rectangles in folgender Reihenfolge geprüft:
- Prüfung auf Kollision an der linken Seite der Spielfigur
- Prüfung auf Kollision an der rechten Seite der Spielfigur
- Prüfung auf Kollision an der oberen Seite der Spielfigur
- Prüfung auf Kollision an der unterenSeite der Spielfigur

Mein Problem ist nun der Fall, wie er auf dem Screenshot zu sehen ist. Die Kollisionserkennung funktioniert nicht richtig, wenn die Spielfigur von einer schrägen Richtung das den schwarzen Block knallt, da sich hier nun das linke und das untere Rectangle der Spielfigur im schwarzen Block befinden und mit diesem "kollidieren". Das Problem hierbei ist nun wie ich feststellen soll, ob die Figur sozusagen von der rechten Seite des schwarzen Blocks mit dem Block kollidierte oder zuerst von oben? Das muss ich ja deshalb wissen, um die Spielfigur entsprechend entweder oben auf den schwarzen Block positionieren zu können oder eben rechts neben dem Block.
Aber selbst wenn ich dies wüsste: Was wäre für den Fall, falls die Spielfigur mit dem linken und unteren Rectangle gleichzeitg im selben Spieltick/Spielupdate das schwarze Viereck betritt? Was dann?

Das Problem tritt besonders dann häufig auf, wenn die Anzahl der Pixel, mit der sich die Spielfigur pro Spieltick/Spielupdate fortbewegt, größer ist, als die Breite bzw. Höhe der Rectangles der Spielfigur.

Meine einzige Idee ist gewesen zu sagen, dass man die Spielfigur nur maximal mit der Breite bzw. Höhe der Rectangles der Spielfigur bewegt pro Spieltick/Spielupdate. Aber was, wenn mir diese Bewegung dann zu langsam ist? Spieltick/Spielupdates pro Sekunde erhöhen? Derzeit habe ich 60 Spieltick/Spielupdates pro Sekunde und 60 FPS. Würde ich erstere erhöhen/verringern, dann hätte ich ja sozusagen kein Async aktiviert, was ich aber aktiviert haben möchte, um Tearing zu vermeiden.

Kann jemand helfen?
Ist meine Kollisionserkennung generell komplett falsch?
 
Prüfe doch einfach die Ecken statt Seiten? :)

Bei den Schritten musst du vorab die Bewegung prüfen, ob sie im nächsten Schritt kollidieren würde.
Oder du kompensierst es mit einem Toleranzbereich, was aber nicht so sauber ist.

Hier kommt wieder Vektor Rechnung ins Spiel...
 
Zuletzt bearbeitet:
Ich hoffe, ich habe das Problem richtig verstanden. Muss das blaue Rechteck unbedingt diese vier weiteren Rechtecke an der Seite haben? Oder war das nur als Hilfe für die Kollisionserkennung gedacht?

Also normalerweise prüft man ja bei Kollision mit Rechtecken so:

Code:
protected bool Intersects(Rectangle rectA, Rectangle rectB)
{
    // Returns True if rectA and rectB contain any overlapping points
    return (rectA.Right > rectB.Left && rectA.Left < rectB.Right &&
            rectA.Bottom > rectB.Top && rectA.Top < rectB.Bottom);
}
 
Deine Kollisionslogik ist okay, wenn ich sie auch (wie im letzten Thread beschrieben) für viel zu kompliziert halte, durch die 4 Boxen für eine Figur, aber genug von dem Thema.

Was nicht geht, ist, dass du in deiner Bewegungslogik immer noch Bewegungen erlaubst, ohne vorher zu "simulieren" (hatte ich im letzten Thread schonmal erwähnt), ob bei der Bewegung eine Kollision stattfinden würde. Dabei musst du natürlich den ganzen Weg berücksichtigen, der überbrückt werden würde. Mal ein einfacheres Beispiel als deine schräge Kollision:
Die Figur läuft auf gerader Fläche von links nach rechts mit enorm hoher Geschwindigkeit (überbrückte Pixel/tick). Mitten auf dem Weg steht eine (dünne) Wand, meinetwegen 1px-Breite. Bei deiner aktuellen Herangehensweise wirst du vermutlich an der Wand vorbei teleportieren.

Dann musst du dich vom Gedanken lösen die fps kontrollieren zu können. Die sind je nach Spielsituation und abhängig von der Hardware unterschiedlich. Auf einem langsamen Rechner, der nur 30 fps schafft, wird dein Spiel unerträglich langsam. => entkoppeln ("frame independent game loop")

Edit: Habe ganz vergessen noch auf dein Problem mit der schrägen Kollision einzugehen. Ich würde im Moment der Kollision einen Positionsvergleich der 2 kollidierenden Partner machen. Dann brauchst du einen Schwellenwert, wie viel großer Zeh des Spielers über der Kiste sein muss, um als "oben drauf stehend" zu gelten. Das ist mehr eine Designentscheidung als eine technische. Ist ja mit der Realität vergleichbar. Wenn du auf einen Block hüpfst und nur mit der Fußspitze aufkommst, dann rutschst du halt ab und fällst runter. Ist zumindest der Fußballen drauf, kann das schon reichen.
 
Zuletzt bearbeitet:
Zurück
Oben