Nach Kollision mit dem Rechteck-Begrenzungsrahmen in der Wand stecken

7

Mit XNAs in Intersects () auf zwei Rechtecken kann ich eine Kollision erkennen und meine Geschwindigkeit auf Null setzen. Das Objekt steckt jedoch dort fest und kann nicht raus! Wie kann ich diese Kollision richtig beheben?

Jopo
quelle

Antworten:

12

Dies liegt daran, dass Sie, sobald Ihr Objekt in die Wand gelangt und Sie die Kollision gefunden haben, die Bewegung des Objekts einfach stoppen, indem Sie seine Geschwindigkeit auf Null setzen, das Objekt jedoch stillsteht innerhalb dieser Wand.

Um dies zu beheben, müssen Sie die Kollision durch Verschieben des Objekts beheben . Sie haben hier zwei Möglichkeiten:

  • Bewegen Sie das Objekt zurück in seine alte Position, indem Sie das Gegenteil der Geschwindigkeit anwenden, um die Bewegung abzubrechen, sobald Sie eine Kollision feststellen. Vorteile: extrem einfach zu implementieren. Wenn es Ihr Spiel nicht beeinflusst, wählen Sie diese Option. Nachteile: Dadurch wird verhindert, dass sich das Objekt in eine Richtung bewegt, die eine Kollision verursachen würde (sodass Sie beispielsweise nicht an einer Wand entlang gleiten können).
  • Finden Sie heraus, wo sich das Objekt befindet, und lösen Sie die Kollision entsprechend auf. Wenn das Objekt beispielsweise von links kommt und auf der linken Seite der Wand kollidiert, bewegen Sie das Objekt einfach links von der Wand. Wenn dies auf allen Seiten der Rechtecke wiederholt wird, kann sich das Objekt weiter in Richtung seiner gewünschten Geschwindigkeit bewegen, vermeidet jedoch Kollisionen.

Implementierung der zweiten Option

Hier werde ich davon ausgehen , dass die Geschwindigkeit , die Richtung darstellt , in dem das Objekt wird (im Grunde , dass Sie nicht die Geschwindigkeit Wechsel zwischen der Positionsänderung des Objekts und der Kollisionsprüfung). Ich gehe auch davon aus, dass sich Ihr Ursprung oben links im Bild befindet (wenn Sie also das Objekt bewegen, um die Kollision zu beheben, positioniere ich die obere linke Ecke).

So würde ich es machen:

if (objRect.Intersects(wallRect)) // If there is a collision
{
    Vector2 newPos = obj.Position;

    if (obj.Velocity.X > 0) // object came from the left
        newPos.X = wallRect.Left - objRect.Width;
    else if (obj.Velocity.X < 0) // object came from the right
        newPos.X = wallRect.Right;
    if (obj.Velocity.Y > 0) // object came from the top
        newPos.Y = wallRect.Top - objRect.Height;
    else if (obj.Velocity.Y < 0) // object came from the bottom
        newPos.Y = wallRect.Bottom;

    obj.Position = newPos;
}

Sie können auch die Position des alten Objekts verwenden, um herauszufinden, woher das Objekt stammt. In diesem Fall ist die Verwendung der Geschwindigkeit jedoch einfacher.

Jesse Emond
quelle
Okay, im Grunde steckt es in der Wand und die Kollision geht weiter. Wie würde ich das allerdings lösen?
Jopo
Hat es bearbeitet, wie Sie gefragt haben. Möchten Sie anhand einiger Codebeispiele zeigen, wie beide Optionen implementiert werden?
Jesse Emond
Ich habe versucht, den ersten zu implementieren, indem ich einen Vektor implementiert habe, der als Richtung bezeichnet wird und ein normalisierter Vektor ist, wobei je nach gedrückter Taste links oder rechts ist. Dann habe ich diesen mit der Geschwindigkeit multipliziert, als eine Kollision erkannt wurde. Dies funktionierte größtenteils, aber es scheint nur auf einer Seite des Rechtecks ​​zu funktionieren (auf der rechten Seite?). Für das zweite würde ich mich sehr über ein Codebeispiel freuen, da ich viel darüber gehört habe, aber keine konkreten Implementierungen gesehen habe.
Jopo
1
Ihre erste Option sollte ein Beispiel dafür sein, was Sie nicht tun sollten. Jedes Spiel mit dieser Art der Kollisionserkennung würde ich als defekt betrachten.
AttackingHobo
1
Warum wird diese Antwort nicht akzeptiert, wenn Sie die angegebene Methode implementiert haben und sie funktioniert hat?
Jonathan Connell
1

Sie können dies auf verschiedene Arten tun.

Eine Methode besteht darin, die vorherige Position des Rechtecks ​​in jedem Frame zu speichern. Wenn sich Ihre Rechtecke überschneiden, setzen Sie einfach die Objektposition auf die ältere, die nicht kollidiert. Diese Methode ist nicht die beste, da bei hoher Rechteckgeschwindigkeit möglicherweise die Neupositionierung angezeigt wird, die Sie über Code vorgenommen haben.

Eine andere Methode ist das Testen der Kollision mit einem Raycast, sodass Sie eine Vorschau einer Kollision anzeigen können, bevor sie jemals auftritt.

Schauen Sie sich msdn an, um eine Dokumentation für die Raycast-Kollision zu erhalten, und Sie werden dies tun können.

Jean
quelle