2009-12-03 10 views
18

Sono sempre stato interessato alle strutture dati coinvolte in un gioco di ruolo (gioco di ruolo). In particolare, sono curioso del dialogo e delle azioni basate sugli eventi.Motore di dialogo RPG/struttura

Ad esempio: se mi avvicino un NPC a punto x nel gioco, con gli elementi y e missioni z, come potrei capire cosa l'Anp ha bisogno di dire? Il dialogo di ramificazione e la risposta all'input del giocatore sembrano banali come avere uno script definito, e l'input dell'utente fa sì che il lettore di script salti su una particolare riga dello script, che ha un corrispondente set di linee di risposta (proprio come scegliere la propria avventura)

Tuttavia, legare in logica per capire se il giocatore ha determinati elementi e completare alcune missioni sembra rovinare davvero questo modello basato su script.

Sto cercando idee (non necessariamente esempi di linguaggio di programmazione) su come affrontare tutto questo dialogo e logica, e separarlo in modo che sia molto facile aggiungere nuovi contenuti di diramazione, senza scavare troppo nel codice.

Questa è davvero una domanda aperta. Non credo che esista un'unica soluzione, ma sarebbe bello far girare la palla con alcune idee. Essendo più un designer che un programmatore, sono sempre interessato a modi per separare contenuti e codice.

+0

Cool, ho appena modificato la domanda per essere una wiki della comunità –

risposta

5

