Come posso implementare lo scripting intelligente nel mio gioco?


18

Sto sviluppando un motore di gioco. Dovrebbe essere basato su un'entità / componenti. Per lo sviluppo del mio gioco, ho pensato di usare un linguaggio di scripting per creare effettivamente le entità.

Ad esempio, se voglio aggiungere un tipo di mostro aggressivo per il giocatore, sarà un'entità con diversi componenti; questi componenti cambieranno con il tipo di mostro, quindi se avrò cento diversi tipi di mostri, nel mio gioco, non dovrò creare un nuovo metodo per ciascuno di essi direttamente nel mio codice di gioco.

Dovrei usare un linguaggio di scripting per descrivere questa entità, in termini di componenti o c'è qualcos'altro che funzionerebbe meglio? Più in generale, come dovrei usare gli script nel mio gioco?


Solo per la descrizione dell'entità, puoi usare solo xml o qualcosa di simile, senza bisogno di script. Per lo scripting
userei

@Kikaimaru C # Non è un linguaggio di scripting. Usare lua sarebbe un'idea migliore, o qualche altra lingua che può essere incorporata nel tuo motore.
JDSweetBeat,

@DJMethaneMan "C # non è un linguaggio di scripting" non significa nulla, non c'è assolutamente alcun problema con la scrittura di script in C # in un gioco scritto in C # e l'utilizzo di qualcosa come Roselyn per la compilazione ... Ma dopo 4 anni, userei json a javascript invece di xml e C # :)
Kikaimaru,

Risposte:


17

Il mio gioco utilizza un framework di componenti di entità e utilizza script per definire entità (questo non definisce direttamente il comportamento, ne parlerò di più alla fine). Gli script definiscono i componenti effettivi da utilizzare per la creazione di ciascuna entità. Utilizza un semplice linguaggio di scripting che ho creato. Ecco una versione semplificata di uno dei miei script:

ENTITY:"Goblin"
{
    description="It's currently their age."
    commonname="goblin"
    pluralCommonName="goblins"
    childname="gob'in"
    pluralChildName="gob'ins"
    active=Nocturnal
    tags=Mobile
    baseAttributes="OrganicMobileCreature"

    [Model]{
            meshname="Goblin"
            texturename="GoblinTexture"
    }

    [Motion]{
            maxvelocity=0.01:0.015
            locomotion=Walk,Swim
    }

    [Skills]{
            ALL=0.01:0.05,Mine=8.3:8.8,PlaceCube=8.3:8.8
    }

    [Inventory]{
            maxItems=2
            Allow=ALL
            Disallow=NONE
    }
}

Molto di questo è auto-descrittivo, ma qui ci sono alcuni punti salienti:

  • La prima sezione descrive le informazioni comuni per l'entità. Ciò include una descrizione e nomi visualizzati per vari aspetti dell'entità.
  • Il baseAttributestag fa riferimento a un altro file di script che definisce i componenti comuni che non voglio ridefinire più volte. Esso contiene componenti come position, liferequirementse così via. Se un componente viene definito di nuovo qui, questo componente sovrascriverà quello comune.
  • Ogni [NAME] { }set definisce un nuovo componente che verrà aggiunto a queste entità.
  • Questa descrizione non è solo per una singola entità , è per tutti i goblin creati. Vedrai che alcuni dei valori hanno intervalli (cioè 0.01:0.015), quando viene creato un nuovo goblin viene creato con un componente che ha un valore casuale in quell'intervallo. Quindi ogni goblin avrà abilità leggermente diverse e velocità leggermente diverse. Questa configurazione definisce che tutti i goblin inizieranno con abilità veramente buone nel posizionare cubi e miniere, il che è davvero solo per i miei scopi di test. Ma come sono sicuro che puoi indovinare, è molto facile cambiare i valori in qualsiasi cosa io voglia.

L'intera cosa comporta la creazione di un parser personalizzato, una sorta di struttura per contenere le definizioni delle entità (io chiamo il mio Lexicon!) E una fabbrica per prendere quelle definizioni di entità e generare nuove entità. Per me questo sistema è ancora nelle sue fasi iniziali, ma sta andando davvero molto bene. È un sistema abbastanza potente per la definizione rapida di entità e consente di creare qualsiasi entità desiderata utilizzando i componenti che hai creato. Se non ti senti a tuo agio nel creare il tuo parser, penso che XML funzionerà bene. Ho convertito il mio da un parser ricorsivo pushback che ho scritto per un linguaggio di programmazione un po 'inventato.

Come puoi vedere, questo definisce l'entità. Ho detto che non definisce direttamente il comportamento. Può, tuttavia, definire facilmente cose come odiati nemici e quanto aggressivamente reagire a detti nemici. Questo sarebbe semplice come definire qualsiasi componente che usi per controllare tale comportamento. Le mie entità hanno anche un componente di intelligence (non mostrato) che definisce cose come:

  • Come trovano il percorso (semplice movimento della linea di vista, semplice A *, predittivo A *, ecc.)
  • Quanto sono aggressivi / difensivi. Le entità possono avere zone di residenza che verranno difese, ma forse non aggressive al di fuori di tali zone.
  • Consapevolezza della tecnologia (porte aperte, uso di gadget, evitare trappole, ecc.)
  • E altro ...

Comunque sia definito il tuo, è il tuo sistema che guiderà i dati in quel componente, che a sua volta influenza il comportamento dei tuoi enti.


