Welche Technologie ermöglicht das Programmieren in einem Spiel?

27

Es gibt einige Spiele, in denen der Spieler Skripte im Spiel schreiben / erstellen kann, zum Beispiel: Raumfahrtingenieure oder Psi .

Ich möchte etwas Ähnliches wie eines von beiden verwenden, aber ich hatte Schwierigkeiten, Informationen zu finden, daher lautet meine Frage:

Gibt es einen Zweig der Programmierung, der die Fähigkeit einer einmal kompilierten Software abdeckt, neuen vom Benutzer erstellten Code auszuführen?

Mit Programmierzweig meine ich so etwas wie PTG (Procedural Terrain Generation).

Um zu vermeiden, dass Fragen oder Meinungen zu weit gefasst sind, möchte ich klarstellen, dass ich keine Anleitungen oder Orte zum Lernen suche, sondern den Namen oder die Definition (falls vorhanden) der betreffenden Technologie.

Westside Tony
quelle
22
Na, wahrscheinlich "Dolmetscher schreiben"?
MatthewRock
2
Kürzlich beantwortete ich eine ähnliche Frage , in der ich " Virtual Machine " als Bezeichnung für das System, auf dem der Benutzercode ausgeführt wird, sowie auf den Artikel Game Programming Patterns im Bytecode Pattern verwies, um dies schneller als einen herkömmlichen Interpreter zu implementieren.
DMGregory
3
Es wird normalerweise "Scripting" genannt. Sie finden zahlreiche Materialien zur Implementierung von Skripten in einem Spiel sowie zahlreiche (unterschiedlich) Open-Source-Beispiele und echten Code. Im weiteren Sinne gibt es den gesamten Bereich der Compiler-Programmierung (einschließlich Lexing, Parsen, Kompilieren, Verknüpfen, Interpretieren ...). Im weitesten Sinne (nicht unbedingt nützlich) beinhaltet dies so ziemlich jede Benutzerinteraktion, die Ihre Anwendung hat - eine Skript-Engine ist wirklich nur eine viel komplexere Art, aus einem Menü auszuwählen.
Luaan
2
Ein Python-Programm kann Python-Skripte hosten. Das nennt man Metaprogrammierung. Die meisten interpretierten Sprachen haben das.
user6245072
1
AFAIK In Space Engineers ist der Code C # -Code in einer Sandbox-Umgebung kompiliert (das Spiel wurde als Open Source-Version veröffentlicht, sodass Sie online nachsehen können, wie dies funktioniert: github.com/KeenSoftwareHouse/SpaceEngineers ). Grundsätzlich wird das Spiel mit einem C # -Compiler ausgeliefert, und der Code ermöglicht nur den Zugriff auf die API-Funktionen des Spiels, sodass der Umfang des Programms nur auf Sie beschränkt ist. Und wenn Sie Multiplayer spielen, dann läuft der Code nur auf Ihrem Computer (andere Spieler / der Server sehen nur die Ingame-Konsequenzen)
Florian Castellane

Antworten:

42

Skripte, die in Skripten / eingebetteten / interpretierten Sprachen wie "Lua", "Lisp" oder "AngelScript" ( mehr hier ) geschrieben wurden, können während des Spiels aktualisiert werden [*] und werden dann im laufenden Betrieb interpretiert (= ausgeführt).

Sie können Elemente aus diesen Skripten an Ihre systemeigene kompilierte Codierung (C ++ usw.) binden, damit die Skripten dann die Logik aus Ihrer Anwendung ausführen können. Z.B. Ein spezieller Befehl, den der Benutzer in das Skript eingeben kann. Dadurch wird der Charakter im Spiel um eine bestimmte Distanz in der Spielwelt verschoben.

Einige relevante verknüpfte Fragen:


[*] entweder vom Benutzer als Teil des Spiels oder auch von Entwicklern für schnelle Iterationen / Tests ohne Neustart der Anwendung