Mi piacerebbe dire che i giochi più moderni (siano essi giochi di ruolo, giochi d'azione, qualsiasi cosa al di sopra di giochi di carte/giochi di base) in genere sono costituiti da diversi componenti: il motore di visualizzazione, le strutture dati principali e in genere uno script secondario motore. Un esempio che è stato popolare per un certo tempo (e potrebbe essere ancora, non ho nemmeno parlato con uno sviluppatore di giochi in anni) è stato Lua.

Il decisionale si sta parlando (eventi, rami di conversazione, ecc) è tipicamente gestiti dal motore di scripting secondario, come i linguaggi di scripting sono più flessibili e in genere più facile da usare per i progettisti del gioco. Ancora una volta, la maggior parte della vera logica guidata dalla trama o da gioco avverrà qui, dove può essere scambiata e cambiata relativamente facilmente. (Almeno, rispetto a eseguire una compilazione completa di tutto il codice!)

Il motore di gioco principale combina le strutture dati relative al mondo (geometria, ecc.), Le strutture dati relative al/i giocatore/i e altre attore (s) necessario, e gli script per guidare gli incontri, e utilizza tutto ciò per visualizzare l'ambiente finale integrato.

+0

Questa sembra la strada da percorrere, quindi un motore di scripting e un motore per gestire tutte le decisioni. Qualche idea su come questi potrebbero combaciare? –

+0

Non essendo un professionista in quel mondo, non ho molto altro da fare. Consiglierei di colpire gli scaffali - ci sono in realtà libri su design e sviluppo di CRPG disponibili; dovrebbero guidarti attraverso l'architettura principale. In bocca al lupo! –

4

È possibile utilizzare un linguaggio di scripting per gestire il dialogo. Fondamentalmente uno script potrebbe assomigliare a questo:

ShowMessage("Hello " + hero.name + ", how can I help you?") 
choices = { "Open the door for me", "Tell me about yourself", "Nevermind" } 
chosen = ShowChoices(choices) 
if chosen == 0 
    if hero.inventory["gold key"] > 0 
     ShowMessage("You have the key! I'll open the door for you!") 
     isGateOpen = true 
    else 
     ShowMessage("I'm sorry, but you need the gold key") 
    end if 
else if chosen == 1 
    if isGateOpen 
     ShowMessage("I'm the gate keeper, and the gate is open") 
    else 
     ShowMessage("I'm the gate keeper and you need gold key to pass") 
    end if 
else 
    ShowMessage("Okay, tell me if you need anything") 
end if 

Questo va bene per la maggior parte dei giochi. Il linguaggio di scripting può essere semplice e puoi scrivere rami logici più complicati. Il tuo motore avrà una rappresentazione del mondo che è esposta al linguaggio di scripting. In questo esempio, questo significa il nome dell'eroe e gli oggetti nell'inventario, ma potresti esporre qualsiasi cosa tu voglia. Definisci anche le funzioni che possono essere chiamate dagli script per fare cose come mostrare un messaggio o suonare qualche effetto sonoro. È necessario tenere traccia di alcuni dati globali condivisi tra gli script, ad esempio se una porta è aperta o una ricerca viene eseguita (forse come parte delle classi mappa e ricerca).

In alcuni giochi, tuttavia, lo scripting potrebbe diventare noioso, soprattutto se il dialogo è più dinamico e dipende da molte condizioni (ad esempio, stato d'animo del personaggio e statistiche, conoscenza di npc, meteo, articoli, ecc.) Qui è possibile archiviare il tuo albero di dialogo in un formato che consente di specificare facilmente precondizioni e risultati. Non so se questo è il modo per farlo, ma una volta ho chiesto un question about storing game logic in XML files.Ho trovato questo approccio efficace per il mio gioco (in cui il dialogo dipende fortemente da molti fattori). In particolare, in futuro potrei facilmente creare un semplice editor di dialoghi che non richiede molti script e consente di definire semplicemente dialoghi e diramazioni con un'interfaccia utente grafica.

+0

Questo è un commento fantastico e molto utile, insieme al link che hai postato. Ho pensato di farlo in XML e l'esempio che hai dato sembra abbastanza logico. Immagino che questo potrebbe anche essere fatto in json? Inoltre, ti dà una grande idea di avere una GUI per definire semplicemente il dialogo e le diramazioni –

17

Ad esempio: se mi avvicino un NPC a punto x del gioco, con gli elementi ye z missioni, come faccio a capire cosa l'Anp ha bisogno di dire? Ramificazione dialogo e rispondere alle lettore ingresso sembra banale come avente uno script definito , e l'input dell'utente provoca il lettore script per saltare ad una particolare linea nello script, che ha una corrispondente serie di risposta linee (molto come un scegliere il proprio avventura)

Tuttavia, legando nella logica di capire se il giocatore ha alcuni elementi, e completato alcune missioni sembra davvero rovinare questo script modello basato.

Niente affatto. È sufficiente considerare i condizionali nei dati.

Diciamo che hai la tua lista di dialoghi, numerati da 1 a 400 o simili come gli esempi del libro Scegli la tua avventura. Suppongo che ogni dialogo possa consistere nel testo pronunciato dal NPC, seguito da un elenco di risposte disponibili per il giocatore.

Quindi il prossimo passo è aggiungere i condizionali li ', semplicemente allegando le condizioni ad ogni risposta. Il modo più semplice è farlo con un linguaggio di scripting, in modo da avere un codice breve e semplice che restituisce True se questa risposta è disponibile per il giocatore e False se non lo è.

es. (Formato XML, ma potrebbe essere qualsiasi cosa)

<dialogue id='1'> 
    <text> 
    Couldst thou venture forth and kill me 10 rats, perchance? 
    </text> 
    <response condition="True" nextDialogue='2'> 
    Verily! Naught could be better than slaying thy verminous foes. Ten ratty 
    carcasses shall I bring unto thee. 
    </text> 
    <response condition="rats_left_in_world() < 10" nextDialogue='3'> 
    Nay, brother! Had thou but ten rats remaining, my sword would be thine, 
    but tis not to be. 
    </response> 
</dialogue> 

Nel vostro linguaggio di scripting, avresti bisogno di una funzione 'rats_left_in_world' che è possibile chiamare per recuperare il valore in questione.

Cosa succede se non si dispone di linguaggio di scripting? Bene, potresti avere il codice del programmatore una condizione individuale per ogni situazione nel tuo dialogo - un po 'noioso, non è poi così difficile se il tuo dialogo è scritto in anticipo. Quindi fai riferimento a una condizione per nome nello script di conversazione.

Uno schema più avanzato, ancora non richiedono un linguaggio di scripting, potrebbe utilizzare un tag per ogni condizione, in questo modo:

<response> 
    <condition type='min_level' value='50'/> 
    Sadly squire, my time is too valuable for the likes of thee. Get thyself a 
    farm hand or stable boy to do thy bidding! 
</response> 

È possibile aggiungere tutte le condizioni in là come è necessario, purché può essere facilmente specificato con uno o due valori. Se tutte le condizioni sono soddisfatte, la risposta è disponibile.

+6

Trova l'attributo XML non valido per i punti bonus - una buona ragione per cui XML dovrebbe essere fatto in un editor. – Kylotan

+2

Questa è una buona risposta. Non ho abbastanza XML foo per individuare l'attributo non valido. Quindi sembra che lo scripting sia in realtà piuttosto semplice, l'analisi invece ... dovrebbe essere analizzata in un programmatore decente? (vedi cosa ho fatto lì?) –

+0

Inoltre, mi stavo chiedendo come tenere traccia di quali diramazioni di dialogo il giocatore ha visitato o dovrebbe visitare in seguito? Per esempio. Quando torno a un NPC, come faccio a capire quale linea dire, a seconda che una missione sia stata distribuita, ecc. Forse una variabile per personaggio che memorizza il prossimo Dialogo avverrà alla prossima visita? –

6

E 'interessante, c'è sembra essere un'idea centrale viene persa qui. Stiamo discutendo di un programmatore che esegue l'operazione. In effetti, gli esempi di codice sopra sono accoppiati al codice, non al contenuto.

nello sviluppo del gioco, è la sviluppatori di contenuti che i programmatori vogliamo potenziare. Non lo faranno (questo è molto importante) guardate il codice. Periodo. Di tanto in tanto si ottiene un artista tecnico o un progettista tecnico, e sono meravigliosi e non importa; ma la maggior parte degli autori di contenuti non è tecnicamente incline.

Capisco che la domanda è per la tua edificazione; ma, va sottolineato che, nell'industria, quando risolviamo questi tipi di problemi i nostri utenti finali (le persone che utilizzano la tecnologia che stiamo sviluppando) non sono ingegneri.

Un sistema come questo (dialogo di diramazione) richiede una rappresentazione in uno strumento relativamente intuitivo da utilizzare. Ad esempio, il sistema di visual scripting di Unreal's Kismet potrebbe essere utilizzato.

In sostanza, le strutture dati (più che probabile un albero ramificato in quanto è facile da rappresentare/debug/ecc.) Sarebbero create da un programmatore, così come i nodi che rappresentano l'oggetto nello script. Il sistema con la sua capacità di collegarsi agli oggetti del mondo (più che probabile anche rappresentato dai nodi nello scripting visivo), ecc., Sarebbe quindi realizzato e l'intero cabinato del gattino collegato tra loro in un glorioso bit di codice elegante.

Dopo tutto ciò, un progettista sarebbe effettivamente in grado di costruire una rappresentazione visiva del dialogo che si ramifica nel linguaggio di scripting visivo. Questo sarebbe specifico per le mappe, più che probabile. Certo, potresti generarli proceduralmente; ma, è più un desiderio di programmatore che di un designer.

Ho solo pensato di aggiungere quel po 'di conoscenza e intuizione.

MODIFICA: notato c'è un esempio XML. Non sono sicuro di quali altri designer/artisti/ecc. sentirsi a riguardo; ma quelli con cui ho lavorato hanno rabbrividito all'idea di toccare un file di testo.

+1

Come risposta molto ritardata ... Sono d'accordo sul fatto che uno strumento visivo sia l'approccio ideale, ma in pratica è spesso impossibile dedicare le risorse a farne uno per tutto ciò che necessita di editing. Per questo motivo probabilmente non prenderei in considerazione l'idea di impiegare un designer che fosse spaventato dal testo strutturato. Il mio esempio XML non era tanto la prescrizione dell'esperienza utente per i progettisti, quanto piuttosto la dimostrazione che condizionali complessi possono essere incorporati nei dati abbastanza facilmente. – Kylotan

1

Recentemente ho affrontato un problema come questo mentre producevo Chat Mapper. Quello che faccio è tracciare graficamente i dialoghi come nodi in un albero e poi ogni nodo ha una condizione e uno script ad essi associato. Mentre si attraversa l'albero e si colpisce un nodo, si controlla la condizione per vedere se quel nodo è valido o meno, e se lo è, si esegue lo script associato a quel nodo. È un'idea abbastanza semplice, ma sembra funzionare bene dai nostri test. Stiamo utilizzando un interprete Lua .NET per gli script.

1

Per la mia soluzione ho sviluppato un formato di file di testo personalizzato composto da sette righe di testo per nodo. Ogni riga può essere una lista striata o solo una riga di testo. Ogni nodo ha un numero di posizione. L'ultima cifra del numero è un tipo, quindi ci sono 10 diversi tipi di nodi, come domande fresche, conferme, azioni ripetute basate su risultati precedenti, ecc.

Ogni attivazione di finestra di dialogo inizia con una query di selezione sui dati memorizzare i cui risultati possono essere confrontati con i membri di una lista striata, per abbinarli al nodo appropriato. Questo è più brutale di un if/then ma rende il file di configurazione del testo più piccolo poiché non c'è bisogno di alcuna sintassi oltre al separatore della falcata. Uso un sistema di caratteri jolly per consentire di selezionare i risultati della query per poter essere inseriti nel discorso dell'NPC.

Infine ci sono i ganci API per consentire l'interfacciamento di script personalizzati, nel caso in cui il semplice file di configurazione non sia sufficiente. Ho in programma di creare un'app per le app Web in nodejs per consentire agli utenti di visualizzare graficamente i file di configurazione: D

2

Recentemente ho dovuto sviluppare qualcosa per questo e ho optato per una struttura di file di testo molto semplice. Si può vedere il codice e formattare il testo risultante a:

https://github.com/scottbw/dialoguejs

Esiste un compromesso tra la raffinatezza di scripting e la facilità di montaggio per i non programmatori.

Ho optato per una soluzione molto semplice per il dialogo e gestire l'attivazione di eventi di gioco correlati separatamente in un linguaggio di scripting secondario.

Eventualmente potrei aggiungere un modo per aggiungere "indicazioni di palcoscenico" al formato di dialogo del testo che viene utilizzato per attivare eventi nel motore di scripting secondario, ma ancora senza dover inserire qualcosa che assomigli al codice nel file di dialogo stesso.

+0

Il tuo esempio di base mi fa riflettere sulle scelte dinamiche runtime. Dal tuo git: Ciao! Benvenuto in OSSland!È la prima visita? [1,2, ifSomeFlag> 3] 1 Sì, sono appena arrivato -> 4 2 No, sono stato qui prima -> 5 3 Get down to business -> 6 –

2

Questa è una domanda eccellente. Ho dovuto risolverlo un paio di volte per i clienti. Abbiamo iniziato con una struttura XML abbastanza simile alla tua e ora usiamo JSON. È possibile vedere un esempio qui: http://www.branchtrack.com/projects/on029pq6.json o https://dl.dropboxusercontent.com/u/11433463/branchtrack/on029pq6.json (migliorarlo per la leggibilità).

Divulgazione completa: il collegamento sopra riportato viene generato in BranchTrack, un editor online per i dialoghi di diramazione e io sono l'amministratore delegato. Sentiti libero di chiedere qualsiasi cosa.

+1

Appena provato - BranchTrack è cool. – mcintyre321

+0

Questo link ora restituisce l'accesso non autorizzato. È possibile ottenere uno screenshot di ciò che viene visualizzato per i posteri? – sanjaypoyzer

+1

@sanjaypoyzer Controlla questo collegamento: https://dl.dropboxusercontent.com/u/11433463/branchtrack/on029pq6.json –