Ein einfacher 2D-Rechteck-Kollisionsalgorithmus, der auch bestimmt, auf welchen Seiten die Rechtecke kollidieren.

16

Ich habe zunächst versucht, eine rechteckige Kreuzung zu implementieren, was gut funktioniert. Wenn ich jedoch das physikalische System anwenden muss, wie Geschwindigkeits-, Beschleunigungs- und Richtungsvektoren, muss ich einen Weg finden, um zu bestimmen, welche Seite der Rechtecke kollidieren. In meinem System gibt es kein gedrehtes Rechteck, daher wurde das Problem dadurch vereinfacht. Ich konnte jedoch nicht leicht feststellen, welche Rechteckseite kollidierte. Ich habe mich schon einmal mit diesem Problem beschäftigt, bin aber kläglich gescheitert.

Was ich in der Vergangenheit getan habe, ist, den Abstand zwischen den einzelnen parallelen rechteckigen Seiten zu bestimmen und zu überprüfen, ob der Abstand nahe bei 0 liegt (verwenden Sie einen anfänglich definierten Abstandsbereich) oder 0. Für Gleitkomma-Arithmetik erweist sich dies jedoch als instabil, weil unbekannter Zeitspanne. Manchmal überschneiden sich die Rechtecke tatsächlich, bevor sie den definierten Bereich erreichen.

Andererseits habe ich darüber nachgedacht, mehrere Rechtecke zu erzeugen, jedes Rechteck für jede Seite. Nach erneutem Überlegen wäre es jedoch dasselbe wie eine parallele Seite mit Entfernungsbereichsprüfung, nur dass dieser Entfernungsbereich die Breite jedes Mini-Rechtecks ​​ist.

Also irgendeinen Vorschlag zu diesem Problem?

user1542
quelle
Verwenden Sie diskrete oder kontinuierliche Positionsaktualisierungen? (Aktualisieren Sie Ihre Geschwindigkeit durch die Beschleunigung einmal pro Bild und berechnen Sie dann die Position, oder verwenden Sie eine Funktion, um die Position zu extrapolieren)
Casey Kuball

Antworten:

24

Angepasst von meiner Antwort auf "Welche Seite wurde getroffen?" :

Ich schlage vor, die Minkowski-Summe von B und A zu berechnen , die ein neues Rechteck ist, und zu prüfen, wo das Zentrum von Rechteck A relativ zu diesem neuen Rechteck liegt (um zu wissen, ob eine Kollision stattfindet) und zu seinen Diagonalen (um zu wissen, wo die Kollision stattfindet) es passiert):

float w = 0.5 * (A.width() + B.width());
float h = 0.5 * (A.height() + B.height());
float dx = A.centerX() - B.centerX();
float dy = A.centerY() - B.centerY();

if (abs(dx) <= w && abs(dy) <= h)
{
    /* collision! */
    float wy = w * dy;
    float hx = h * dx;

    if (wy > hx)
        if (wy > -hx)
            /* collision at the top */
        else
            /* on the left */
    else
        if (wy > -hx)
            /* on the right */
        else
            /* at the bottom */
}
sam hocevar
quelle
1
Ich möchte hinzufügen, dass "oben" und "unten" relativ zu Ihrem Koordinatensystem sind. In meinem Spiel ist zum Beispiel (0,0) oben links, sie sind also von Ihrem Beispiel invertiert. Nur etwas zu beachten.
Neikos
Tolle Lösung, hat sehr gut für meine Bedürfnisse funktioniert.
Opiatefuchs
1
Gibt es einen Fehler, bei dem dx 0 wird oder dy 0 wird oder beides? Lassen Sie es mich begründen ... Wenn dx = 0 && dy == 0 bedeutet, dass beide Rechtecke denselben Ursprung haben, gibt der Algorithmus standardmäßig bottom zurück? Wenn einer von beiden 0 ist, wird das richtige Ergebnis erwartet. Ich denke, dieser Algorithmus ist korrekt, außer für den Fall, dass dx == 0 && dy == 0 ist, was unbestimmt und nicht unten sein sollte. Also aufgepasst und danke.
Prasanth
1
Nun habe ich mich gefragt, was passiert, wenn dx == dy, w == h ... und der Code entscheidet, dass das Ergebnis eine Seite ist, wenn es tatsächlich unbestimmt ist Eine Ecke eines anderen Quadrats und die Mitte des anderen Quadrats befindet sich an der Ecke des ersten Quadrats. Hier sollte die Seite unbestimmt sein - es ist nicht richtig oder unten. Es ist beides?!
Prasanth