un semplice algoritmo di collisione di rettangoli 2D che determina anche su quali lati si scontrano i rettangoli?


16

Inizialmente ho provato a implementare l'intersezione rettangolare, che funziona bene. Tuttavia, quando devo applicare il sistema fisico, come velocità, accelerazione e vettori direzionali, dovrei trovare un modo per determinare quale lato dei rettangoli si scontrano. Ora, nel mio sistema, non c'è rettangolo ruotato, quindi questo ha semplificato il problema. Tuttavia, non sono riuscito a trovare un modo semplice per determinare quale lato del rettangolo si è scontrato. Una volta ho già affrontato questo problema, ma ho fallito miseramente.

Ciò che ho fatto in passato è determinare la distanza tra i lati rettangolari paralleli e verificare se la distanza è vicina a 0 (utilizzare un intervallo di distanza inizialmente definito) o è 0. Tuttavia, per l'aritmetica in virgola mobile, questo si rivela instabile perché di ignoto tempo trascorso. A volte, i rettangoli si intersecerebbero effettivamente prima di incontrare l'intervallo definito.

D'altra parte, stavo pensando di generare più rettangoli, ogni rettangolo per ogni lato. Tuttavia, dopo aver ripensato, sarebbe la stessa cosa di avere un lato parallelo con il controllo della distanza, solo che quella distanza è la larghezza di ciascun mini-rettangolo.

Pertanto, qualche suggerimento per questo problema?


Stai utilizzando aggiornamenti di posizione discreti o continui? (stai aggiornando la tua velocità con l'accelerazione una volta ogni fotogramma e poi calcolando la posizione, o usando una funzione per estrapolare la posizione)
Casey Kuball

Risposte:


24

Adattato dalla mia risposta a "Quale lato è stato colpito?" :

Suggerisco di calcolare la somma di B e A di Minkowski , che è un nuovo rettangolo, e di controllare dove si trova il centro del rettangolo A relativamente a quel nuovo rettangolo (per sapere se si sta verificando una collisione) e alle sue diagonali (per sapere dove si trova la collisione sta succedendo):

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 */
}

1
Vorrei aggiungere che 'top' e 'bottom' sono relativi al tuo sistema di coordinate. Nel mio gioco, ad esempio, (0,0) è in alto a sinistra, quindi sono invertiti dal tuo esempio. Solo qualcosa da tenere a mente.
Neikos,

ottima soluzione, ha funzionato molto bene per le mie esigenze.
Opiatefuchs,

1
C'è qualche problema tecnico con dx che diventa 0 o dy che diventa 0 o entrambi? Lasciami ragionare ... se dx = 0 && dy == 0, ciò significa che entrambi i rettangoli sono sulla stessa origine, quindi l'algoritmo restituisce bottom per impostazione predefinita? se uno di questi è 0, è previsto il risultato corretto. Quindi, penso che questo algoritmo sia corretto, tranne nel caso in cui dx == 0 && dy == 0, che dovrebbe essere indeterminato e non inferiore. Quindi, attenzione e grazie.
Prasanth,

1
Ora, mi chiedevo cosa succede quando dx == dy, w == h ... allora anche il codice decide che il risultato è un lato quando in realtà è indeterminato ... immagina due quadrati che si intersecano in modo tale che il centro di un quadrato sia a un angolo di un'altra piazza e il centro dell'altra piazza è all'angolo della prima piazza. Qui, il lato dovrebbe essere indeterminato - non è giusto o in basso. Sono entrambi ?!
Prasanth,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.