Creare un sistema basato sul comportamento / componente per i giochi


11

sfondo

Faccio lo sviluppo del gioco come un 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 arriva nartualmente). 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 realizzando un platform 2d e ho bisogno del cattivo per poter saltare. Di solito quello che faccio è aggiungere il codice appropriato nei metodi Update / GetInput. Quindi, se ho bisogno di far strisciare il giocatore, anatra, arrampicarsi, ecc ... il codice andrà lì.

Se non sto attento, quei metodi vengono ingombra, quindi finisco per creare coppie di metodi come questa

CheckForJumpAction(Input input) e DoJump()

CheckforDuckAction(Input input) e DoDuck()

così appare GetInput

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

e l'aggiornamento sembra

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

Se vado a creare un altro gioco in cui il giocatore deve saltare e abbassarsi, di solito vado in un gioco che ha la funzionalità e lo copio. 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 diamo un'occhiata agli stessi esempi.

Vorrei creare un oggetto Comportamento di base

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

E posso creare comportamenti usando quello. JumpBehavior:BehavioreDuckBehavior:Behavior

Posso quindi aggiungere una raccolta di comportamenti alla base 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 volessi usare Jump and Duck in molti giochi, posso semplicemente riportare i comportamenti. Potrei persino creare una biblioteca per quelli comuni.

Funziona?

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

Come posso legarlo insieme in modo che funzioni? Devo creare proprietà di dipendenza tra i comportamenti? Devo avere ogni comportamento a conoscenza del genitore e modificarlo direttamente? Una cosa che pensavo fosse la possibilità di passare un delegato in ciascun comportamento per essere eseguito quando è attivato.

Sono sicuro che ci sono più problemi che sto esaminando, ma l'intero scopo è quello di poter riutilizzare facilmente questi comportamenti tra i giochi e le entità nello stesso gioco.

Quindi te lo giro. Vuoi spiegare come / se ciò può essere fatto? Hai un'idea migliore? Sono tutto orecchie.


Questo potrebbe essere meglio chiesto a gamedev.stackexchange.com ?
rcapote

Mi piace dove stai andando ma non sono sicuro di come affrontare i problemi che sollevi. Molto interessante e ha implicazioni oltre lo sviluppo del gioco.
Edward Strange,

@rcapote non è questo sito per la lavagna / discussioni?

2
@Joe - no, no. Non menzionare nemmeno "discussione" qui o verrai modificato dall'esistenza. Questo sito è solo per domande-> risposte-> Fatto tipo di interazione.
Edward Strange,

Bene, i sistemi di entità basati su componenti sono qualcosa che ha iniziato a fare tendenza nella comunità degli sviluppatori di giochi di recente, quindi ho pensato che potresti ottenere una migliore attenzione lì, ma probabilmente otterrai comunque delle buone risposte qui. Ecco un'interessante discussione su gamedev.net su questo problema che potresti trovare interessante: gamedev.net/topic/…
rcapote

Risposte:


1

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


9

Per me questo sembra un caso quasi da manuale per l'utilizzo del modello strategico . In questo modello, 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 potenziamento può influenzare l'abilità di saltare o correre del tuo personaggio).

Per un esempio (inventivo):

// 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!");
     }
}

Tutti i personaggi che vuoi avere la possibilità di saltare possono ora contenere un riferimento a un IJumpable e possono iniziare a consumare le tue 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ò assomigliare 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 anche estenderli in un secondo momento poiché desideri aggiungere più tipi di salti o creare più giochi creati su un'unica piattaforma a scorrimento laterale.


mentre non è esattamente quello che sto cercando, questo è molto vicino e piace. Ci giocherò per esserne sicuro. Grazie!

1

Dai un'occhiata all'architettura DCI una visione interessante della programmazione OO che può aiutare.

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

È possibile 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 #.


0

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

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.