Crea un sistema basato su comportamento / componente per i giochi

11

Sfondo

Realizzo giochi come hobby e sto cercando un modo migliore per progettarli. Attualmente sto usando un approccio OOP standard (ho fatto lo sviluppo delle imprese per 8 anni, quindi è giunto alla normalità). Prendi ad esempio un "cattivo"

public class Baddie:AnimatedSprite //(or StaticSprite if needed, which inherit Sprite)
{
    //sprite base will have things like what texture to use, 
    //what the current position is, the base Update/Draw/GetInput methods, etc..
    //an AnimatedSprite contains helpers to animated the player while 
    //a StaticSprite is just one that will draw whatever texture is there
}

Il problema

Diciamo che sto facendo un platform 2d, e ho bisogno che il cattivo sia in grado di saltare. Di solito quello che faccio è aggiungere il codice appropriato nei metodi Update / GetInput. Quindi se ho bisogno di far strisciare, anatra, arrampicarsi, ecc ... il codice andrà lì.

Se non sto attento, questi metodi si disordinano, quindi finisco per creare coppie di metodi come questa

CheckForJumpAction(Input input) e DoJump()

CheckforDuckAction(Input input) e DoDuck()

quindi GetInput ha un aspetto simile a

public void DoInput(Input input)
{
    CheckForJumpAction(input);
    CheckForDuckAction(input);
}

e l'aggiornamento ha l'aspetto di

public void Update()
{
    DoJump();
    DoDuck();
}

Se vado a creare un altro gioco in cui il giocatore deve saltare e saltare, di solito vado in un gioco che ha la funzionalità e lo copia. Disordinato, lo so. Ecco perché sto cercando qualcosa di meglio.

Soluzione?

Mi piace molto il modo in cui Blend ha comportamenti che posso associare a un elemento. Ho pensato di usare lo stesso concetto nei miei giochi. Quindi vediamo gli stessi esempi.

Creerei un oggetto Behavior di base

public class Behavior
{
    public void Update()
    Public void GetInput()
}

E posso creare comportamenti usando questo. JumpBehavior:Behavior e DuckBehavior:Behavior

Posso quindi aggiungere una serie di comportamenti alla base di Sprite e aggiungere ciò di cui ho bisogno a ciascuna entità.

public class Baddie:AnimatedSprite
{
    public Baddie()
    {
        this.behaviors = new Behavior[2];
        this.behaviors[0] = new JumpBehavior();
        //etc...
    }

    public void Update()
    {
        //behaviors.update
    }

    public GetInput()
    {
        //behaviors.getinput
    }
}

Quindi ora Se volevo usare Jump and Duck in molti giochi, posso semplicemente portare i comportamenti sopra. Potrei persino creare una libreria per i più comuni.

Funziona?

Quello che non riesco a capire è come condividere lo stato tra di loro. Guardando Jump and Duck, entrambi influenzano non solo la porzione corrente della trama che viene disegnata, ma anche lo stato del giocatore. (Salto sta per applicare una quantità decrescente di forza verso l'alto nel tempo, mentre l'anatra sta per fermare il movimento, cambiare la trama e la dimensione di collisione del cattivo.

Come posso legare questo insieme in modo che funzioni? Devo creare proprietà di dipendenza tra i comportamenti? Dovrei avere ogni comportamento sapere sul genitore e modificarlo direttamente? Una cosa che pensavo fosse riuscire a passare un delegato in ogni comportamento per essere eseguito quando viene attivato.

Sono sicuro che ci sono altri problemi che sto osservando, ma l'unico scopo è che io possa riutilizzare facilmente questi comportamenti tra i giochi e le entità nello stesso gioco.

Quindi consegnalo a te. Cura di spiegare come / se questo può essere fatto? Hai un'idea migliore? Sono tutto orecchie.

    
posta Joe 04.07.2011 - 05:57
fonte

4 risposte

2

Dai un'occhiata alla questa presentazione. Sembra abbastanza vicino al tipo di modello che stai cercando. Questo modello supporta comportamenti e proprietà attaccabili. Non penso che la presentazione lo menzioni, ma puoi anche creare eventi collegabili. Questa idea è simile alle proprietà di dipendenza utilizzate in WPF.

    
risposta data 20.12.2011 - 03:40
fonte
9

Per me questo sembra quasi un caso da manuale per l'uso del Pattern di strategia . In questo schema, i tuoi comportamenti generici possono essere definiti in interfacce che ti permetteranno di scambiare diverse implementazioni di comportamenti in fase di esecuzione (pensa a come un power-up può influenzare l'abilità di salto o di corsa del tuo personaggio).

