Qual è la tecnologia che consente la programmazione all'interno di un gioco?


27

Esistono alcuni giochi che consentono al giocatore di scrivere / creare script all'interno del gioco, ad esempio: Space engineer o Psi .

Voglio usare qualcosa di simile a uno dei due, ma ho avuto difficoltà a trovare informazioni, quindi la mia domanda è:

Esiste un ramo della programmazione che copre la capacità di un software una volta compilato di eseguire un nuovo codice creato dall'utente?

Per ramo di programmazione intendo qualcosa come PTG (Procedural Terrain Generation).

Per evitare la base troppo ampia di una domanda o opinione , lasciatemi dire chiaramente che non sto cercando guide o luoghi da imparare, voglio il nome o la definizione (se esiste) della tecnologia coinvolta.


22
Bene, probabilmente "Scrivere interpreti"?
MatthewRock,

2
Di recente ho risposto a una domanda simile , discutendo di " Macchina virtuale " come termine per il sistema che esegue il codice utente e facendo riferimento anche all'articolo Pattern di programmazione di giochi sul Pattern Bytecode come mezzo per implementarlo più velocemente di un interprete convenzionale.
DMGregory

3
Di solito si chiama "scripting". Troverai molti materiali su come implementare gli script in un gioco, oltre a molti esempi (variamente) di codice open source e codice reale. In un ambito più ampio, c'è l'intero campo della programmazione del compilatore (che include lexing, analisi, compilazione, collegamento, interpretazione ...). Nell'ambito più ampio (non necessariamente utile), ciò comporta praticamente qualsiasi interazione dell'utente con la tua applicazione: un motore di scripting è davvero solo un modo molto più complesso di selezionare da un menu.
Luaan,

2
Un programma Python può ospitare script Python. Si chiama metaprogrammazione. Le lingue più interpretate lo hanno.
user6245072,

1
AFAIK in Space Engineers, il codice viene compilato in codice C # in un ambiente sandbox (il gioco è diventato open source, quindi è possibile verificare come funziona online: github.com/KeenSoftwareHouse/SpaceEngineers ). Fondamentalmente il gioco viene fornito con un compilatore C # e il codice consente solo l'accesso alle funzioni API del gioco, in modo che l'ambito del programma sia limitato solo a te. E se stai giocando in multiplayer, il codice viene eseguito solo sulla tua macchina (altri giocatori / il server vedono solo le conseguenze del gioco)
Florian Castellane,

Risposte:


42

Gli script scritti in linguaggi di scripting / incorporati / interpretati come "Lua", "Lisp" o "AngelScript" ( altro qui ) possono essere aggiornati durante il gioco [*] e quindi interpretati (= eseguiti) al volo.

È possibile associare elementi da tali script alla codifica compilata nativa (C ++, ecc.) In modo che gli script possano quindi eseguire la logica dall'applicazione. Per esempio. un comando specifico che l'utente può inserire nello script, di conseguenza sposta il personaggio in gioco di una determinata distanza nel mondo di gioco.

Alcune domande collegate rilevanti:


[*] o dall'utente durante il gioco o anche dagli sviluppatori per iterazione / test rapidi senza riavviare l'applicazione


14
Starei attento quando chiamo qualcosa "linguaggio interpretato". Nella migliore delle ipotesi è un termine molto discutibile.
Wondra,

1
Computercraft (mod di Minecraft) utilizza LUA come linguaggio di scripting per programmare le attività all'interno del gioco.
Tikeb,

20
Non capisco davvero il clamore. Lisp può essere sia interpretato che compilato. Non siamo qui per scoprire come classificare le lingue e se interpretedsia una buona clasificazione; stiamo dicendo a OP che non è a conoscenza di questo fatto che la lingua non ha bisogno di essere compilata, ma può essere interpretata - e diamo alcune lingue come esempio. Lisp è interpretato? Sì. È compilato? Anche sì! Ma questo è al di fuori dell'ambito. La risposta potrebbe non essere accurata con le parole, ma va bene allo scopo; spinge OP nella giusta direzione, ed è quello che conta. Ecco, prendi il mio +1.
Matthew Rock

1
Bene, anche se una lingua è solo di compilazione, cosa ti impedisce di incorporare un IDE, un compilatore e un runtime nel tuo gioco? Tranne il budget, cioè.
Ordous,

