Vale la pena implementare le meccaniche / regole di gioco separatamente dal codice principale?


25

Non sono sicuro che si adatti allo scopo di questa community o che debba invece andare su Stackoverflow.

Supponiamo che io voglia che il mio gioco sia facilmente estensibile nel suo nucleo, cioè voglio che molte persone, anche senza una discreta conoscenza della programmazione, siano in grado non solo di modificare le regole esistenti, ma anche di aggiungere meccaniche di gioco totalmente nuove. Non sono un buon programmatore, ma sono pronto per imparare, ho solo bisogno di alcune indicazioni e certezza che può essere fatto.

Quello a cui ho pensato è se è possibile / fattibile implementare in qualche modo le meccaniche di gioco separatamente dal codice principale dell'utilità? Voglio dire, per i giochi da tavolo abbiamo quei manuali che non contengono algoritmi reali di tutte le azioni, ma piuttosto descrivono alcuni protocolli e limiti, facendo riferimento pesantemente al contesto di ciascuno di questi elementi. È possibile fare qualcosa di simile per un gioco per PC, come descrivere tutte le regole in un livello molto alto, facilmente leggibile (e modificabile) da un linguaggio di programmazione umano, che viene poi "consumato" e analizzato dal codice di utilità in un istanza funzionante della meccanica di gioco?

Mi sembra davvero di dover scrivere la mia lingua e un compilatore per essa)) Che non sarò in grado di fare, ovviamente. Ma potrebbe esserci un approccio più semplice al problema?

Cordiali saluti: la mia lingua preferita per il codice di utilità sarà Python 3.x


Dato che non hai esperienza e lavori come singolo sviluppatore, ti suggerisco di non provare a implementare tutto da solo. L'uso delle librerie SDL2 può esserti molto utile in molte aree e hanno i collegamenti Python in modo da poter lavorare nella lingua che preferisci. Per ottenere quello che stai cercando, il design della tua architettura dovrebbe essere fatto molto, molto, attentamente e anticiperei almeno una riscrittura completa anche per un team esperto. Inoltre, Python non è molto più facile da imparare rispetto a qualsiasi altra lingua e secondo me ha i maggiori problemi a livello intermedio.
tbek

Il concetto che stai cercando è comune al di fuori dello sviluppatore del gioco. Esistono raccolte di strumenti software chiamati motori delle regole aziendali che devono fare esattamente questo. In game dev, puoi anche sfruttare questi strumenti. Il GameplayKit di Apple, ad esempio, includeva le classi GKRuleSystem e GKRule per uno scopo simile. Ci vorrebbe un certo sforzo per estenderlo per consentire l'editing esterno di questo, ma potrebbe essere strutturato in modo da cambiare comportamento senza ricompilazione del codice.
Sandy Chapman,

Risposte:


34

In generale, la facilità con cui qualsiasi sistema può essere esteso dipende dal grado in cui i suoi sottosistemi sono strettamente o liberamente accoppiati . Di solito, più i sottosistemi sono accoppiati in modo lasco, più è facile modificarli man mano che sono isolati e non richiedono necessariamente una completa comprensione del sistema nel suo insieme.

Nulla è gratuito, tuttavia: tale sistema in genere richiede più risorse (varie combinazioni di tempo, denaro e abilità) per essere costruito. Il grado di estensibilità che hai descritto mi sembra direttamente in contrasto con il livello di abilità che hai attribuito a te stesso. Potrebbe essere fatto, ma creare software come hai descritto è un'impresa molto impegnativa.

