Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 32 di 53
  • livello principiante
Indice lezioni

Collision Detection

Come gestire le collisioni tra gli oggetti (sprite) sullo schermo
Come gestire le collisioni tra gli oggetti (sprite) sullo schermo
Link copiato negli appunti

Uno degli aspetti più delicati nello sviluppo di un gioco è l'implementazione di un sistema di collision detection: un algoritmo in grado di calcolare quando due oggetti (siano essi sprite 2D o modelli 3D) entrano in collisione sullo schermo.

Esistono molti algoritmi in grado di svolgere questo compito, ciascuno dei quali si presenta con un diverso grado di precisione e di efficienza in termini di risorse hardware consumate. Come regola generale, si può dire più un algoritmo è preciso nell'individuare punti di contatto tra due oggetti, maggiore è il carico di lavoro per la CPU. Al contrario, algoritmi "approssimativi" possono migliorare di molto la performance del nostro gioco.

Per ovviare ai difetti dell'uno e dell'altro sistema, si preferiscono in genere soluzioni "ibride", in cui vengono impiegati due (o più) algoritmi diversi:

  • ad un primo algoritmo, più "grezzo", viene affidato il compito di "filtrare" in tempi estremamente rapidi tutti quei casi in cui, già a "colpo d'occhio", si può ragionevolmente escludere qualunque contatto tra due oggetti (ad esempio perché questi occupano posizioni completamente diverse nello spazio);
  • un secondo algoritmo, più raffinato rispetto al primo, verrà utilizzato per quelle situazioni che, sopravvissute al vaglio da parte del primo "filtro", richiedono un'analisi pixel per pixel delle possibili aree di contatto.

In questo gioco utilizzeremo una tecnica simile, seppure in una versione semplificata.

Per prima cosa, verificheremo se le due texture presentano punti di sovrapposizione. Per far questo creermo un rettangolo che rappresenti, se esistente, l'area di sovrapposizione delle due texture.

Una volta accertato che le due texture hanno effettivamente punti di sovrapposizione, non possiamo ancora dare per certa l'esistenza di una collisione tra gli sprite, dal momento che è possibile che le aree di sovrapposizione siano "vuote" (caso A) (vedi figura seguente).

Figura 2. Collisione fra texture
Collisione fra texture

Per calcolare se le aree colorate dei due sprite presentino delle sovrapposizioni, useremo un wrapper (denominato ColliderTexture, nell'esempio) contenente una Texture2D e i dati relativi al colore di ciascuno dei suoi pixel, dati che verranno memorizzati in un array di tipo Color, le cui dimensioni saranno pari al numero totale di pixel che compongono la texture (= altezza × larghezza):

public class ColliderTexture
{
  public Texture2D Texture { get; private set; }
  protected Color[] texture_data;
  public ColliderTexture(Texture2D texture)
  {
    Texture = texture;
    texture_data = new Color[texture.Width * texture.Height];
    texture.GetData(texture_data);
  }

Per "attravasare" le informazioni relative al colore dei singoli pixel della texture nel corrispondente array utilizziamo il metodo GetData<Color> esposto dalla classe Texture2D.

Le informazioni relative al colore di ciascun pixel comprendono i valori relativi alle tre proprietà RGB, più il valore del canale Alpha (relativo alla trasparenza). Queste informazioni verranno appunto riversate, pixel per pixel, nell'array texture_data, i cui elementi assumeranno valori simili a quelli riportati qui di seguito a scopo meramente illustrativo:

texture_data[1] = {R:255 G:124 B:23 A:255}
texture_data[2] = {R:250 G:123 B:50 A:255}
texture_data[3] = {R:244 G:118 B:24 A:255}
[…]

Poiché la texture originale è un rettangolo, texture_data conterrà i pixel della texture memorizzati una riga dopo l'altra. Quindi tutti i pixel della prima riga sarano memorizzati in ordine per primi, seguiti da tutti i pixel della seconda riga, etc.

Adesso che la nostra classe wrapper è pronta, possiamo utilizzarla nel nostro gioco per caricare le texture dei due oggetti (i cui asset name sono, rispettivamente, "asteroid1" e "ship"). Nel metodo Initialize aggiungiamo le seguenti righe:

player = new ColliderTexture(Content.Load(@"ship"));
asteroid = new ColliderTexture(Content.Load(@"asteroid1"));

Ti consigliamo anche