Per esempio (forzato):

// The basic definition of the jump behavior
public interface IJumpBehavior {
    void Jump();
}

Ora puoi implementare vari tipi di salti che il tuo personaggio può usare, senza necessariamente conoscere i dettagli di ogni salto specifico:

// This is the jump the character may have when first starting
public class NormalJump : IJumpBehavior {

     public void Jump() {
         Console.WriteLine("I am jumping, and being pretty boring about it!");
     }

}

// This is the jump of a character who has consumed a power-up
public class SuperJump : IJumpBehavior {
    public void Jump() { 
         Console.WriteLine("I am all hopped up on star power, now my jumps can do damage!");
     }
}

Ogni personaggio che vuoi avere la possibilità di saltare ora può contenere solo un riferimento a un IJumpable e può iniziare a consumare le varie implementazioni

public class HeroCharacter {

    // By default this hero can perform normal jump.
    private IJumpBehavior _jumpBehavior = new NormalJump();

    public void Jump() {
        _jumpBehvaior.Jump();
    }

    // If you want to change the hero's IJumpable at runtime
    public void SetJump(IJumpBehavior jumpBehavior) {
      _jumpBehavior = jumpBehavior;
    }

}

Quindi il tuo codice può avere un aspetto simile a:

HeroCharacter myHero = new HeroCharacer();

// Outputs: "I am jumping, and being pretty boring about it!"
myHero.Jump()

// After consuming a power-up
myHero.SetJump(new SuperJump());

// Outputs: "I am all hopped up on star power, now my jumps can do damage!"
myHero.Jump();

Ora puoi facilmente riutilizzare questi comportamenti, o addirittura estenderli in seguito, se vuoi aggiungere altri tipi di salti, o creare più giochi creati su una singola piattaforma a scorrimento laterale.

    
risposta data 12.07.2011 - 22:24
fonte
1

Dai un'occhiata a architettura DCI un'interessante presa sulla programmazione OO che potrebbe aiutarti.

L'implementazione di un'architettura in stile DCI in C # richiede l'utilizzo di classi di dominio semplici e l'utilizzo di oggetti Context (comportamenti) con i metodi di estensione e le interfacce per consentire alle classi dominio di collaborare in ruoli diversi. Le interfacce vengono utilizzate per evidenziare i ruoli richiesti per uno scenario. Le classi di dominio implementano le interfacce (ruoli) che si applicano al loro comportamento previsto. La collaborazione tra i ruoli avviene negli oggetti di contesto (comportamento).

Potresti creare una libreria di comportamenti e ruoli comuni che possono essere condivisi tra oggetti di dominio da progetti separati.

Vedi DCI in C # per esempi di codice in C #.

    
risposta data 06.07.2011 - 11:54
fonte
0

Che ne è di passare un oggetto contesto in un comportamento che fornisce metodi per modificare lo stato degli sprite / oggetti interessati da un comportamento? Ora se un oggetto ha diversi comportamenti, vengono chiamati ciascuno in un ciclo che dà loro la possibilità di cambiare il contesto. Se una determinata modifica di una proprietà esclude / limita la modifica di altre proprietà, l'oggetto contesto può fornire metodi per impostare qualche tipo di flag per indicare questo fatto, oppure può semplicemente negare modifiche indesiderate.

    
risposta data 04.07.2011 - 19:51
fonte

Leggi altre domande sui tag