Philip Allgaier
quelle
14
Ich wäre vorsichtig, wenn ich etwas "interpretierte Sprache" nennen würde. Bestenfalls ist es ein sehr umstrittener Begriff.
Wondra
1
Computercraft (Minecraft Mod) verwendet LUA als Skriptsprache, um Aufgaben innerhalb des Spiels zu programmieren.
Tikeb
20
Ich verstehe die Aufregung nicht wirklich. Lisp kann sowohl interpretiert als auch kompiliert werden. Wir sind nicht hier, um zu diskutieren, wie man die Sprachen klassifiziert und ob dies interpretedeine gute Unterteilung ist. Wir sagen OP, wer sich dieser Tatsache nicht bewusst ist, dass Sprache nicht kompiliert werden muss, sondern interpretiert werden kann - und wir geben einige Sprachen als Beispiel. Wird Lisp interpretiert? Ja. Ist es kompiliert? Auch ja! Aber das liegt außerhalb des Rahmens. Die Antwort ist möglicherweise falsch formuliert, aber für den Zweck in Ordnung. es drückt OP in die richtige Richtung, und darauf kommt es an. Hier nimm meine +1.
MatthewRock
1
Nun, selbst wenn eine Sprache nur kompiliert werden kann, was hindert Sie daran, eine IDE, einen Compiler und eine Laufzeitumgebung in Ihr Spiel einzubetten? Mit Ausnahme des Budgets.
Ordous
3
@DanielJour Obwohl ich zustimmen würde, dass eine Sprache theoretisch von ihrer Implementierung verschieden sein kann (kompiliert zu Maschinencode vs. kompiliert zu Bytecode für einen VM), ist es dennoch eine sinnvolle, zeitsparende Annahme, dass C kompiliert wird, sofern nicht anders angegeben (und können Sie sich vorstellen) das Aussehen, das Sie erhalten würden, wenn Sie jedes Mal gefragt würden: "Warten Sie, kompilieren Sie C oder interpretieren Sie C?" Für den Zweck des OP muss er sich Sprachen ansehen, die das Dolmetschen unterstützen. ob sie auch kompiliert werden können oder nicht, ist keine Frage, denn so würde er es nicht verwenden.
Blackhawk
12

Eingebettete Sprache ist der richtige Fachbegriff. In der Praxis werden Sprachen, die in anderen Anwendungen (z. B. Spielen) verwendet werden, häufig als Skriptsprachen oder sogar als interpretierte Sprachen bezeichnet, obwohl sie nicht unbedingt interpretiert oder zur Automatisierung von Routineaufgaben verwendet werden sollten. Wenn Sie "Skriptsprachen für Spiele" googeln, erhalten Sie wahrscheinlich nützlichere Ergebnisse als wenn Sie nach "eingebetteten Sprachen" suchen.

interphx
quelle
11

Sie suchen nach einer Möglichkeit, den Code in einige Aktionen zu ändern. Genau das tun Dolmetscher .

Schauen Sie sich Python an. Sie leiten es und bam! Sie landen in REPL ( R ead E val P rint L oop).

Sie definieren eine Funktion "Hallo", die "Hallo Welt" ausgibt. Und da hast du es!

Beachten Sie, dass Sie nichts kompiliert haben. Der Interpreter hat einige magische Aktionen ausgeführt, um Funktionen im laufenden Betrieb (während der Laufzeit) zu erstellen, und jetzt können Sie sie aufrufen.

Gleiches gilt für Spiele. Anstatt eine REPL zu haben, haben Sie ein Spiel mit dem REPL-Modul. Das Spiel startet wahrscheinlich die REPL und führt dann alles andere in dieser REPL aus, sodass Sie Zugriff auf die Daten haben und diese aktiv ändern können.

Wenn Sie mit großen Sprachen wie C ++ arbeiten, sind diese in der Regel weniger dynamisch und werden wahrscheinlich kompiliert. Sie wollen etwas einfacher. Sie erstellen entweder Ihre eigene Sprache oder verwenden eine vorhandene Sprache (wie CoffeScript, Squirrel, Lua, Scheme, ...).

Diese werden häufig als Skriptsprachen bezeichnet , da Sie sie zum Schreiben von Skripten verwenden , die auf der in einer anderen Sprache (z. B. C ++) entwickelten Game Engine basieren.

MatthewRock
quelle
2

Wenn die Programmiersprache im Spiel nur für den Zweck des Spiels entwickelt wurde, handelt es sich um eine domänenspezifische Sprache .