Grazie per la condivisione. In realtà penso che proverò a farlo usando il formato XML. Ci ho pensato molto (grazie a AbstractChaos a proposito) e dovrebbe soddisfare i miei bisogni (almeno per le descrizioni delle entità).
Nathan,

1
@nathan Sono d'accordo che dovresti andare con XML. Il motivo del mio post era più quali dati includere nel tuo XML e come usarli. Il formato dei dati può essere quello che ti piace. I dati che scegli di includere e il modo in cui implementi il ​​suo utilizzo sono molto più importanti.
MichaelHouse

@ Byte56 So che questo post è vecchio, ma come potresti gestire le relazioni figlio-genitore? Supponiamo che abbiamo un albero delle abilità e che hai bisogno di 10 punti nell'abilità A [0] per abilitare A [1] e 10 punti in quello per abilitare A [2], ecc. Devo nidificarli o appiattirli e premere un tasto ParentId? Ovviamente sono logicamente equivalenti, ma speravo che avessi qualche intuizione nel mondo reale.
Superstringcheese

@Superstringcheese if player.hasPoints(10) then i++ end skillTree[i]sarebbe uno pseudocodice. Non ho idea di come questa domanda sia rilevante per il post, tuttavia.
JDSweetBeat

4

Se tutto ciò di cui hai veramente bisogno è un modo per definire i componenti di un Monster, allora XML funzionerebbe bene sia in C # sia in java con una sua rapida implementazione.

Il tuo xml potrebbe essere

<?xml version="1.0" encoding="UTF-8"?>
<mobs>
  <mob>
    <personality>Aggressive</personality>
    <intelligence>20</intelligence>
  </mob>
</mobs>

Quindi la tua classe Mob potrebbe assomigliare. (Giava)

public class Mob {
  private IPersonality personality;
  private Integer intelligence

  //**  Getters & Setters **//
}

Dove IPersonality è un'interfaccia.

È quindi possibile caricare l'XML e analizzare ogni valore attraverso una factory.

ad esempio, analizzare il valore della personalità in PersonalityFactory che è semplicemente:

public IPersonality getPersonality(String personalityName) {
  if(personalityName.equals("Aggressive")) {
    return new AggressivePersonality();
  }
  else if(personalityName.equals("Passive")) {
    return new PassivePersonality();
  }
  else {
     //Maybe allow for no personality (We all know monster like that ;) )
     return null; 
  }
}

Quindi potresti creare un mob in questo modo

Mob mob = new Mob();
mob.setPersonality(getPersonality(xmlValue));
mobList.add(mob);

La chiave è che il tuo motore conosce il formato dell'xml e ha una fabbrica per tutto ciò di cui ha bisogno.

Un vantaggio di xml è che puoi definire il tuo schema per assicurarti che il formato sia sempre corretto, vedi qui .

Spero che sia di aiuto


In realtà ho bisogno di trovare un modo per creare facilmente nuove entità sul gioco durante il processo di sviluppo del gioco. XML è abbastanza flessibile? Dovrò comunque aggiungere degli script per la logica di gioco interna.
Nathan,

Se leggi la classe Mob come Entità, stai creando una nuova Enitity (Mob) utilizzando XML con componenti diversi (IPersonalità, Intelligenza [esempio di dati per quel mob]). E sfortunatamente non posso rispondere se sarà abbastanza flessibile in quanto non so che altro vorresti che facesse diverso da quello che hai specificato, tuttavia XML è un formato in cui gli unici limiti sono il modo in cui interpreti ogni sezione. Aggiorna la tua domanda con un esempio dettagliato e mostrerò un XML in grado di gestirlo. La logica di gioco interna suona come dovrebbe essere interna?
AbstractChaos

0

Python va bene penso. Spesso LUA è anche una buona alternativa se si desidera aggiungere funzionalità di scripting ai programmi.

Puoi utilizzare XML per descrivere il comportamento dei tuoi mostri, ciò comporterebbe un po 'di codice nel codice di gioco effettivo perché salverai solo il "nome" o alcuni attributi in base al comportamento (velocità, tipo di arma che il mostro usa, ecc.) del comportamento da utilizzare nel codice di gioco.

Se si utilizza uno Scriptengine (ad es. LUA), è possibile trasferire questo codice dal programma precompilato in file di script caricati durante il runtime. Per fare questo devi esporre l'API dei tuoi "mostri" allo scriptengine. Ciò ti consente di chiamare i metodi del codice di gioco dei mostri dall'esterno.


L'API del mio mostro? Voglio dire, dovrò essere in grado di creare nuovi componenti dalla sceneggiatura (installazione). È possibile?
Nathan,

Dopo questo dovrebbe essere possibile. È inoltre possibile utilizzare un approccio misto di archiviazione esterna (come menzionato da abstractchaos o byte56) e linguaggio di scripting (LUA, Python ...). Il vantaggio principale di es. LUA è che puoi cambiare il tuo codice in fase di esecuzione ed è immediatamente disponibile nel tuo gioco / motore in esecuzione
Aron_dc

Ho seriamente? È davvero un enorme vantaggio. Inoltre ho pensato a LUA (o altro linguaggio di scripting) per "cronologia dei giochi". Voglio dire, per creare alcune scene in cui il giocatore deve essere bloccato, questo sprite deve spostarsi qui, illuminarsi qua e là ... Quindi forse potrei anche usare un linguaggio di script per caricare le entità? Inoltre pubblicherò un'altra domanda per esporre il mio modo attuale di gestire entità / componenti rispetto a ciò che chiamo "manager" per vedere se sto andando bene.
Nathan,
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.