✚ Sviluppo videogiochi

Broad phase: griglie spaziali e quadtree per molte collisioni

Quando gli oggetti sono centinaia, controllare ogni coppia costa troppo: come griglie spaziali, quadtree e sweep and prune riducono i controlli.

Controllare se due oggetti si toccano è veloce. Il problema nasce quando gli oggetti sono tanti. Con 10 oggetti le coppie possibili sono 45; con 100 diventano 4.950; con 1.000 quasi mezzo milione. In uno sparatutto pieno di proiettili o in una simulazione con molte particelle, confrontare tutto con tutto a ogni fotogramma diventa rapidamente insostenibile. La soluzione è dividere il lavoro in due fasi.

Broad phase e narrow phase

  • La broad phase (fase ampia) scarta in modo economico le coppie che non possono collidere perché troppo lontane, producendo un elenco ridotto di coppie candidate.
  • La narrow phase (fase stretta) applica il test preciso, per esempio AABB contro AABB o cerchio contro cerchio, solo a queste candidate.

Il numero di coppie cresce con il quadrato del numero di oggetti: n × (n − 1) / 2. Una buona broad phase riduce questo costo a qualcosa di molto più vicino a una crescita lineare, a patto che gli oggetti siano distribuiti nello spazio e non tutti ammassati nello stesso punto.

La griglia spaziale uniforme

È la tecnica più semplice ed è sorprendentemente efficace. Si divide il mondo in celle quadrate di dimensione fissa e si registra ogni oggetto nelle celle che occupa. Due oggetti possono collidere solo se condividono almeno una cella.

dimensione_cella = 64

per ogni oggetto o:
    cx0 = floor(o.x / dimensione_cella)
    cx1 = floor((o.x + o.larghezza) / dimensione_cella)
    cy0 = floor(o.y / dimensione_cella)
    cy1 = floor((o.y + o.altezza) / dimensione_cella)
    per cx da cx0 a cx1, cy da cy0 a cy1:
        griglia[cx, cy].aggiungi(o)

per ogni cella non vuota:
    confronta tra loro gli oggetti nella cella

Scegliere la dimensione delle celle

La dimensione della cella è il parametro decisivo:

  • celle troppo piccole: ogni oggetto occupa molte celle, aumentano inserimenti e duplicati;
  • celle troppo grandi: troppi oggetti per cella, e si torna al confronto quasi completo.

Una regola pratica è usare celle grandi circa quanto l'oggetto tipico o un po' di più, per esempio una o due volte la dimensione dei nemici più comuni.

Evitare i controlli doppi

Un oggetto a cavallo di quattro celle verrebbe confrontato con lo stesso vicino fino a quattro volte. Si può memorizzare un insieme delle coppie già controllate in questo fotogramma, oppure confrontare una coppia solo nella cella che contiene, per esempio, l'angolo in alto a sinistra della loro intersezione.

Il quadtree

Il quadtree divide lo spazio in modo adattivo. Si parte da un nodo che copre tutto il mondo; quando contiene più di un certo numero di oggetti, viene suddiviso in quattro quadranti, e così via ricorsivamente fino a una profondità massima.

Il vantaggio rispetto alla griglia uniforme è l'adattamento alla densità: zone affollate vengono suddivise finemente, zone vuote restano un unico nodo grande. È utile quando gli oggetti hanno dimensioni molto diverse o si concentrano in poche aree della mappa.

Gli svantaggi sono la maggiore complessità e il costo di aggiornamento quando gli oggetti si muovono molto: spesso conviene ricostruire l'albero da zero a ogni fotogramma, cosa che con strutture ben scritte resta abbastanza rapida. Gli oggetti che stanno a cavallo dei confini tra quadranti vanno gestiti con attenzione, per esempio conservandoli nel nodo padre.

Sweep and prune

Questa tecnica sfrutta un'osservazione: due AABB possono sovrapporsi solo se si sovrappongono le loro proiezioni sull'asse x. Si ordinano gli oggetti in base al bordo sinistro e si scorre la lista mantenendo un insieme di oggetti «attivi»:

  1. si ordinano gli oggetti per x minimo;
  2. per ogni oggetto, si rimuovono dagli attivi quelli il cui x massimo è minore del suo x minimo;
  3. i rimanenti attivi sono candidati e vanno verificati con il test completo;
  4. si aggiunge l'oggetto corrente agli attivi.

Poiché tra un fotogramma e l'altro gli oggetti si spostano poco, la lista è quasi già ordinata, e un ordinamento per inserimento la sistema in tempo molto breve. Funziona bene quando gli oggetti sono sparsi lungo l'asse scelto, come in uno sparatutto a scorrimento orizzontale.

Quale scegliere

Tecnica Ideale per Punti deboli
Griglia uniforme Oggetti di dimensioni simili, mappa limitata Oggetti molto grandi o di taglie diverse
Quadtree Densità molto variabile Complessità, aggiornamento degli oggetti in movimento
Sweep and prune Oggetti sparsi lungo un asse Molti oggetti allineati sulla stessa x

Per la maggior parte dei giochi 2D indipendenti una griglia uniforme ben dimensionata è la scelta migliore: semplice da scrivere, facile da verificare e veloce. I motori fisici professionali usano spesso strutture più raffinate, come alberi di volumi di contenimento dinamici, ma il principio è lo stesso.

Ulteriori ottimizzazioni utili

  • Gruppi di collisione: i proiettili del giocatore non devono essere confrontati tra loro né con il giocatore stesso. Filtrare per categoria elimina molte coppie prima ancora della broad phase.
  • Oggetti statici separati: muri e piattaforme non si muovono; si possono inserire in una struttura costruita una sola volta.

In sintesi

  • Confrontare tutte le coppie ha un costo che cresce con il quadrato del numero di oggetti.
  • La broad phase scarta rapidamente le coppie lontane, la narrow phase verifica quelle rimaste.
  • La griglia uniforme è semplice ed efficace se le celle hanno la dimensione giusta.
  • Quadtree e sweep and prune si adattano a distribuzioni particolari degli oggetti.
  • Gruppi di collisione e strutture statiche riducono ancora il lavoro.
MM
Marco Marzaduri

Marco Marzaduri si occupa di cybersecurity, informatica forense e sviluppo web. Laureato in informatica e in psicologia, unisce l'analisi tecnica alla comprensione del fattore umano.

Leggi anche