Der Vorteil (und Nachteil) domänenspezifischer Sprachen besteht darin, dass die Sprache selbst die Möglichkeiten des Benutzers einschränken kann (dh Sie können keine Verbindung zum Internet herstellen). Sie könnten eine Sprache entwerfen, die typische Spielaufgaben einfacher macht als in einer Allzwecksprache. Der Nachteil ist, dass der Benutzer eine neue Sprache lernen muss.

Wenn Sie nicht bereinigten Benutzercode in einer universellen Sprache (wie Python oder Perl) in Ihrem Spiel ausführen , kann der Benutzer mit Dingen experimentieren, mit denen er nicht experimentieren sollte. Aber es hängt von deinem Spiel ab. Wenn Sie nichts dagegen haben, dass Benutzer beispielsweise neue Fenster in Ihrem Spiel öffnen oder was auch immer sie möchten, können Sie eine Allzwecksprache verwenden und bestimmten Funktionen Ihrer Spielwelt Bindungen zuweisen.

TheEspinosa
quelle
1

Es gibt zwei Beispiele, die mir auf den ersten Blick einfallen. Beide scheinen genau das zu tun, wonach du fragst.

Das erste ist Kreischen. https://screeps.com/ Wie dieses Ziel erreicht wird, können Sie unter http://support.screeps.com/hc/en-us/articles/205960931-Server-side-architecture-overview nachlesen

Die zweite ist ComputerCraft http://www.computercraft.info/ Sie gehen nicht so detailliert darauf ein, wie es funktioniert, aber ein wenig ist in ihrem Wiki http://www.computercraft.info/wiki/Main_Page zu sehen

Im Wesentlichen führt das Hauptspiel einen Interpreter in einem separaten Thread aus und ermöglicht diesem Thread dann, die Spielwelt durch API-Aufrufe zu manipulieren.

In beiden Beispielen sind Manipulationen durch API-Aufrufe beschränkt, obwohl die Sprache nahezu unbegrenzt ist (nur einige Aufrufe werden aus Sicherheitsgründen blockiert).

Normalerweise ist sehr wenig Arbeit erforderlich, um so etwas in Gang zu setzen. Du brauchst

  • ein Thread-Manager, der die Schleife Ihres Spiels schützt (kein Thread blockiert die Schleife oder verbraucht zu viele Ressourcen). In beiden Beispielen wird ein zeitbasierter Begrenzer verwendet.
  • ein Dolmetscher, um eine Sprache zu führen. LUA ist heutzutage ziemlich verbreitet.
  • Eine Reihe von API-Aufrufen, die die Spielwelt verändern. Was für ein Spaß macht eine Programmiersprache, wenn Sie damit nichts anfangen können.
  • eine Ressourcenmanagement-Implementierung. Mit anderen Worten eine Möglichkeit, Code-Dateien zu speichern und im Spiel zu referenzieren.

Es gibt keinen einzigen Programmzweig, der all diese Probleme löst. Sie benötigen jedoch eine solide Grundlage für Multithreading und allgemeine Kenntnisse über die Funktionsweise eines Dolmetschers.

coteyr
quelle
0

Die kompilierte ausführbare Datei muss einen Parser enthalten , der externen Programmcode lesen kann . Der Programmcode muss nicht wie C oder Python oder xyz aussehen - es kann sich um jede Art von beschreibenden Daten handeln, die für den jeweiligen Zweck geeignet sind. Zum Beispiel Schwedisch oder Morse.

Der externe Programmcode muss eine Syntax haben , damit der Parser sie versteht und sie zeichenweise liest. Die Syntax kann Bezeichner, numerische Werte, Operatoren usw. Beschreiben (und Code kann diese enthalten) .

Der Parser ist fest (kompiliert), funktioniert aber mit flexiblem, externem Code.

Die kompilierte ausführbare Datei muss über eine interne API für die relevante Funktionalität verfügen. damit der Parser Aktionen ausführen kann. Höchstwahrscheinlich muss es auch (bidirektionalen) Zugriff auf die internen Daten der ausführbaren Datei geben, oder der Parser muss eine Art Datenspeicherung und -verwaltung bereitstellen.

