Utenti.BabaogluEngine History
Hide minor edits - Show changes to markup
Il motore del gioco è scritto in Java, ma il gioco stesso no. Utilizza un linguaggio di script chiamato FScript, che è molto semplice da imparare. Le azioni e le interazioni tra gli oggetti, le locazioni della mappa ed il personaggio avvengono tramite gli script scritti in FScript. Il bello di un sistema del genere è che il motore rimane identico, ma si può cambiare la realtà del gioco intervenendo su questi script, senza bisogno di ricompilare alcunché. Inoltre, la semplicità del linguaggio di script permette la creazione di avventure anche a chi non è programmatore. Un altro vantaggio è che si può separare il gioco dalla sua interfaccia: per ora c'è una semplice GUI, ma non ci vuole molto a scrivere qualcosa di diverso e più apapriscente. La grafica non è prevista (niente giochi tipo Monkey Island, per intenderci).
Il motore del gioco è scritto in Java, ma il gioco stesso no. Utilizza un linguaggio di script chiamato FScript, che è molto semplice da imparare. Le azioni e le interazioni tra gli oggetti, le locazioni della mappa ed il personaggio avvengono tramite gli script scritti in FScript. Il bello di un sistema del genere è che il motore rimane identico, ma si può cambiare la realtà del gioco intervenendo su questi script, senza bisogno di ricompilare alcunché. Inoltre, la semplicità del linguaggio di script permette la creazione di avventure anche a chi non è programmatore. Un altro vantaggio è che si può separare il gioco dalla sua interfaccia: per ora c'è una semplice GUI, ma non ci vuole molto a scrivere qualcosa di diverso e più appariscente. La grafica non è prevista (niente giochi tipo Monkey Island, per intenderci).
Come è strutturata un'avventura
Un'avventura è composta da un'insieme di locazioni, oggetti, pietre miliari e NPC, più un giocatore che gira tra di essi. L'interazione tra le varie componenti del gioco è affidata principalmente agli script scritti in FScript'.
Fisicamente le avventure risiedono in diversi files, i quali servono a descrivere le varie componenti dell'avventura.
I files .baba servono per le gli oggetti, gli NPC e le pietre miliari.
I files .loc servono per le locazioni.
I files .script contengono gli script.
I files .blabla contengono i discorsi.
Il file .ini contiene le informazioni necessarie all'avvio del gioco.
Tutti questi files vanno messi in una cartella, e l'indirizzo di quella cartella va passato come parametro al costruttore della classe Gioco. Nella mia implementazione del Babaoglu Engine, si passa l'indirizzo della cartella da linea di comando, e questo verrà successivamente passato al costruttore di Gioco.
Il file .ini
[inizio] nomeGiocatore = Dario descrizioneGiocatore = Studente locazioneIniziale = biblio001 titoloFinestra = Gioco di prova per il Babaoglu Engine
Un file .ini deve avere la struttura qui riportata, obbligatoriamente. Tutto il resto viene ignorato.
Il formato dei files .ini viene usato anche per i .baba e i .loc, con un diverso utilizzo dei campi.
I discorsi
... TODO ...
Le locazioni vengono salvate in files con l'estensione .loc, il cui formato è il seguente:
[id_della_locazione] nome = nome della locazione descrizione = descrizione della locazione #uscita dir = id_destinazione aperta visibile uscita nord = id_destinazione true true uscita sud = id_destinazione false false
Le righe che iniziano con # sono considerate commenti.
Per essere valida, una locazione in un file .loc deve avere i campi nome e descrizione.
Un oggetto ha un nome e una descrizione. Il giocatore ha un inventario, che contiene un numero infinito di oggetti (ma sì! chi se ne frega:), e può avere più di una copia di uno stesso oggetto. Oggetti come le chiavi possono essere usate per aprire porte. In generale, il giocatore può usare un oggetto da solo (per esempio, usare una cornamusa per suonare un po') oppure usare un oggetto con un altro oggetto (per esempio, usare una chiave con una porta).
Un oggetto ha un nome e una descrizione. Il giocatore ha un inventario, che contiene un numero infinito di oggetti, e può avere più di una copia di uno stesso oggetto. Oggetti come le chiavi possono essere usate per aprire porte. In generale, il giocatore può usare un oggetto da solo (per esempio, usare una cornamusa per suonare un po') oppure usare un oggetto con un altro oggetto (per esempio, usare una chiave con una porta).
Gli oggetti sono salvati in files con l'estensione .baba. Il formato è simile a quello delle locazioni:
[nome oggetto] tipo = oggetto descrizione = descrizione dell'oggetto
Per essere valido, occorre indicare il campo tipo = oggetto e la descrizione. La riga tipo = oggetto serve per distinguere gli oggetti dagli NPC e dalle Pietre Miliari. Gli altri campi sono ignorati.
Anche le Pietre Miliari sono salvate in files .baba.
[nome pietra miliare] tipo = pietra descrizione = descrizione della pietra miliare
La riga tipo = pietra ed il campo descrizione sono obbligatori. Altri campi saranno ignorati.
Dati tecnici
In questa sezione sono raccolte le note relative all'implementazione del gioco e degli script.
Locazioni
La Locazione è un oggetto con i seguenti campi:
- String nome
- String id
- String descrizione
- ArrayList<Uscita> uscite
- ArrayList<Oggetto> oggetti
Lo script di default associato ad una locazione è una funzione FScript dal nome composto così: <id>_func(). Per esempio, se la locazione Biblioteca ha id biblio, la sua funzione di default sarà chiamata biblio_func. Il motore cercherà questa funzione: se esiste, sarà eseguita.
Uscita:
- String direzione (nord, sud, etc...)
- Boolean visibile
- Boolean aperta
Quando si tenta di aprire una porta con un oggetto, occorre specificarlo nel comando apri. Un'uscita ha una funzione di default associata, di nome <idloc>_<direzione>_func => biblio_nord_func(String cheCosa).
Oggetti
- String nome
- String descrizione
- Boolean mobile
Un oggetto ha una funzione di default associata, di nome <nome_oggetto>_func(String cheCosa). Se l'argomento cheCosa è "niente", si attiva l'azione associata all'oggetto, per esempio suonarlo se è uno strumento musicale. Altrimenti, cheCosa può essere il nome di un altro oggetto presente nell inventario oppure un'uscita della locazione attuale. In questi casi, avverranno le azioni stabilite dallo script.
Solo gli oggetti contrassegnati con mobile possono essere messi in inventario.
Da notare che nella riga di comando il primo argomento è l'oggetto attivo, mentre il secondo è l'oggetto passivo. Ciò vuol dire che una riga di comando come usa accendino carta
chiamerà la funzione carta_funz("accendino") e lo script di carta reagirà di conseguenza.
Pietra Miliare
- String nome
- String evento
Una pietra miliare è del tutto simile ad un Oggetto, ed è possibile associarvi una String contenente il testo che verrà comunicato al giocatore in occasione del conseguimento di tale Pietra Miliare.
Anche alle pietre miliari è associata una funzione di default, chiamata <nomepietra>_func. Quando una pietra miliare viene data al player, viene chiamata la funzione <nomepietra>_func con parametro "dai"; quando viene tolta il parametro è "togli".
NPC
- String nome
- String descrizione
- String idLocAttuale
idLocAttuale è la posizione in cui si trova in un preciso istante. La funzione di default di un PNG si chiama <nome>_func(string azione, string argomento). L'azione è "niente" se si vuole attivare la sequenza normale, oppure può essere "parla" per interagire con il personaggio. L'argomento può essere richiesto, ad esempio, per parlare con l'NPC di uno specifico argomento.
Giocatore
- String nome
- inventario => ArrayList di Oggetti
- pietreMiliari => arrayList di Pietre Miliari
Anche gli NPC sono salvati nei files .baba.
[nome NPC] tipo = NPC descrizione = descrizione dell'NPC proprietà 1 = valore proprietà 2 = valore
La riga tipo = NPC e il campo descrizione sono obbligatori. Gli altri campi sono facoltativi, e possono servire per gestire alcuni aspetti di un'avventura, in quanto sono accessibili via script.
Vai
vai
Apri
apri <dove> [<oggetto>]
<dove> deve essere un'uscita valida. Se presente l'argomento <oggetto>, si chiamerà lo script dell'uscita con <oggetto> come argomento, e l'oggetto deve essere presente nell'inventario.
Prendi
apri
apri <dove>
<dove> deve essere un'uscita valida.
chiudi
chiudi <dove>
prendi
<oggetto> deve essere un oggetto presente nella lista di oggetti della locazione attuale.
Lascia
<oggetto> deve essere un oggetto presente nella locazione attuale.
lascia
<oggetto> deve essere un oggetto presente nell'inventario. Se ci sono più copie dell'oggetto, ne viene lasciata 1. L'oggetto lasciato si aggiunge alla lista degli oggetti della locazione corrente.
Inventario
<oggetto> deve essere un oggetto presente nell'inventario. Se ci sono più copie dell'oggetto, ne viene lasciata 1. L'oggetto lasciato rimane nella locazione corrente.
inventario
Uscite
uscite
Guarda
guarda
Usa
usa
Funzioni usabili negli script
Gli script
Gli script sono scritti in FScript, che è un linguaggio piuttosto semplice (forse fin troppo, ma va beh). Si possono associare script a oggetti, locazioni ed uscite di locazione.
Sono letti dai files con estensione .script.
Script associati ad oggetti
func nomeoggetto_func(String azione, String param) ... ... end func
L'azione è l'azione che si vuol compiere con l'oggetto. È possibile anche passare un parametro, che rappresenta l'oggetto passivo nell'azione. Ecco un esempio:
func coltello_func(string param, string obj) if (param == "usa") if (obj=="") scrivi("Usi il coltello con che cosa? Vuoi farti male?") elsif (obj=="salame") if (inInventario("salame") == 0) scrivi("Mangi il salame... mmm delizioso:)") togliOggetto("salame") endif endif endif endfunc
Script associati a locazione
func idlocazione_func(String param) ... ... endfunc
Vengono eseguiti ogni volta che il giocatore capita in una locazione.
Script associati ad uscite
func idlocazione_nomeuscita_func(String param) ... ... endfunc
Vengono chiamati quando si esegue un comando apri o chiudi su di un'uscita. Ecco un esempio:
func biblio001_giu_func(string param) if (inInventario("chiave") == 0) if (param == "apri") apri("biblio001", "giu") scrivi("La botola si apre lentamente...") elsif (param == "chiudi") chiudi("biblio001" , "giu") endif else scrivi("Non hai la chiave...") endif endfunc
Funzioni utilizzabili negli script
Ci sono un po' di chiamate di funzione disponibili all'interno degli script. Servono per recuperare ed impostare i parametri del gioco.
- int aperta(int uscita) = 1 sì, 0 no. NOTA: uscita qui corrisponde al numero di sequenza dell'uscita così come restituito dalla funzione quanteUscite(String idloc)
- String dammiIdLoc(int uscita) = restituisce la stringa contenente l'id della locazione indicata, che corrisponde al numero di sequenza delle uscite restituito da quanteUscite
- int aperta(String locazione, String uscita) = 1 sì, 0 no.
- String dammiIdLoc(String locazione, String uscita) = restituisce la stringa contenente l'id dell'uscita della locazione indicata
- int domanda(String testo, String domande) = pone la domande contenuta nella String testo all' NPC o al player, e restituisce quale di queste ha scelto. Le domande sono separate da una | (pipe), eg: "Come ti chiami?|Sei gay?|Ma tu sei il famoso Cthulhu?"
- scriviDiscorso(String idDiscorso) = scrive il discorso segnato con id
Formato dei files
Il gioco è salvato in una cartella, la quale viene passata come argomento al motore del gioco all'avvio. La cartella può contenere un qualsiasi numero di files.
Si assume che i files con estensione .baba
contengano la descrizione di locazioni e oggetti, i files .script
devono contenere gli script, le locazioni siano contenute nei files .loc
.
In questi files, le informazioni vengono codificate secondo un certo schema che presento qui sotto.
Divisione in blocchi
Un blocco è composto da un certo numero di righe contenenti definizioni, separate da righe contenenti 4 trattini. Le definizioni sono del tipo:
<nome>=<definizione>
La prima riga del blocco deve contenere il tipo del blocco stesso. Le righe che iniziano per # sono considerate commenti.
Locazioni
tipo=locazione nome=Biblioteca id=biblio01 descrizione=È una sala ampia, dal pavimento di linoleum blu. Le finestre sono grandi, rivolte verso sud. Ci sono diversi tavoli bianchi, e il silenzio regna sovrano #direzione idloc visibilità aperta uscita=nord biblio02 true true uscita=sud corridoio01 true true uscita=est cortile01 true false
Oggetti
tipo=oggetto nome=martello descrizione=Un martello da muratore, col manico lungo e sporco di cemento.
PNG
tipo=png nome=Danio descrizione=Un uomo di mezza età, un po' calvo, dal viso tranquillo. idloc=biblio01
Gli script
Gli script, come spiegato sopra, sono contenuti in funzioni con un nome standard, così da poter essere facilmente rintracciabili.
func biblio01_func(string param) ... ... endfunc func martello_func(string param, string obj) ... ... endfunc func biblio01_nord_func(string param) ... ... endfunc func danio_func(string param, string argomento) ... ... endfunc
Avvio del gioco
In ogni avventura realizzata per il Babaoglu Engine, occorre che sia definita la pietra miliare di nome inizio, e che la sua relativa func presenti almeno queste funzionalità:
func inizio_func(string param) if (param=="getNomePlayer") return "Studente" elsif (param=="getDescrPlayer") return "Un bel bambino" elsif (param=="getLocIniziale") return "biblio001" else scrivi("Benvenuto nella demo del Babaoglu Engine!") endif endfunc
Infatti, inizio_func viene chiamata per inizializzare il gioco.
- String leggiProprieta(String NPC, String nomeProprieta) = ritorna il valore della Proprietà di quell'NPC
- int haProprieta(String NPC, String nomeProprieta) : 1 = si, 0 = no
Esempio: guarda Ceravolo, guarda salame.
Inoltre, se un personaggio ora non dice niente di interessante, può darsi invece che più in là abbia qualche cosa da dirvi...
vai nord|sud|est|ovest|su|giu: va nella direzione specificata, se possibile. Se esce il messaggio "Tu non puoi passare!" vuol dire semplicemente che quella porta è chiusa.
vai nord|sud|est|ovest|su|giu: va nella direzione specificata, se possibile. Se esce il messaggio "Tu non puoi passare!" vuol dire semplicemente che quella porta è chiusa. Esempio: vai est.
parla <personaggio: parla con un personaggio. Per esempio, parla Ceravolo parlerà con Ceravolo.
parla <personaggio>: parla con un personaggio. Per esempio, parla Ceravolo parlerà con Ceravolo.
Demo!
Ho pronta una demo del Babaoglu Engine, con tanto di un'avventura di prova:)
- demo.babaoglu.zip
- I sorgenti: babaoglu.zip. È un progetto di NetBeans.
C'è un file .bat che dovrebbe funzionare sotto winzozz, cmq la sintassi è:
java -jar babaoglu.jar demo
demo è la cartella che contiene i files del gioco. Sono files di testo, quindi guardandoli potrete capire la dinamica della piccola avventura che ho scritto: vi conviene aspettare a farlo, prima giocatela e datemi le vostre impressioni!
Faccio un riassunto dei comandi: vai nord|sud|est|ovest|su|giu: va nella direzione specificata, se possibile. Se esce il messaggio "Tu non puoi passare!" vuol dire semplicemente che quella porta è chiusa.
apri nord|sud|est|ovest|su|giu: apre la porta corrispondente alla direzione selezionata. Attenzione: non sempre è possibile aprire tutte le porte, a volte occorrono chiavi, oppure sono semplicemente porte chiuse del tutto! Inoltre, quando si apre una porta NON si va automaticamente in quella direzione: la sequenza di comandi corretta è, per esempio:
apri nord vai nord
uscite: vi dà una lista delle uscite VISIBILI della locazione in cui vi trovate.
guarda: vi dà una descrizione del posto in cui vi trovate, completa di lista di oggetti, personaggi ed uscite. Attenzione: NON tutte le uscite sono visibili, quindi, può darsi che ci siano uscite che il comando guarda inizialmente non rileva!:) Le direzioni sono sempre le solite: nord, sud, est, ovest, su, giu.
guarda <checosa>: posso guardare oggetti o personaggi. Il gioco rispetta le maiuscole, quindi rispettatele anche voi. Inoltre, i nomi degli oggetti e dei personaggi NON contengono spazi, nei comandi.
parla <personaggio: parla con un personaggio. Per esempio, parla Ceravolo parlerà con Ceravolo. È anche possibile indicare un argomento di conversazione, ma non tutti i PNG lo possono fare. Di solito, ma non sempre, quando un PNG dice qualcosa in MAIUSCOLO, provate a chiedergli quella cosa. Esempio: se Dario dice una frase come "mi piacciono i GATTI", potete provare a usare il comando "parla Dario gatti". Un po' rozzo, ma per ora è così:)
prendi <nomeoggetto>: cerca di prendere l'oggetto presente. Non tutti gli oggetti sono trasportabili.
inventario oppure inv: vi dà una lista di ciò che vi portate appresso.
lascia <nomeoggetto>: lascia un oggetto del vostro inventario nel posto in cui vi trovate.
usa <oggetto>: è il comando per interagire con un oggetto. È un po' generico, quindi per ora usa può voler dire fruga o accendi e così via. Più in là vedo di fare qualcosa di più carino.
usa <oggetto> <oggettopassivo>: è un modo per utilizzare un certo oggetto SU di un altro oggetto, detto passivo. Ad esempio, usa martello chiodo cercherà di usare l'oggetto martello con l'oggetto chiodo. Un po' grezzo, ma al solito, siamo agli inizi:)
[@func biblio01_func(string param)
...
...\\
[@func biblio01_func(string param) ... ...
func martello_func(string param, string obj)
...
...\\
func martello_func(string param, string obj) ... ...
func biblio01_nord_func(string param)
...
...\\
func biblio01_nord_func(string param) ... ...
func danio_func(string param, string argomento)
...
...\\
func danio_func(string param, string argomento) ... ...
[@func biblio01_func()\\
[@func biblio01_func(string param)\\
func martello_func(String cheCosa)\\
func martello_func(string param, string obj)\\
func biblio01_nord_func(String cheCosa)\\
func biblio01_nord_func(string param)\\
func danio_func(String argomento)\\
func danio_func(string param, string argomento)\\
endfunc
endfunc@]
I PNG
I Personaggi Non Giocanti hanno un nome e una descrizione. L'interazione di un personaggio con un PNG avviene principalmente tramite la parola, attraverso anche il saggio utilizzo delle Pietre Miliari descritte qui sopra. Tramite opportuni script, è possibile far muovere un PNG in giro per la mappa, passando solo per le uscite aperte della locazione in cui si trova, per esempio, oppure semplicemente teletrasportandosi. Possono dare oggetti o toglierli al personaggio, ed elargire Pietre Miliari.
Gli NPC
Gli NPC (non-playing characters), o PNG (Personaggi Non Giocanti), hanno un nome e una descrizione. L'interazione di un personaggio con un PNG avviene principalmente tramite la parola, attraverso anche il saggio utilizzo delle Pietre Miliari descritte qui sopra. Tramite opportuni script, è possibile far muovere un PNG in giro per la mappa, passando solo per le uscite aperte della locazione in cui si trova, per esempio, oppure semplicemente teletrasportandosi. Possono dare oggetti o toglierli al personaggio, ed elargire Pietre Miliari.
Scrive la lista degli oggetti in inventario.
Scrive la lista degli oggetti in inventario. Abbreviata con inv.
Uscite
uscite
Scrive la lista delle uscite visibili di quella locazione.
descrizione=È una sala ampia, dal pavimento di linoleum blu. Le finestre sono grandi, rivolte verso sud . Ci sono diversi tavoli bianchi, e il silenzio regna sovrano
- direzione visibilità aperta
uscita=nord 1 1 uscita=sud 1 1 uscita=est 0 1
descrizione=È una sala ampia, dal pavimento di linoleum blu.
Le finestre sono grandi, rivolte verso sud. Ci sono diversi tavoli bianchi, e il silenzio regna sovrano
- direzione idloc visibilità aperta
uscita=nord biblio02 true true uscita=sud corridoio01 true true uscita=est cortile01 true false
Schema delle classi
Avvio del gioco
In ogni avventura realizzata per il Babaoglu Engine, occorre che sia definita la pietra miliare di nome inizio, e che la sua relativa func presenti almeno queste funzionalità:
func inizio_func(string param) if (param=="getNomePlayer") return "Studente" elsif (param=="getDescrPlayer") return "Un bel bambino" elsif (param=="getLocIniziale") return "biblio001" else scrivi("Benvenuto nella demo del Babaoglu Engine!") endif endfunc
Infatti, inizio_func viene chiamata per inizializzare il gioco.
Il motore del gioco è scritto in Java, ma il gioco stesso no. Utilizza un linguaggio di script chiamato FScript, che è molto semplice da imparare. Le azioni e le interazioni tra gli oggetti, le locazioni della mappa ed il personaggio avvengono tramite gli script scritti in FScript. Il bello di un sistema del genere è che il motore rimane identico, ma si può cambiare la realtà del gioco intervenendo su questi script, senza bisogno di ricompilare alcunché. Inoltre, la semplicità del linguaggio di script permette la creazione di avventure anche a chi non è programmatore. Un altro vantaggio è che si può separare il gioco dalla sua interfaccia: per ora c'è una semplice GUI, ma non ci vuole molto a scrivere qualcosa di diverso e più apapriscente. La grafica non è prevista (niente giochi tipo Monkey Island, per intenderci).
Il motore del gioco è scritto in Java, ma il gioco stesso no. Utilizza un linguaggio di script chiamato FScript, che è molto semplice da imparare. Le azioni e le interazioni tra gli oggetti, le locazioni della mappa ed il personaggio avvengono tramite gli script scritti in FScript. Il bello di un sistema del genere è che il motore rimane identico, ma si può cambiare la realtà del gioco intervenendo su questi script, senza bisogno di ricompilare alcunché. Inoltre, la semplicità del linguaggio di script permette la creazione di avventure anche a chi non è programmatore. Un altro vantaggio è che si può separare il gioco dalla sua interfaccia: per ora c'è una semplice GUI, ma non ci vuole molto a scrivere qualcosa di diverso e più apapriscente. La grafica non è prevista (niente giochi tipo Monkey Island, per intenderci).
PNG
NPC
idLocAttuale è la posizione in cui si trova in un preciso istante. La funzione di default di un PNG si chiama <nome>_func(String argomento). L'argomento è "niente" se si vuole attivare la sequenza normale, oppure può essere "parla" per interagire con il personaggio.
idLocAttuale è la posizione in cui si trova in un preciso istante. La funzione di default di un PNG si chiama <nome>_func(string azione, string argomento). L'azione è "niente" se si vuole attivare la sequenza normale, oppure può essere "parla" per interagire con il personaggio. L'argomento può essere richiesto, ad esempio, per parlare con l'NPC di uno specifico argomento.
Il motore del gioco è scritto in Java, ma il gioco stesso no. Utilizza un linguaggio di script chiamato FScript, che è molto semplice da imparare. Le azioni e le interazioni tra gli oggetti, le locazioni della mappa ed il personaggio avvengono tramite gli script scritti in FScript. Il bello di un sistema del genere è che il motore rimane identico, ma si può cambiare la realtà del gioco intervenendo su questi script, senza bisogno di ricompilare alcunché. Inoltre, la semplicità del linguaggio di script permette la creazione di avventure anche a chi non è programmatore. Un altro vantaggio è che si può separare il gioco dalla sua interfaccia: per ora è a linea di comando, ma non occorre cambiare nulla per portare il tutto dentro a una semplice GUI. La grafica non è prevista (niente giochi tipo Monkey Island, per intenderci).
Il motore del gioco è scritto in Java, ma il gioco stesso no. Utilizza un linguaggio di script chiamato FScript, che è molto semplice da imparare. Le azioni e le interazioni tra gli oggetti, le locazioni della mappa ed il personaggio avvengono tramite gli script scritti in FScript. Il bello di un sistema del genere è che il motore rimane identico, ma si può cambiare la realtà del gioco intervenendo su questi script, senza bisogno di ricompilare alcunché. Inoltre, la semplicità del linguaggio di script permette la creazione di avventure anche a chi non è programmatore. Un altro vantaggio è che si può separare il gioco dalla sua interfaccia: per ora c'è una semplice GUI, ma non ci vuole molto a scrivere qualcosa di diverso e più apapriscente. La grafica non è prevista (niente giochi tipo Monkey Island, per intenderci).
- int inInventario(String oggetto) = 1 sì, 0 no
- int inPM(String PietraMiliare) = 1 sì, 0 no
- int inInventario(String oggetto) = 0 sì, 1 no
- int inPM(String PietraMiliare) = 0 sì, 1 no
- apri|chiudi(String uscita) = apre|chiude l'uscita, indicata nella forma idloc_uscita
- apri|chiudi(String idloc, String uscita) = apre|chiude l'uscita
Anche alle pietre miliari è associata una funzione di default, chiamata <nomepietra>_func.
Anche alle pietre miliari è associata una funzione di default, chiamata <nomepietra>_func. Quando una pietra miliare viene data al player, viene chiamata la funzione <nomepietra>_func con parametro "dai"; quando viene tolta il parametro è "togli".
- String doveMiTrovo() = restituisce l'idloc della locazione attuale di un PNG
- String doveNPC() = restituisce l'idloc della locazione attuale di un PNG
- int domanda(String domande) = pone le domande contenute nella String domande al player, e restituisce quale di queste ha scelto. Le domande sono separate da una | (pipe), eg: "Come ti chiami?|Sei gay?|Ma tu sei il famoso Cthulhu?"
- vai(String idloc) = sposta il PNG nella locazione indicata da idloc
- int domanda(String testo, String domande) = pone la domande contenuta nella String testo all' NPC o al player, e restituisce quale di queste ha scelto. Le domande sono separate da una | (pipe), eg: "Come ti chiami?|Sei gay?|Ma tu sei il famoso Cthulhu?"
- spostaNPC(String chi, String idloc) = sposta il PNG nella locazione indicata da idloc
- spostaPlayer(String idloc) = sposta il Player nella locazione indicata da idloc
Si assume che i files con estensione .oglu
contengano la descrizione di locazioni e oggetti, mentre i files .script
devono contenere gli script.
Si assume che i files con estensione .baba
contengano la descrizione di locazioni e oggetti, i files .script
devono contenere gli script, le locazioni siano contenute nei files .loc
.
<nome>::=<definizione>
<nome>=<definizione>
[@tipo::=locazione nome::=Biblioteca id::=biblio01 descrizione::=È una sala ampia, dal pavimento di linoleum blu. Le finestre sono grandi, rivolte verso sud
[@tipo=locazione nome=Biblioteca id=biblio01 descrizione=È una sala ampia, dal pavimento di linoleum blu. Le finestre sono grandi, rivolte verso sud
uscita::=nord 1 1 uscita::=sud 1 1 uscita::=est 0 1
uscita=nord 1 1 uscita=sud 1 1 uscita=est 0 1
[@tipo::=oggetto nome::=martello descrizione::=Un martello da muratore, col manico lungo e sporco di cemento.
[@tipo=oggetto nome=martello descrizione=Un martello da muratore, col manico lungo e sporco di cemento.
tipo::=png nome::=Danio descrizione::=Un uomo di mezza età, un po' calvo, dal viso tranquillo. idloc::=biblio01
tipo=png nome=Danio descrizione=Un uomo di mezza età, un po' calvo, dal viso tranquillo. idloc=biblio01
PNG
Pietra Miliare
- String evento
Una pietra miliare è del tutto simile ad un Oggetto, ed è possibile associarvi una String contenente il testo che verrà comunicato al giocatore in occasione del conseguimento di tale Pietra Miliare.
Anche alle pietre miliari è associata una funzione di default, chiamata <nomepietra>_func.
PNG
- String nome
- inventario => struttura dati da definire, presumibilmente una Map
- pietreMiliari => struttura dati da definire, presumibilmente una Map
- inventario => ArrayList di Oggetti
- pietreMiliari => arrayList di Pietre Miliari
endfunc
[@func biblio01_func() ... ...
[@func biblio01_func()
...
...\\
func martello_func(String cheCosa) ... ...
func martello_func(String cheCosa)
...
...\\
func biblio01_nord_func(String cheCosa) ... ...
func biblio01_nord_func(String cheCosa)
...
...\\
func danio_func(String argomento) ... ...
func danio_func(String argomento)
...
...\\
idLocAttuale è la posizione in cui si trova in un preciso istante. La funzione di default di un PNG si chiama <nome>_funz(String argomento). L'argomento è "niente" se si vuole attivare la sequenza normale, oppure può essere "parla" per interagire con il personaggio.
idLocAttuale è la posizione in cui si trova in un preciso istante. La funzione di default di un PNG si chiama <nome>_func(String argomento). L'argomento è "niente" se si vuole attivare la sequenza normale, oppure può essere "parla" per interagire con il personaggio.
PNG
tipo::=png nome::=Danio descrizione::=Un uomo di mezza età, un po' calvo, dal viso tranquillo. idloc::=biblio01
func martello_func(String oggetto)
func martello_func(String cheCosa)
func biblio01_nord(String oggetto)
func biblio01_nord_func(String cheCosa) ... ... endfunc
func danio_func(String argomento)
Quando si tenta di aprire una porta con un oggetto, occorre specificarlo nel comando apri. Un'uscita ha una funzione di default associata, di nome <idloc>_<direzione>_func => biblio_nord_func().
Quando si tenta di aprire una porta con un oggetto, occorre specificarlo nel comando apri. Un'uscita ha una funzione di default associata, di nome <idloc>_<direzione>_func => biblio_nord_func(String cheCosa).
Un oggetto ha una funzione di default associata, di nome <nome_oggetto>_funz(String cheCosa). Se l'argomento cheCosa è "niente", si attiva l'azione associata all'oggetto, per esempio suonarlo se è uno strumento musicale. Altrimenti, cheCosa può essere il nome di un altro oggetto presente nell inventario oppure un'uscita della locazione attuale. In questi casi, avverranno le azioni stabilite dallo script.
Un oggetto ha una funzione di default associata, di nome <nome_oggetto>_func(String cheCosa). Se l'argomento cheCosa è "niente", si attiva l'azione associata all'oggetto, per esempio suonarlo se è uno strumento musicale. Altrimenti, cheCosa può essere il nome di un altro oggetto presente nell inventario oppure un'uscita della locazione attuale. In questi casi, avverranno le azioni stabilite dallo script.
descrizione::=È una sala ampia, dal pavimento di linoleum blu. Le finestre sono grandi, rivolte verso sud. Ci sono diversi tavoli bianchi, e il silenzio regna sovrano
descrizione::=È una sala ampia, dal pavimento di linoleum blu. Le finestre sono grandi, rivolte verso sud . Ci sono diversi tavoli bianchi, e il silenzio regna sovrano
Gli script, come spiegato sopra, sono contenuti in funzioni con un nome standard, così da poter essere facilmente rintracciabili.
Gli script, come spiegato sopra, sono contenuti in funzioni con un nome standard, così da poter essere facilmente rintracciabili.
[@func biblio01_func() ... ... endfunc
func martello_func(String oggetto) ... ... endfunc
func biblio01_nord(String oggetto) ... ... endfunc
@]
tipo::=locazione
[@tipo::=locazione
- direzione
uscita::=nord 0
- direzione visibilità aperta
uscita::=nord 1 1 uscita::=sud 1 1 uscita::=est 0 1 @]
Oggetti
[@tipo::=oggetto nome::=martello descrizione::=Un martello da muratore, col manico lungo e sporco di cemento.
Gli script
Gli script, come spiegato sopra, sono contenuti in funzioni con un nome standard, così da poter essere facilmente rintracciabili.
Formato dei files
Il gioco è salvato in una cartella, la quale viene passata come argomento al motore del gioco all'avvio. La cartella può contenere un qualsiasi numero di files.
Si assume che i files con estensione .oglu
contengano la descrizione di locazioni e oggetti, mentre i files .script
devono contenere gli script.
In questi files, le informazioni vengono codificate secondo un certo schema che presento qui sotto.
Divisione in blocchi
Un blocco è composto da un certo numero di righe contenenti definizioni, separate da righe contenenti 4 trattini. Le definizioni sono del tipo:
<nome>::=<definizione>
La prima riga del blocco deve contenere il tipo del blocco stesso. Le righe che iniziano per # sono considerate commenti.
Locazioni
tipo::=locazione nome::=Biblioteca id::=biblio01 descrizione::=È una sala ampia, dal pavimento di linoleum blu. Le finestre sono grandi, rivolte verso sud. Ci sono diversi tavoli bianchi, e il silenzio regna sovrano
- direzione
uscita::=nord 0
- String chiave
La chiave è l'oggetto per aprirla. Quando si tenta di aprire una porta con un oggetto, occorre specificarlo. Un'uscita ha una funzione di default associata, di nome <idloc>_<direzione>_func => biblio_nord_func().
Quando si tenta di aprire una porta con un oggetto, occorre specificarlo nel comando apri. Un'uscita ha una funzione di default associata, di nome <idloc>_<direzione>_func => biblio_nord_func().
- Boolean mobile
Solo gli oggetti contrassegnati con mobile possono essere messi in inventario.
<dove> deve essere un'uscita valida. Se presente l'argomento <oggetto>, si chiamerà lo script dell'uscita con <oggetto> come argomento.
<dove> deve essere un'uscita valida. Se presente l'argomento <oggetto>, si chiamerà lo script dell'uscita con <oggetto> come argomento, e l'oggetto deve essere presente nell'inventario.
Usa
usa <oggetto_attivo> <oggetto_passivo>
L'oggetto attivo
L'<oggetto_attivo> può essere nell'inventario oppure presente nella lista degli oggetti della locazione attuale. L'<oggetto_passivo> può essere nell'inventario o nella locazione.
Funzioni usabili negli script
- String doveMiTrovo() = restituisce l'idloc della locazione attuale di un PNG
- int inInventario(String oggetto) = 1 sì, 0 no
- int inPM(String PietraMiliare) = 1 sì, 0 no
- String dovePlayer() = restituisce l'idloc della locazione attuale del player
- daiOggetto(String oggetto) = dà l'oggetto al player
- daiPM(String PM) = dà PM al player
- togliOggetto(String oggetto) = toglie l'oggetto al player
- togliPM(String OM) = toglie la PM al player
- int random(int limite) = restituisce un valore random compreso tra 0 incluso e limite escluso
- int quanteUscite(String idloc) = restituisce il numero di uscite complessivo della idloc specificata
- int aperta(int uscita) = 1 sì, 0 no. NOTA: uscita qui corrisponde al numero di sequenza dell'uscita così come restituito dalla funzione quanteUscite(String idloc)
- String dammiIdLoc(int uscita) = restituisce la stringa contenente l'id della locazione indicata, che corrisponde al numero di sequenza delle uscite restituito da quanteUscite
- scrivi(String cheCosa) = scrive la stringa cheCosa
- int domanda(String domande) = pone le domande contenute nella String domande al player, e restituisce quale di queste ha scelto. Le domande sono separate da una | (pipe), eg: "Come ti chiami?|Sei gay?|Ma tu sei il famoso Cthulhu?"
- vai(String idloc) = sposta il PNG nella locazione indicata da idloc
- svuotaInventario() = svuota l'inventario del player...
- apri|chiudi(String uscita) = apre|chiude l'uscita, indicata nella forma idloc_uscita
- visibile|invisibile(String uscita) = imposta visibile o invisibile l'uscita, indicata nella forma idloc_uscita
Le locazioni
Le locazioni sono i vari punti della mappa del gioco in cui il giocatore, gli oggetti e i PNG o NPC (personaggi non giocanti) si possono trovare.
Una locazione fondamentalmente ha un nome e un id (per essere trovata in modo univoco dagli script) e delle uscite. Le uscite possono essere in una delle direzioni note (nord, est, sud, ovest, su, giu, e magari anche quelle intermedie come nordest e così via). Ogni uscita può essere visibile o invisibile. Inoltre, una particolare uscita può essere aperta o chiusa, e la sua apertura può dipendere dall'interazione di un oggetto con essa. Ciò vuol dire che il player può dover trovare una chiave per poter andare in cantina, per esempio.
Ad ogni locazione è possibile associare uno script. Quello script verrà eseguito ogniqualvolta il giocatore finirà in una locazione. Per esempio, se entro in cantina la prima volta, posso sbattere la testa. La seconda volta starò attento e non lo farò più. Oppure, se entro in un tempio con un amuleto cthulhesco, potrei causare un crollo e restarci secco.
Gli oggetti
Un oggetto ha un nome e una descrizione. Il giocatore ha un inventario, che contiene un numero infinito di oggetti (ma sì! chi se ne frega:), e può avere più di una copia di uno stesso oggetto. Oggetti come le chiavi possono essere usate per aprire porte. In generale, il giocatore può usare un oggetto da solo (per esempio, usare una cornamusa per suonare un po') oppure usare un oggetto con un altro oggetto (per esempio, usare una chiave con una porta).
Le pietre miliari
Sono come oggetti, ma non rappresentano entità fisiche, bensì dei punti di svolta che il giocatore ha raggiunto nella trama del gioco. Per esempio, se salvo una principessa, avrò una pietra miliare "Salvata la principessa" e quando parlerò al re suo padre, egli lo saprà e mi darà dei soldi, assieme ad una pietra miliare chiamata "Ricevuta ricompensa". Se parlo al re un'altra volta ancora, egli mi ringrazierà ma non mi darà più dei soldi, perché la pietra miliare "Ricevuta ricompensa" attesterà che l'ho già fatto. Qui si intravede bene la potenza degli script...
I PNG
I Personaggi Non Giocanti hanno un nome e una descrizione. L'interazione di un personaggio con un PNG avviene principalmente tramite la parola, attraverso anche il saggio utilizzo delle Pietre Miliari descritte qui sopra. Tramite opportuni script, è possibile far muovere un PNG in giro per la mappa, passando solo per le uscite aperte della locazione in cui si trova, per esempio, oppure semplicemente teletrasportandosi. Possono dare oggetti o toglierli al personaggio, ed elargire Pietre Miliari.
Parlare con un PNG significa anche porgli delle domande. Lo script associato al PNG mi dirà quali domande posso fargli, e in base a ciò che gli chiederò otterrò le opportune risposte.
Dati tecnici
In questa sezione sono raccolte le note relative all'implementazione del gioco e degli script.
Locazioni
La Locazione è un oggetto con i seguenti campi:
- String nome
- String id
- String descrizione
- ArrayList<Uscita> uscite
- ArrayList<Oggetto> oggetti
Lo script di default associato ad una locazione è una funzione FScript dal nome composto così: <id>_func(). Per esempio, se la locazione Biblioteca ha id biblio, la sua funzione di default sarà chiamata biblio_func. Il motore cercherà questa funzione: se esiste, sarà eseguita.
Uscita:
- String direzione (nord, sud, etc...)
- Boolean visibile
- Boolean aperta
- String chiave
La chiave è l'oggetto per aprirla. Quando si tenta di aprire una porta con un oggetto, occorre specificarlo. Un'uscita ha una funzione di default associata, di nome <idloc>_<direzione>_func => biblio_nord_func().
Oggetti
- String nome
- String descrizione
Un oggetto ha una funzione di default associata, di nome <nome_oggetto>_funz(String cheCosa). Se l'argomento cheCosa è "niente", si attiva l'azione associata all'oggetto, per esempio suonarlo se è uno strumento musicale. Altrimenti, cheCosa può essere il nome di un altro oggetto presente nell inventario oppure un'uscita della locazione attuale. In questi casi, avverranno le azioni stabilite dallo script.
Da notare che nella riga di comando il primo argomento è l'oggetto attivo, mentre il secondo è l'oggetto passivo. Ciò vuol dire che una riga di comando come usa accendino carta
chiamerà la funzione carta_funz("accendino") e lo script di carta reagirà di conseguenza.
PNG
- String nome
- String descrizione
- String idLocAttuale
idLocAttuale è la posizione in cui si trova in un preciso istante. La funzione di default di un PNG si chiama <nome>_funz(String argomento). L'argomento è "niente" se si vuole attivare la sequenza normale, oppure può essere "parla" per interagire con il personaggio.
Giocatore
- String nome
- inventario => struttura dati da definire, presumibilmente una Map
- pietreMiliari => struttura dati da definire, presumibilmente una Map
Comandi del giocatore
Vai
vai <dove>
<dove> deve essere un'uscita valida. Il comando è eseguito solo se la porta è aperta e non ci sono controindicazioni al passaggio (indicate dallo script associato alla porta). Un'uscita invisibile diventa visibile dopo che la si è trovata.
Apri
apri <dove> [<oggetto>]
<dove> deve essere un'uscita valida. Se presente l'argomento <oggetto>, si chiamerà lo script dell'uscita con <oggetto> come argomento.
Prendi
prendi <oggetto>
<oggetto> deve essere un oggetto presente nella lista di oggetti della locazione attuale.
Lascia
lascia <oggetto>
<oggetto> deve essere un oggetto presente nell'inventario. Se ci sono più copie dell'oggetto, ne viene lasciata 1. L'oggetto lasciato si aggiunge alla lista degli oggetti della locazione corrente.
Inventario
inventario
Scrive la lista degli oggetti in inventario.
Guarda
guarda <oggetto>|<personaggio>
L'ordine di analisi è il seguente: se <oggetto> è un oggetto valido, lo si cerca prima nell'inventario, e se non c'è tra gli oggetti presenti nella locazione. Altrimenti, si controlla se si tratta di un nome valido di personaggio, e se quel personaggio si trova attualmente nella locazione in cui si trova il player.
Quando si trova un caso positivo, viene visualizzata la descrizione dell'oggetto o del personaggio.
Usa
usa <oggetto_attivo> [<oggetto_passivo>]
Usa
usa <oggetto_attivo> <oggetto_passivo>
L'oggetto attivo
(:title Babaoglu Engine:)
:: Babaoglu Engine ::
Che cos'è
Il Babaoglu Engine è un semplice motore per psuedo giochi di ruolo che si giocano da linea di comando. Ricorda un po' le IF (Interactive Fiction) e i MUD (Multi-User Dungeon) nel tipo di interazione col gioco, solo che non c'è opportunità di multiplayer.
Serve per poter scrivere delle avventure in cui il giocatore si muove qua e là per una mappa, incontrando persone, raccogliendo e utilizzando oggetti. Non è previsto (per ora) il combattimento.
Il motore del gioco è scritto in Java, ma il gioco stesso no. Utilizza un linguaggio di script chiamato FScript, che è molto semplice da imparare. Le azioni e le interazioni tra gli oggetti, le locazioni della mappa ed il personaggio avvengono tramite gli script scritti in FScript. Il bello di un sistema del genere è che il motore rimane identico, ma si può cambiare la realtà del gioco intervenendo su questi script, senza bisogno di ricompilare alcunché. Inoltre, la semplicità del linguaggio di script permette la creazione di avventure anche a chi non è programmatore. Un altro vantaggio è che si può separare il gioco dalla sua interfaccia: per ora è a linea di comando, ma non occorre cambiare nulla per portare il tutto dentro a una semplice GUI. La grafica non è prevista (niente giochi tipo Monkey Island, per intenderci).