3
@DanielJour Anche se concordo sul fatto che teoricamente un linguaggio può essere distinto dalla sua implementazione (compilato in codice macchina vs compilato in bytecode per un vm), è ancora un'ipotesi utilmente che fa risparmiare tempo che C sia compilato se non diversamente specificato (e puoi immaginare l'aspetto che otterresti se ti chiedessi "aspettare, compilare C o interpretare C?" ogni volta). Ai fini del PO, ha bisogno di esaminare le lingue che supportano l'interpretazione; il fatto che possano o meno essere compilati non è un problema perché non è così che lo userebbe.
Blackhawk,

12

Il linguaggio incorporato è il termine tecnico appropriato. In pratica, le lingue utilizzate all'interno di altre applicazioni (come i giochi) vengono spesso definite come script o addirittura lingue interpretate , sebbene non debbano necessariamente essere interpretate o utilizzate per automatizzare le attività di routine. Googling "linguaggi di scripting per giochi" probabilmente produrrebbe risultati più utili della ricerca di "linguaggi incorporati".


11

Stai cercando un modo per cambiare il codice in alcune azioni. Questo è esattamente ciò che stanno facendo gli interpreti .

Dai un'occhiata a Python. Lo esegui e bam! Si terra in REPL ( R ead E val P tampa L oop).

Definisci una funzione "ciao" che stampa "Ciao, mondo". E il gioco è fatto!

Nota che non hai compilato nulla; l'interprete ha fatto un po 'di magia per creare la funzione al volo (durante il runtime) e ora puoi chiamarla.

Lo stesso vale per i giochi. Invece di avere un REPL, hai un gioco con il modulo REPL. Il gioco avvia probabilmente il REPL e quindi esegue tutto il resto in questo REPL, quindi hai accesso ai dati e puoi modificarlo attivamente.

Se stai lavorando con linguaggi enormi come il C ++, tendono ad essere meno dinamici e probabilmente compilati. Ne vuoi un po 'più facile. Puoi creare la tua lingua o utilizzare alcuni esistenti (come CoffeScript, Squirrel, Lua, Scheme, ...)

Questi sono spesso chiamati linguaggi di scripting , poiché li usi per scrivere script basati sul motore di gioco sviluppato in un'altra lingua (ad es. C ++).


2

Se il linguaggio di programmazione in-game è stato progettato solo per lo scopo del gioco, allora è un linguaggio specifico del dominio .

Il vantaggio (e lo svantaggio) delle lingue specifiche del dominio è che la lingua stessa può limitare ciò che l'utente può fare (cioè è possibile impedire la connessione a Internet). È possibile progettare un linguaggio che renda le attività di gioco tipiche più semplici che in un linguaggio di uso generale. Lo svantaggio è che l'utente deve imparare una nuova lingua.

Eseguendo un codice utente non autenticato in un linguaggio generico (come Python o Perl) all'interno del tuo gioco, potresti consentire all'utente di fare confusione con cose che non dovrebbe fare. Ma dipende dal tuo gioco. Se non ti dispiace che gli utenti facciano cose come aprire nuove finestre all'interno del tuo gioco o quello che vogliono, puoi usare un linguaggio generico ed esporre i vincoli a determinate caratteristiche del tuo mondo di gioco.


1

Ci sono due esempi che mi vengono in mente dalla cima della mia testa. Entrambi sembrano fare esattamente quello che stai chiedendo.

Il primo è screeps. https://screeps.com/ Puoi leggere molto su come raggiunge questo obiettivo su http://support.screeps.com/hc/en-us/articles/205960931-Server-side-architecture-overview

Il secondo è ComputerCraft http://www.computercraft.info/ Non entrano nei dettagli di come funziona, ma un po 'può essere visto sul loro wiki http://www.computercraft.info/wiki/Main_Page

In sostanza, il gioco principale esegue un interprete in un thread separato, quindi consente a quel thread di manipolare il mondo di gioco tramite chiamate API.

In entrambi gli esempi, mentre la lingua è quasi illimitata (solo alcune chiamate bloccate per motivi di sicurezza) le manipolazioni sono limitate dalle chiamate API che possono essere effettuate.

Di solito è necessario pochissimo lavoro per avviare qualcosa di simile. Hai bisogno

  • un gestore di thread che protegge il loop del tuo gioco (non consente a un thread di bloccare il loop o consumare molte risorse). Entrambi gli esempi usano un limitatore basato sul tempo.
  • un interprete per eseguire una lingua. LUA è abbastanza comune in questi giorni.
  • un insieme di chiamate API che modificano il mondo di gioco. Che divertimento è un linguaggio di programmazione se non puoi farci niente.
  • un'implementazione della gestione delle risorse. In altre parole, un modo per memorizzare i file di codice e fare riferimento a loro nel gioco.