Der Parser kann den externen Programmcode beim Start der ausführbaren Datei lesen, oder er kann (Teile davon) ad hoc lesen , oder er kann ihn für jeden Frame erneut lesen (wäre ineffizient), oder der Code kann sogar von Hand eingegeben werden und im Parser gepostet, sobald er fertig ist (wie: "Einheit X 5 Schritte vorwärts bewegen" [Enter]).

Im Wesentlichen ist der externe Code nicht festgelegt - er kann sich zu jedem Jahr, Tag oder jeder Minute ändern, die ausführbare Datei muss jedoch nicht neu kompiliert werden. Nur das resultierende Verhalten, das von der ausführbaren Datei gehostet wird, ändert sich.

Der Text, den Sie gerade lesen, wird (und noch viel mehr, wenn er gesprochen wurde) interpretiert, weil Sie ihn beim Lesen in Ihrem Gehirn "ausführen", ohne zu wissen, was der nächste Satz sagt (oder selbst wenn er sich möglicherweise sofort ändert) jetzt). Im Gegensatz zu Stack Overflow (Pre) kompilieren Sie die gesamte Story in Ihrem Gehirn zu Bytecode, der sie dann ausführt - und ofc dann nicht mehr ändern kann.

Das Phänomen, das noch andauert, ist Interpretation. Das Schreiben von Skripten ist nur der Vorgang des Erstellens einer Beschreibung oder des Schreibens . Alle Computerkodierungen sind Imo-Skripte - wir beschreiben, was passieren soll. Das Wort "Scripting" hat eine etwas verkippte Bedeutung, aber bitte schön. Wir wissen was wir meinen.

Es gibt absolut nichts Außergewöhnliches bei interpretierten Sprachen, und es ist in keiner Weise ein umstrittener Begriff . Eine Vielzahl von ihnen existiert, und einige der ältesten werden interpretiert und nicht kompiliert. In einer interpretierten Sprache könnte man zum Beispiel von Hand schreiben:

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

... und dann 30 ... nein, 45 Minuten Kaffeepause :-). Bei der Rückkehr ist "sock" vorhanden und kann weiter verwendet werden, indem Sie mehr von Hand eingeben oder die Automatisierung des Interpreters fortsetzen.

Sturmwind
quelle
Es gibt ein weit verbreitetes Missverständnis, dass eine interpretierte Sprache langsam sein muss. Es ist nicht wahr. Abhängig von den verschiedenen Faktoren, die diese Diskussion für die Kommentare zu umfangreich machen, kann die interpretierte Sprache eine Größenordnung oder weniger langsam sein, genauso schnell wie oder sogar für einige Operationen schneller als die Kontrollsprache, die als schnell angesehen wird (normalerweise C). Das Beispiel mit Socket würde wahrscheinlich mehr oder weniger wie in C funktionieren, daher ist das Beispiel irreführend. Sie können kompilierte Funktionen in einigen Sprachen auch zur Laufzeit neu definieren, und das Dolmetschen bedeutet nicht einfach, dass Sie immer nur eine Anweisung ausführen müssen.
MatthewRock
Sicher, eine interpretierte Sprache kann auch schneller ausgeführt werden - schließlich wird der Bytecode ausgeführt, und die Ausführung kann je nach der Automatisierung des Interpreters viel besser optimiert werden. Darüber hinaus können einige Interpreter Teile des Codes aus dem Code in Bytecode kompilieren (und ausführen), und zwar ad hoc. Das Beispiel ist nur ein Beispiel für die Freiheit, "jeweils eine Anweisung ausführen". Nun, das ist eine zu große Vereinfachung, vielleicht fügen Sie hinzu "während der zukünftige Code flexibel ist".
Stormwind
Stellen Sie sich "Drehbuch" eher wie ein Drehbuch vor - Sie brauchen immer noch Schauspieler, und diese werden direkt in Bezug auf Biologie und Soziologie definiert, nicht in Bezug auf Theaterwissenschaften (obwohl diese letztendlich auf Biologie und Soziologie basieren), weil diese Sprachen mehr sind geeignet für diesen Zweck, aber nicht die andere :)
Rackandboneman