Le cose esistenti più vicine di cui sono a conoscenza sono Vassal (che è molto più programmatico di quanto tu abbia descritto), o creare una mod per Tabletop Simulator (che dipende principalmente dall'interazione umana per interpretare e applicare qualsiasi regola di gioco).


Consiglio solido. Cerco di mantenere il mio codice il più liberamente possibile accoppiato per facilitare l'estensibilità, ma avrai sempre dei casi in cui è molto più facile hardcodificare / accoppiare qualcosa. Anche come sviluppatore professionista non è un compito facile e sicuramente non adatto ai principianti.
angarg12,

TTS ora supporta Lua e l'applicazione delle regole non è completamente all'altezza delle interazioni umane.
Ave,

17

Quello a cui ho pensato è se è possibile / fattibile implementare in qualche modo le meccaniche di gioco separatamente dal codice principale dell'utilità?

È assolutamente possibile. Un modo usato spesso nei giochi è lo scripting Lua .

Dall'articolo collegato:

Lua è stato originariamente progettato nel 1993 come linguaggio per l'estensione delle applicazioni software per soddisfare la crescente domanda di personalizzazione dell'epoca.

Molti giochi usano Lua. (Vorrei link, ma la reputazione di un nuovo utente sta limitando il mio conteggio dei link.)

Gli script Lua possono essere compilati in fase di esecuzione. Ciò significa che possono (ad esempio) essere file di testo che si trovano nella directory "script" del tuo gioco, facilmente modificabili da un modder. Il tuo gioco li carica e li esegue.

Ho visto gli script di Lua definire le proprietà delle unità di gioco. Ecco un esempio casuale di TA Spring.

Ma vuoi "descrivere tutte le regole". In teoria questo è possibile, poiché Lua è un linguaggio completo, ma il problema è che devi essere abbastanza coscienzioso da avere il codice di gioco principale in grado di cercare script per estenderne il comportamento.

Ad esempio, potresti sviluppare un gioco di carte che sa cercare le carte in una directory "script / carte". È perfetto per aggiungere nuove carte o modificare quelle esistenti. Ma se in seguito vuoi espandere il tuo gioco per includere miniature su una griglia, dovrai modificare il codice di base - nessuna quantità di Lua giocherellare ti porterà da solo.

Nota: tengo in contatto Lua perché so che è comunemente usato sia nei giochi che nei software per la personalizzazione. Non sto suggerendo che sia l'unica soluzione, né la migliore per le esigenze dell'interrogante.


7
Questa risposta implica che Lua è l'unico linguaggio di scripting utilizzato in questo modo. Esistono molti altri linguaggi di scripting che possono essere integrati nei motori di gioco. Alcuni motori vanno anche per la propria strada e implementano il proprio linguaggio di scripting specifico del dominio. Di solito non lo consiglierei (perché costruire una lingua è un sacco di lavoro), ma dovrebbe essere menzionato.
Philipp,

3

C'è un continuum di approcci e se ne valga la pena dipenderà esattamente da ciò che stai cercando di fare. In particolare, quanto controllo vuoi offrire al tweaker?

All'estremo limite del controllo, puoi semplicemente lasciare che tweaker modifichi il codice dell'intero gioco. A quel punto essenzialmente pubblicheresti il ​​codice di utilità e almeno un esempio di come usarlo. Un tweaker potrebbe usare il codice che desidera.

Un approccio che offre un po 'meno controllo sarebbe in qualche modo "congelare" il tuo codice di utilità (dicilo compilandolo in anticipo) e lasciare che tweaker riempia solo funzioni specifiche (callback), limitando ciò che possono fare. A seconda di ciò che si desidera fare, questo approccio può assumere molte forme. Un metodo comune sarebbe quello di mettere tutta la parte di visualizzazione nel codice utility / main e tutti i meccanici nella parte modificabile. Oppure, potresti voler mantenere alcuni meccanici nella parte "congelata" perché è improbabile che i giocatori vogliano cambiarli, o renderli mutabili è troppo complicato.

All'estremità a basso controllo del continuum è solo consentire ai tweaker di modificare i valori in un intervallo fisso. Un file di dati che ti consente di selezionare i colori delle cose all'interno del gioco sarebbe un esempio. Tuttavia, è possibile utilizzare questo approccio e offrire ancora molta personalizzazione. Sarebbe possibile definire una selezione di funzioni e consentire ai tweaker di comporle per creare i callback dell'approccio precedente, ma non consentendo loro di definirne di nuovi. O forse salti la parte della composizione e offri solo una selezione finita.

I dettagli di tutti questi approcci e quale si adatta al tuo caso d'uso dipende dal tipo di gioco base che vuoi fare e da quanto controllo vuoi rinunciare. Nota che i giochi commerciali usano generalmente solo il secondo e il terzo metodo perché il primo consente ai giocatori di creare giochi completamente separati, il che introduce problemi di licenza complicati. Si noti che poiché questi approcci formano un continuum, anche il secondo approccio può introdurre questi problemi.


Realizzarlo opensource è il mio obiettivo, in realtà. Quello che vedo come un problema è come implementare questa estensibilità nel modo più semplice, in modo che altri giocatori del gioco (che sono MP game, tra l'altro) possano creare le proprie estensioni del set di regole di base e condividerle con ciascuna altro, in qualche modo evitando conflitti allo stesso tempo. Quindi, se un utente sviluppa una certa estensione che ha la precedenza su determinate regole e un altro sviluppa una diversa estensione, come garantire che il terzo utente che desidera utilizzare entrambi quelli nei suoi giochi non incontrerà problemi di compatibilità? Oltre a costringerli a collaborare strettamente.
tis

..e implementarlo in modo tale da non richiedere la modifica di alcun codice di utilità e quindi troppe conoscenze sulla programmazione.
tis

1
Non penso che ci sarebbe un modo per prevenire problemi di compatibilità, (anche l'impostazione del colore di qualcosa può causarlo!) Penso che la cosa migliore da fare sia avere un modo per rilevare possibili problemi di compatibilità e avere un buon modo per gli utenti per rispondere. A seconda del design dell'interfaccia del codice di utilità e delle estensioni in questione, potrebbe esserci un modo per ordinare callback ecc. Che produce il risultato desiderato. Inoltre, potrebbe non esserci. Avvisare l'utente che potrebbero esserci problemi e perché sembra un'esperienza utente migliore delle cose che si rompono senza spiegazioni.
Ryan1729,

2

È assolutamente possibile separare le regole del sistema dal codice che applica tali regole. Preferisco strutturare il mio codice in questo modo per progetti complessi, in quanto semplifica l'aggiunta di nuove regole o la modifica delle regole in un secondo momento senza introdurre bug nel sistema sottostante. E i bug in un motore di regole vengono trovati più velocemente dei bug in un sistema in cui le regole e altri codici vengono mescolati insieme in modo altamente ridicolo, perché lo stesso motore di regole viene utilizzato più volte da ogni regola.

Se ne valga la pena dipende dalla complessità del sistema. Come se non mi preoccupassi di Pac-Man, ma non potevo immaginare di scrivere Dwarf Fortress in nessun altro modo.


Grazie, @Robyn. Qualche consiglio di lettura a qualcuno che non sa nemmeno come affrontare correttamente questo progetto? Esistono modelli di progettazione consolidati per tali applicazioni? Libri che trattano l'argomento?
tis

Niente libri, scusa. Ma l'idea di base di un semplice motore di regole: crea una classe Rule che abbia una proprietà per ogni informazione necessaria per descrivere una regola. Se alcune di queste proprietà contengono funzioni lambda, è possibile assegnare loro comportamenti complessi. Crea una classe che crea un'istanza di un elenco di regole, quindi tutte le tue regole sono in un unico posto. Crea un'altra classe che abbia un metodo che accetta un elenco di regole come input e le applica al sistema.
Robyn,

2

È sicuramente fattibile. Se ne vale la pena dipende dai tuoi obiettivi.

Non devi inventare la tua lingua o scrivere un compilatore per farlo funzionare.

Se vuoi che il tuo gioco sia facilmente estensibile, è probabilmente una buona idea provarci.

Probabilmente è più lavoro per te, almeno a breve termine, creare sistemi comprensibili e rendere le cose facili da modificare.

Un gioco che fa questo è Rimworld (non ho affiliazioni) e potresti essere in grado di vedere e imparare da come hanno fatto, fondamentalmente mettendo molti dati di gioco e meccanismi in file XML che sono nelle cartelle di gioco per chiunque possa vederli e modificare. Il nucleo / motore del gioco è stato realizzato utilizzando Unity.

C'è anche la possibilità di estendere / approfondire il gioco con la programmazione reale, ne so di meno ma puoi imparare guardando il forum delle mod.

La possibilità di modding rende il gioco più interessante per molte persone e penso che abbia contribuito molto al suo successo. Inoltre, consente agli sviluppatori di inserire qualsiasi contenuto mod che desiderano nel gioco principale e, in un certo senso, ciò accelera lo sviluppo e migliora il gioco poiché ottengono assistenza da molte persone e possono decidere di accettare le cose in base a ciò che è popolare, ciò che sembra funzionare, ecc.

E ovviamente, specialmente per un piccolo studio indipendente, hanno centinaia di persone che escono con idee e le testano per loro, che è un sacco di lavoro che non potevano fare da soli, né probabilmente assumere persone per farlo.


Anche se posso vedere come i dati di gioco possono essere definiti con XML, non riesco a immaginare come utilizzarli per definire le meccaniche / regole del gioco. Potresti fornire qualche esempio / articolo sull'argomento, forse?
tis

@tis Le regole sono solo un altro tipo di dati. Se il mio motore ha "Se A do B" posso caricare A e B da un file XML, ora gli utenti possono mettere regole abbastanza arbitrarie, un altro bit che può aiutare è quello di fornire un elenco con tutti i possibili As e Bs che supporti di per sé , ad es. "Se status statustype quindi movepeed 100", "If status statustype e time> x then status statustype" Quindi nel tuo progetto pensa a quali tipi di regole vuoi consentire su quali tipi di oggetti (stato, tempo, movepeed) e con quali tipi di composizione consentire (e / o, ecc ...). Se lo stato sott'acqua e il tempo> 5 salute -10.
Tbek

1

Potresti voler esaminare il design orientato agli oggetti . Python ha un buon supporto per questo.

Sono scritti libri spessi su questo, che possono essere spaventosi quando sei nuovo, ma i principi principali sono abbastanza facili.

Il punto principale è solo che identifichi il tipo di oggetti con cui stai lavorando. Non dici a che tipo di gioco stai pensando, ma cose come Giocatore, Mostro, Oggetto, Equipaggiamento, Arma, Armatura e così via sono oggetti tipici.

Se vuoi diversi tipi di gioco, probabilmente vorrai un oggetto di gioco che si occupi delle condizioni di vittoria e così via. Forse anche un oggetto Mappa?

A volte non è chiaro se qualcosa merita di essere un oggetto o no, ad esempio un danno. Se non danneggi un oggetto, il codice sarà più semplice, ma renderlo un oggetto semplifica la personalizzazione.

Sottoclasse: Sia le armi che le armature sono equipaggiamento. Le attrezzature sono articoli. Probabilmente ci sono altri tipi di oggetti. Probabilmente ti sarà utile definire un combattente di classe di cui sia Giocatori che Mostri sono sottoclassi.

L'idea è che, ad esempio, le armi avranno molte cose in comune con tutti gli altri tipi di oggetti, hanno peso, dimensioni e altre proprietà del genere.

Quindi, la sottoclasse ti dà un modo di dire che "Le armi sono come gli altri oggetti, ma inoltre puoi esercitarli, influenzano il danno che fai, ecc. Ecc."

La sottoclasse consente anche ai tuoi mod builder di dire "Il mio nuovo tipo di arma è proprio come le armi standard tranne che ..."

Quindi devi decidere quale oggetto è responsabile di cosa. Non è così facile come sembra e dovresti pensarci un po '. Fare le scelte sbagliate non influirà molto sul gioco di base, ma renderà più difficile la personalizzazione.

Finché stai solo armeggiando da solo puoi cambiare le cose, ma nel momento in cui rilasci qualcosa al pubblico, apportare modifiche diventa molto più difficile! Le persone realizzeranno mod che dipendono dal fatto che le cose siano proprio come sono adesso. Anche i bug. Le persone scriveranno mod che dipendono dai bug presenti nel codice. Se cambi cose, quelle mod si romperanno e appariranno linciaggi mob a casa tua.

Per esempio:

Un giocatore che brandisce un'arma attacca un mostro che indossa armature multiple. Ciò avviene in una particolare modalità di gioco e su una determinata mappa.

Entrambi i combattenti possono avere abilità come colpo critico e schivata.

Ora, quale oggetto è responsabile di cosa?

Non esiste una risposta corretta a questo. Molto dipende dal tipo di personalizzazione che si desidera consentire.

Se non chiami mai un oggetto (es. La Mappa), quell'oggetto non può cambiare l'attacco in alcun modo.

Dopo aver preso tutte queste decisioni, documentale . Scrivi un "Manuale dei modder" che elenca esattamente quali metodi modificabili ha ogni oggetto, quali parametri prendono, cosa dovrebbero restituire, e così via e ancora e ancora ...

In bocca al lupo!


Il tuo contributo è molto apprezzato e ci hai messo molti sforzi, quindi vale sicuramente un +1, ma mi capita di essere a conoscenza di OOP, in generale (anche se manca di esperienza). I miei problemi attuali riguardano l'approccio progettuale più generale che dovrei adottare. Il mio gioco non è qualcosa di così grande come D&D in scala, tuttavia è MOLTO profondo nella sua meccanica. Ciò significa molto complesso, mescolato a regole di diversi livelli. Che vorrei consentire agli utenti di estendere in modo significativo, non solo modificare leggermente alcuni valori. Può essere non esiste una soluzione più facile, anzi ..
tis

@tis La chiave di tutto ciò è prendere la decisione corretta su quali siano realmente gli oggetti nel tuo modello OO del gioco. Il "ovvio" punto di partenza è con i "nomi" come arma, armatura, ecc. Non è l'unico modo, e può portare a un groviglio di codice non personalizzabile. Se una regola dice "sparate solo ad alcuni mostri con proiettili d'argento in un cimitero a mezzanotte", dove imponete quella regola nel codice? Nella classe Gun (o Bullet), nella classe Monster, nella classe Fighter dell'utente che usa la pistola, nella classe Churchyard o nella classe Time? La migliore risposta potrebbe essere "nessuna delle precedenti" ...
alephzero,

... e ripensare l'intero progetto in termini di una classe di regole (che probabilmente è davvero un database) e una classe di risoluzione dei conflitti. Ora, altre regole come "se non hai proiettili, puoi comunque usare la tua pistola come mazza" e "se Alice lancia un incantesimo che protegge parzialmente (ma non completamente) Bob dalle ferite da proiettile, mentre Charlie sta cercando di sparare a Bob, quindi .... "hanno un unico e" ovvio "posto da implementare nel codice. Potresti scoprire che la tua classe Gun originale ora fa molto poco, tranne per produrre alcuni effetti audiovisivi - e nemmeno quello, se si tratta di un gioco testuale!
alephzero,

1

Un modo semplice per ottenere un supporto di base per questo sarebbe quello di separare la maggior parte dei valori numerici in uno o più file di testo separati per consentire alle persone interessate di modificarli nell'oblio.

Ad esempio, hai menzionato i giochi da tavolo; se avessi un gioco basato su D&D potresti avere un weapon_damagefile contenente righe come Battleaxe: 1d12. Il tuo codice di utilità legge quel file e ogni volta che un danno è stato inflitto da un Battleaxetuo codice lo generate a number from 1-12, 1 time(s)aggiunge e li aggiunge. Ritoccare la riga da leggere Battleaxe: 4d6sarebbe invece generate a number from 1-6, 4 time(s)e aggiungerli. Allo stesso modo, potresti avere una cartella Creaturese al suo interno un file per ogni creatura, incluse linee come AC: 12; quindi l'aggiunta di nuovi file in quella cartella creerebbe nuove creature. Potrebbe anche essere fatto per classi di personaggi, tipi di terreno, un sacco di cose.

Questo stile di personalizzazione senza codice può essere ancora molto potente e coprire molti pezzi del tuo gioco. Tuttavia, ciò in realtà non consente a un utente di apportare modifiche che non hai specificato esplicitamente. Ad esempio, potresti consentire Sneak Attack: [damage]di essere assegnato a qualsiasi Creatura o Classe da aggiungere [damage]a qualsiasi attacco che soddisfi le condizioni per un attacco furtivo. Potresti anche fornire modi per cambiare le condizioni, come "ogni volta che attacchi di nascosto" o "ogni volta che fiancheggi" o "ogni volta che hai un vantaggio". Tuttavia, se un utente decide che desidera che gli attacchi furtivi siano "Quando effettui un tiro per colpire, puoi anche lanciare furtività contro la percezione del bersaglio. Se entrambi i tiri hanno esito positivo, aggiungi il danno dell'attacco furtivo"

Se volevi che un utente fosse in grado di aggiungere un comportamento completamente nuovo al gioco senza bisogno di abilità di programmazione allo stesso livello dello sviluppatore, allora come le persone hanno detto che stai essenzialmente cercando di creare un motore di gioco o un linguaggio di programmazione separato. Per le modifiche che non richiedono conoscenze di codifica, i file di dati basati su testo e le strutture di cartelle possono comunque fornire molte opzioni. Se desideri che gli utenti modifichino più di questo, dovrai chiedere loro di imparare o conoscere un linguaggio di programmazione.


Sì, devo consentire anche loro di aggiungere nuove meccaniche, solo alcune modifiche non lo faranno. Ho anche pensato che potrebbe essere necessario un linguaggio separato, ho pensato che potrebbe essercene già uno che posso usare nel mio codice di utilità Python.
tis

@tis Hai già considerato ciò che Wikipedia ha ancora sull'argomento? en.wikipedia.org/wiki/Logic_programming
ttbek

0

[Sono uno sviluppatore di software decennale, ma senza esperienza di sviluppo di giochi, quindi forse l'industria dei giochi adotta approcci diversi, forse per buoni motivi ...]

Il tuo approccio ha assolutamente senso per me. Il nucleo fornisce le funzionalità di base su cui si basano la meccanica e le regole, quindi è un'API che deve essere utilizzata dai componenti di livello superiore.

E quando si progetta un'API, la mia linea guida preferita è quella di creare il linguaggio in cui si desidera esprimere il proprio codice di livello superiore (ovviamente, tenendo conto dei limiti di sintassi del proprio linguaggio di programmazione).

Quindi, un buon approccio sarebbe quello di scrivere alcune ipotetiche regole e meccaniche nel modo in cui vorresti che fossero espresse (con la sintassi di Python, ovviamente), scoprendo così cosa vuoi che l'API di base fornisca alle regole e alla meccanica strati.

E, naturalmente, consiglierei di dare un'occhiata alle strutture di scripting dei giochi esistenti per avere un'idea di quello che fanno.

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.