Se due oggetti interagiscono, cosa contiene il codice di interazione?


28

Pensa a un proiettile e un nemico, o al giocatore e al pavimento. Se questi oggetti interagiscono, cosa contiene il codice di interazione?


2
Interagisci in che modo? Intendi il rilevamento delle collisioni? In tal caso, è molto probabile che implementiate sia una classe di rilevamento delle collisioni sia un gestore della risoluzione delle collisioni.
CaptainRedmuff,

In parte sì, sono interessato sia alla collisione sia a ciò che accade dopo la collisione. Il proiettile controlla se è vicino al nemico o viceversa? E cosa succede dopo la collisione, un oggetto proiettile può dire a un oggetto nemico che è stato colpito? Come puoi vedere sono abbastanza confuso sull'intera faccenda, e rende molto difficile leggere il codice.
ThatOneGuy

Risposte:


23

TL; DR:

I tuoi oggetti di gioco non si conoscono né eseguono controlli su altri oggetti. Si crea un modello di rilevamento e risoluzione delle collisioni che controlla gli oggetti di gioco ed esegue le azioni appropriate per simulare la fisica del gioco.

La roba buona

Dai precedenti tentativi di scrivere il rilevamento delle collisioni e leggere questo libro , ci sono due fasi per il rilevamento delle collisioni e la risoluzione delle collisioni. Il primo stadio (rilevamento delle collisioni) è un passaggio anticipato in cui si determina se due oggetti possono avere una potenziale collisione. Nel caso in cui due oggetti formino una potenziale collisione, passare quindi questi oggetti nella seconda fase (risoluzione della collisione) per eseguire un controllo più accurato sugli oggetti e tentare di risolvere la collisione.

Da qualche parte nel tuo motore / gioco, avrai una serie di tutti gli oggetti nel tuo mondo. Su ciascun fotogramma si esegue il loop dell'array e si controlla ogni oggetto contro ogni altro oggetto con un semplice riquadro di delimitazione / rilevamento delle collisioni della sfera.

pseudocodice:

dectectCollisions(objects)
{
    for(objectA in objects)
    {
        for(objectB in objects)
        {
            if(objectA != objectB) //ignore self
            {
                if(BoundingSpheresIntersect(objectA, objectB))
                {
                    collisionResolver.addObjects(objectA, objectB);
                }
            }
        }
    }
}

Questo tipo di loop è piuttosto inefficiente, ma lascia spazio a miglioramenti mediante l'uso del partizionamento spaziale come early-out per oggetti che sono garantiti essere troppo distanti per scontrarsi.

Dopo aver verificato i due oggetti per una potenziale collisione (ovvero entrambi gli oggetti sono abbastanza vicini da scontrarsi), gli oggetti vengono fatti passare per eseguire una routine di rilevamento delle collisioni più precisa.

Immagina di avere due poligoni di forme e dimensioni casuali che sono abbastanza vicine da potenzialmente intersecarsi ma non dovute alla loro geometria:

Immagine trovata tramite google

Usando sfere di delimitazione, questi due oggetti creerebbero un falso positivo per una potenziale collisione. Qui è dove eseguiresti un passaggio più accurato per determinare se i due oggetti si intersecano effettivamente.

Una volta trovata una vera collisione, la fase di risoluzione della collisione eseguirà quindi l'azione appropriata per risolvere gli oggetti applicando forze o momenti a seconda della granularità e delle esigenze della fisica del gioco.

Con questo in mente, puoi astrarre l'intero processo di rilevamento e risoluzione delle collisioni in modo che i tuoi oggetti non debbano conoscere nulla l'uno dell'altro, né il processo richiesto per determinare e risolvere le collisioni. Le due classi / gestori che gestiscono questo per te devono solo conoscere le proprietà di base di ciascun oggetto per eseguire un controllo rapido e sporco per le collisioni e quindi un controllo più approfondito nel caso fosse necessario.


2
In particolare, il modello di progettazione del mediatore sarebbe appropriato. Il modello Observer sarebbe una buona alternativa, che ha un intento molto diverso. Puoi ottenerne un buon riassunto in questo post di Stackoverflow .
Kurtzbot,

12

In un modo Unreal Engine 3 lo gestisce:

Il proiettile riceve un messaggio di collisione che dice che ha colpito qualcosa, con una discussione che gli dice che cosa ha colpito. Può quindi chiamare objectHit.takeDamage (self). Il bersaglio quindi riceve il messaggio TakeDamage, con un puntatore alla cosa che lo ha colpito, e intraprende l'azione appropriata.

Personalmente mi piace questo approccio perché significa che il proiettile può compiere azioni speciali (come fare una sorta di effetto di esplosione a seconda del tipo di cosa colpita) e il bersaglio può intraprendere azioni speciali a seconda del tipo di proiettile.

È anche possibile che il proiettile sappia cosa fa ai target e può chiamarci funzione, come objectHit.freeze (self). Quindi il bersaglio sa che è stato colpito da qualcosa che lo congela e che tipo di oggetto era.

EDIT: questa risposta è intesa come un quadro generale di come può funzionare, dal momento che probabilmente non stai lavorando con UE3. :)


10

Il ladro ha fatto molto bene nel Dark Engine con Sources and Receptrons. Un oggetto potrebbe avere entrambe queste proprietà, con tipi diversi. Ad esempio, una freccia d'acqua avrebbe una Sorgente per WaterStim al contatto. Un'esplosione avrebbe un AoE FireStim.

Quando una Freccia d'acqua colpisce un oggetto, l'oggetto bersaglio cerca quindi nei suoi Receptrons qualsiasi cosa cerchi un WaterStim con i valori di intensità appropriati. Quindi esegue qualsiasi comando ad esso associato (in questo caso, trasformando una torcia accesa in una torcia spenta ed emettendo un getto di fumo).

Dato che lo stesso motore viene utilizzato in SystemShock2, è così che vengono gestiti tutti i diversi tipi di danno, proiettili diversi hanno Stim diversi impostati e mostri diversi hanno Receptron per i diversi tipi di Stim e infliggono danni pari a 1 *, 2 *, 1 / 2 l'intensità a seconda che il tipo di munizioni sia "super efficace" o meno.

Sembrava un sistema molto flessibile in quanto si potevano aggiungere fonti e receptron agli oggetti nell'editor di livello, (per creare una porta unica che si apre se colpita dal fuoco, diciamo.) Mentre si potrebbe anche dire a un receptron di "inviare script messaggio "se all'oggetto erano associati script speciali.

Quello che non vuoi fare è codificare una matrice di interazione nXn di tutti gli oggetti possibili che si scontrano con tutti gli oggetti possibili! Generalizzando le interazioni attraverso messaggi standardizzati, si semplifica il processo.


Dal punto di vista dello scripting, questo approccio sembra il più flessibile e il più espressivo. Molto bello.
drhayes,

-2

Una soluzione è quella di mantenere i contenitori di proiettili e giocatori in classi separate, e quindi avere la funzione main () che mantiene il frame frame responsabile dell'interazione.

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.