Non esiste un singolo ramo della programmazione che gestisca tutte queste preoccupazioni. Ma avrai bisogno di solide basi nel multi-threading e una conoscenza generale di come funziona un interprete.


0

L'eseguibile compilato deve contenere un parser in grado di leggere il codice di programma esterno . Il codice del programma non deve necessariamente apparire come C o Python o xyz: può essere qualsiasi tipo di dato descrittivo adatto allo scopo in questione. Ad esempio svedese o morse.

Il codice del programma esterno deve avere una sintassi , in modo che il parser lo capisca mentre lo legge carattere per carattere. La sintassi può descrivere (e il codice può contenere) identificatori, valori numerici, operatori ecc .

Il parser è fisso (compilato) ma funziona su un codice esterno flessibile.

L'eseguibile compilato deve avere un'API interna per la relativa funzionalità. in modo che il parser possa eseguire azioni. Molto probabilmente ci deve essere anche un accesso (bidirezionale) ai dati interni dell'eseguibile, oppure il parser deve fornire un qualche tipo di archiviazione e pulizia dei dati.

Il parser può leggere il codice del programma esterno all'avvio dell'eseguibile , oppure può leggerlo (parti di esso) ad hoc , oppure può rileggerlo per ogni frame (sarebbe inefficiente), oppure il codice può anche essere digitato a mano e inviato al parser mentre si prepara (come: "sposta l'unità X in avanti di 5 passi" [invio]).

In sostanza, il codice esterno non è fisso : può cambiare in qualsiasi anno, giorno o minuto, ma non è ancora necessario ricompilare l'eseguibile. Solo il comportamento risultante, ospitato dall'eseguibile, cambia.

Il testo che stai leggendo in questo momento è ( in un certo senso , e ancora di più se fosse pronunciato) interpretato perché lo "esegui" nel tuo cervello mentre lo leggi, senza sapere cosa dice la frase successiva (o anche se eventualmente, subdolamente cambia giusto adesso). Al contrario di Stack Overflow (pre) compilando l'intera storia in bytecode nel tuo cervello, che poi la esegue - e spesso non potrebbe più cambiare.

Il fenomeno in corso è l'interpretazione. Lo scripting è solo l'atto di creare un deSCRIPTion o scrivere . Tutta la codifica del computer è imo scripting: descriviamo ciò che vogliamo che accada. La parola "scripting" ha un significato leggermente inclinato, ma va bene. Sappiamo cosa intendiamo.

Non c'è assolutamente nulla di straordinario nelle lingue interpretate, e non è in alcun modo un termine discutibile . Ne esiste una moltitudine, e alcune delle più antiche vengono interpretate anziché compilate. In una lingua interpretata si potrebbe ad esempio digitare a mano:

sock = Socket.New (AddressFamily.InterNetwork, SocketType.Stream ProtocolType.Tcp) [INVIO]

... e poi fare una pausa caffè di 30 ... no, 45 minuti :-). Al ritorno, "calzino" esiste ed è pronto per un ulteriore utilizzo digitando più a mano o lasciando che l'automazione dell'interprete continui con esso.


C'è un malinteso comune sul fatto che un linguaggio interpretato debba essere lento. Non è vero. A seconda dei vari fattori che rendono questa discussione troppo ampia per i commenti, il linguaggio interpretato può essere di una grandezza o meno lento, più veloce o addirittura per alcune operazioni più veloce del controllo del linguaggio che è considerato veloce (di solito C). L'esempio con socket probabilmente funzionerebbe più o meno come in C, quindi l'esempio è fuorviante. È inoltre possibile ridefinire le funzioni compilate in fase di esecuzione in alcune lingue e interpretare non significa semplicemente "seguire un'istruzione alla volta".
MatthewRock,

Certo, anche un linguaggio interpretato può funzionare più velocemente - dopo tutto è il bytecode che viene eseguito e l'esecuzione può essere ottimizzata molto meglio, a seconda dell'automazione dell'interprete. Inoltre, alcuni interpreti possono compilare, da codice, parti del codice in bytecode (ed eseguire), ad hoc L'esempio è solo un esempio della libertà, "Andare a un'istruzione alla volta"? Beh, questa è una semplificazione eccessiva, forse aggiungere "mentre il codice futuro è flessibile".
Stormwind,

Pensa alla "sceneggiatura" più come a una sceneggiatura cinematografica: hai ancora bisogno di attori, e questi sono definiti direttamente in termini di biologia e sociologia, non di scienze del teatro (anche se questi alla fine si basano su biologia e sociologia), perché questi linguaggi sono più adatto a tale scopo ma non all'altro :)
rackandboneman,
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.