Come faccio a fare attacchi di bravi ragazzi colpendo solo cattivi e viceversa?


11

Il mio gioco ha molti tipi diversi di bravi ragazzi e molti tipi diversi di cattivi. Tutti spareranno proiettili l'uno contro l'altro, ma non voglio che si verifichino danni collaterali accidentali per nessuno dei due allineamenti. Quindi i cattivi non dovrebbero essere in grado di colpire / danneggiare altri cattivi e i bravi ragazzi non dovrebbero essere in grado di colpire / danneggiare altri bravi ragazzi.

Il modo in cui sto pensando di risolverlo è farlo in modo che l' Unitistanza (questo è JavaScript, BTW), abbia una alignmentproprietà che può essere goodo bad. E lascerò che la collisione avvenga solo se il

class Attack

    boolean didAttackCollideWithTarget(target)
        return attack.source.alignment != target.alignment and collisionDetected(attack.source, target)

Questo è pseudo-codice, ovviamente.

Ma sto ponendo questa domanda perché ho la sensazione che potrebbe esserci un modo molto più elegante di progettarlo oltre ad aggiungere un'altra proprietà alla mia Unitclasse.


5
Il filtro è l'approccio tipico qui. In sostanza è quello che hai descritto. Ci sono anche livelli. Due strati, strato cattivo e strato buono. I proiettili dei cattivi vengono lanciati nello strato buono e viceversa.
MichaelHouse

@ Byte56 Puoi approfondire questo concetto di "livello"? O almeno link a qualcosa al riguardo? Non ne ho mai sentito parlare prima.
Daniel Kaplan,

Essenzialmente sono diversi "mondi". Tutti gli oggetti in un livello interagiscono tra loro, ma non interagiscono con nessun altro livello. Questo può essere fatto con tag (come i filtri) o con set di dati totalmente diversi per ogni livello.
MichaelHouse

3
In una parola, sta raggruppando. Raggruppa i proiettili buoni e controlla solo la collisione contro i cattivi. Flixel ha un concetto come questo.
ashes999,

3
Una nota di design nitida: vuoi colpire colpi "fuoco amico" ma non fare danni, o vuoi che ignorino completamente gli alleati, magari passandoli attraverso per colpire i nemici?
Steven Stadnicki,

Risposte:


6

Filtro collisioni

Una situazione più solida che si ridimensiona in molti livelli è l'uso del filtro, che non è la stessa cosa del raggruppamento.

Funziona meglio dando ad ogni oggetto 2 maschere di bit .

Category
Mask

E innescare una collisione solo se il seguito è vero.

(filterA.maskBits & filterB.categoryBits) != 0 &&
(filterA.categoryBits & filterB.maskBits) != 0;

È più semplice impostare la Maschera su 0xFFFF che si scontra con tutto. E imposta la categoria predefinita su 0x0001. gli oggetti si scontrano con le categorie nella maschera degli altri ci sarà una collisione.

Un altro modo di pensarci è che ogni oggetto ha un tipo e un elenco di tutti i tipi con cui può scontrarsi. Solo quando due oggetti si scontrano con i tipi l'uno dell'altro c'è una collisione. Potresti avere lo stesso comportamento avendo un elenco di enumer invece di una maschera ma una maschera in un ordine di grandezza più veloce.

Scenario che descrivi

Mi piace approfittare degli enumerati in questa situazione.

Quindi dire che abbiamo.

enum Categories {
    GoodGuy =           0x0001,
    BadGuy =            0x0002,
    Bullet =            0x0004,
    GlassWall =         0x0008,
    Lazer =             0x0010,
    All =               0xFFFF
};

Proiettile sparato da un bravo ragazzo

 Category = Bullet
 Mask = BadGuy | GlassWall

Bravi ragazzi

 Category = GoodGuy
 Mask = All

Cattivi ragazzi

 Category = BadGuy
 Mask = All

Il risultato è il seguente quando un proiettile sparato da un bravo ragazzo colpisce un altro bravo ragazzo.

(All & GoodGuy) != 0 && <-- Passes
(GoodGuy & (BadGuy | GlassWall)) != 0; <-- This would fail

Ma colpirà i cattivi.

(All & BadGuy) != 0 && <- Passes
(BadGuy & (BadGuy | GlassWall)) != 0; <-- Passes

Ti dispiacerebbe spiegarlo concettualmente invece di spiegarlo con un dettaglio di basso livello dell'aritmetica dei bit?
Daniel Kaplan,

@tieTYT sicuramente ricontrollare tra 5 minuti
ClassicThunder

2

Ho avuto lo stesso problema nel mio progetto attuale (in Java). Dopo un paio di tentativi viene risolto creando quattro elenchi. Questa soluzione è creata in Java e per un gioco 2D ma dovrebbe funzionare anche in modo simile in JavaScript

public static main (String [] args)
{
    private List<Bullets> bullets_GoodGuys = new LinkedList <Bullet>(); //List of all bullets fired by good guys
    private List<Bullets> bullets_BadGuys  = new LinkedList <Bullet>(); //List of all bullets fired by bad guys
    private List<Guys> goodGuys  = new LinkedList <Guys>(); //List of all good guys
    private List<Guys> badGuys  = new LinkedList <Guys>();  //List of all good guys

    init();
    ...
    while(game_is_running)
    {
        ... 
        for(int i=0;i>=goodGuys.length;i++)
        {
            for(int j=0;j>=bullets_BadGuys.length;i++)
            {
                if(goodGuys.get(i).getBounding().interacts(bullets_BadGuys.get(i).getBounding()))
                {// If a good guy was hit by a bullet from a bad guy
                    goodGuys.get(i).getDamage();
                    bullets_BadGuys.remove((bullets_BadGuys.get(i));
         }   }   }
       for(...) //same for the bad guys
       {...}
}

pseudo-codice

class Guys
{
   private float xkoordinate;
   private float ykoordinate;
   private BufferedImage look;
   private Rectangle bounding = new Rectangle(xkoordinate,ykoordinate,look.getWith(),look.getHight())
   ...
}

pseudo-codice, lo stesso per la classe Bullets

Questa potrebbe non essere la soluzione migliore o più veloce, ma ti aiuterà in questo momento. Mi dispiace di non poterti offrire una soluzione in JavaScript ma spero di poterti aiutare

A proposito, il mio inglese non è il migliore, ma spero che tu possa seguire la mia spiegazione

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.