Ist die Implementierung Ihrer eigenen Skriptsprache sinnvoll?

21

Ich programmiere ein verprügeltes Spiel in C ++ und es ist an der Zeit, Skripte für Ereignisse, Auslöser, Zwischensequenzen usw. zu implementieren. Ich habe im Internet herumgelesen und ein paar Informationen erhalten. Meine erste Wahl wäre, meine eigene Skriptsprache wie die in Cave Story zu implementieren . Ich habe diesen Vorschlag gesehen, aber die meisten Leute schlagen lua vor, aber das scheint nicht zu meiner Art der Programmierung zu passen.

Haben Sie eine eigene Skriptsprache erstellt? Warum hast du dich entschieden, dein eigenes zu würfeln, anstatt ein existierendes zu verwenden? Welche Ressourcen haben Sie während der Entwicklung konsultiert?

Skiperic
quelle
43
Meine persönliche Faustregel lautet: Wenn Sie andere Leute fragen müssen, ob es eine gute Idee ist, Ihr eigenes _____ zu würfeln, dann ist es keine gute Idee.
Sam Hocevar
2
Wenn Sie Ihre eigene Sprache implementieren, müssen die Benutzer diese lernen und hoffen, dass Ihr Interpreter keine Fehler enthält, wohingegen Sprachen wie Lua populärer sind und sehr viel seltener Fehler aufweisen.
Nick Caplinger
2
@ NickCaplinger trifft es auf den Kopf. Eigenes Rolling bedeutet, dass es keine Dokumentation, keine Community, keine Tutorials von Drittanbietern, keinen StackExchange usw. gibt. Unabhängig von den geringfügigen Fortschritten bei der Syntax oder der Integration wird dies durch den Mangel an Support aufgewogen, es sei denn, Sie sind ein wirklich bekannter Entwickler Millionen von Fans.
Sean Middleditch
4
Denken Sie auch an die Werkzeuge. Dies ist mein Problem mit D, Rust, Dart usw. Ihre Syntax ist für sich genommen sinnlos. Sie benötigen einen geeigneten Editor, Hervorhebung, "Intellisense" (Code-Vervollständigung), gute Diagnose, Refactoring-Unterstützung, Inline-Dokumentationsunterstützung usw., um wirklich etwas wert zu sein. Ganz zu schweigen von den tatsächlichen Sprachfunktionen, der Integration, der Effizienz und so weiter.
Sean Middleditch
1
Wenn Sie ein C ++ - Programmierer sind und LUA nicht mögen, versuchen Sie stattdessen JavaScript.
Zeel

Antworten:

42

Nein . Zumindest, wahrscheinlich nicht.

Dies ist ein sehr häufiger Fall, in dem das Rad in der Spieleentwicklung neu erfunden wird - ein Fehler, der immer noch sehr beliebt ist.

Wenn Sie diese Frage stellen, werden Sie sehr wahrscheinlich von den Aktivitäten anderer beeinflusst. Schauen Sie sich also an, was Epic Games gerade mit der Unreal Engine gemacht hat:

  • UE3 hatte eine benutzerdefinierte, seltsame, nicht optimierte, schwer zu debuggende UnrealScript-Sache,
  • Wenn das Gerücht wahr ist, wird seine Unterstützung in UE4 zugunsten von hot-reloadbaren C ++ - DLLs entfernt.

Glaubst du, du kannst es besser als Epic?

Das Erstellen von Programmiersprachen gehört den Programmiersprachenentwicklern und nicht den Spielingenieuren .

Es dauert Jahre, bis eine Sprache vollständig ausgereift ist und das zugehörige Toolset (Compiler, Linker, Interpreter, Debugger usw.) verwendet werden kann. Heutzutage haben Sie eine Menge verfügbarer Lösungen zur Hand, sodass es absolut keinen wirklichen Grund gibt, eine neue Sache von Grund auf neu zu beginnen, zumindest nicht, wenn das Ziel einfach darin besteht, ein Spiel zu machen. Zeitraum.

Um Ihre Nebenfragen zu beantworten, nein, aus genau diesen Gründen habe ich noch nie meine eigene Skriptsprache implementiert. Aber ich habe viel mit einigen halbgebackenen gelitten. Weil sie mit einem sehr engen Funktionsumfang erstellt wurden, hatten sie immer diese kleinen verrückten Macken, die dich verrückt machen. Oft verbringst du sehr viel Zeit damit, die Sprachbeschränkungen zu umgehen, anstatt nur dein Spiel zu machen.

Wenn der Grund , warum Sie eine Sprache erstellen möchten, weil sie für die Nutzung durch Personen bestimmt, die nicht wissen , sehr gut programmieren, oder wenn Sie glauben , dass Sie es brauchen , weil Sie etwas sehr domänenspezifische wollen, lassen Sie mich Ihnen sagen , diese sind auch schlechte Gründe. Sie können eine API auf sehr hoher Ebene schreiben, die Funktionen do_what_they_say_and_say_what_they_do()und sehr einfachen Code enthält, der die grundlegende Verwendung offenlegt. Ihre weniger technischen Benutzer werden sich freuen, ein wenig Programmieren zu lernen, und Sie werden sich freuen, nicht von einer schlecht implementierten Sprache eingeschränkt zu werden.

So, wie dies ein wenig abrupt oder auch hart klingen wird, werde ich sagen , dass es ein Fall , in dem es könnte Sinn machen: Wenn Sie erfahren möchten , wie eine Skriptsprache gemacht wird. Aber bitte, bitte, wenn Sie dies tun: Zwingen Sie andere nicht, es zu benutzen.

Bearbeiten

Ich habe mir gerade die Cave Story-Befehlsliste angesehen, die Sie verlinkt haben. Autsch:

<ECJx:y      [EC?] Jump           @ Jump to event Y if any npc with ID X is present

Ich möchte dem Entwickler hinter Cave Story keine Respektlosigkeit zeigen, aber dies ist ein perfektes Beispiel für eine einfache Befehlsliste, die in einer unkontrollierbaren benutzerdefinierten Skriptsprache mutiert ist. Dies mag für einen einzelnen Entwickler oder ein sehr kleines Team noch brauchbar sein, aber zu diesem Zeitpunkt rate ich, auf eine korrekte, vollständige und bewährte Sprache (z. B. Lua) zu wechseln, in der Sie Folgendes tun können:

if (npc.id == x) then
    jump_to_event(y)
end

Dies erleichtert die Arbeit erheblich, wenn Sie beispielsweise eine komplexere Bedingung benötigen:

if (npc.id == x) or (npc.type == "enemy") then
    jump_to_event(y)
end
Laurent Couvidou
quelle
21
+1 "Das Erstellen von Programmiersprachen gehört den Programmiersprachenentwicklern, nicht den Spielingenieuren." Dieses Zitat könnte nicht korrekter sein. Diese Leute haben einen Programmiersprachenkurs besucht, der von einem Mann unterrichtet wurde, der sich mit Programmiersprachen auskennt. Sie sind eine andere Rasse. In einer Klasse wurde mir die Menge an CS-Theorie und Mathematik klar, die für die Erstellung einer echten Programmiersprache erforderlich sind. Das hat mich dazu gebracht, diese Leute und ihre Fähigkeiten noch mehr zu schätzen. Sie lassen mich die Spiele erstellen, ich stehe ihnen aus dem Weg und lassen sie die Sprachen erstellen.
Dean Knight
+1, ich kenne lua oder die benutzerdefinierte Skriptsprache nicht, aber es war offensichtlich genau, was in lua los war und das ist, wo die Benutzerfreundlichkeit wichtig ist
RhysW
1
Es gibt nichts Magisches an dem einen oder anderen, was es unmöglich macht, beides zu lernen. Unreal entfernt vielleicht UnrealScript, aber sie erweitern und ergänzen Kismet erheblich, um eine fähige und vollständige visuelle Skriptsprache zu sein. Sie haben UnrealScript nicht entfernt, weil es ein Fehler ist. Sie entfernen es, weil es durch wesentlich schwierigere Funktionen (Hot-Reload von C ++, aktualisiertes Kismit) veraltet ist. Das heißt nicht, dass ich mit Ihrer Aussage nicht einverstanden bin: Das Schreiben Ihrer eigenen Sprache ist eine enorme Zeitverschwendung, eine Quelle von Fehlern und eine Ursache für große Lernkurven usw.
Sean Middleditch
2
@ott-- Ich habe auch keine Angst, mein Punkt ist, dass das Erweitern dieser Notation es immer komplizierter macht, während die Verwendung einer richtigen Sprache auf lange Sicht helfen wird. Der Aufwand ist im Vergleich zur Benutzerfreundlichkeit in diesem Fall, IMHO, nicht relevant.
Laurent Couvidou
1
Beachten Sie, dass UnrealScript durch Blueprints ersetzt wird (aber ich habe meine Kollegen darauf gewettet, dass es zurück sein wird). Das Hotloading von DLLs ist eine orthogonale Funktion.
Sam Hocevar
9

Haben Sie Ihre eigene Skriptsprache erstellt und warum haben Sie sich entschieden, Ihre eigene zu schreiben, anstatt eine vorhandene zu verwenden?

Ich habe, obwohl ich die Syntax aus anderen Sprachen ausgeliehen habe. Alles in allem war es eine großartige Lernerfahrung und in meinem Fall nicht so schwer, weil die Sprache einfach war.

Ich habe es hauptsächlich gemacht, weil ich für meine Skripte eine reguläre C-Syntax verwenden wollte, da jeder im Team damit vertraut war.

Ich war auch daran interessiert, ein bisschen über das Implementieren von Programmiersprachen zu lernen, und da ich nur eine sehr einfache Untermenge von Funktionen (Variablen, Arithmetik, Bedingungen, Schleifen und Aufrufen von In-Game-Funktionen oder Coroutinen) benötigte, habe ich mich dazu entschlossen, es auszuprobieren.

Welche Ressourcen haben Sie während der Entwicklung konsultiert?

Meine Hauptressource war dieses Buch:

Bildbeschreibung hier eingeben

Aus diesem Buch habe ich genug gelernt, um Folgendes umzusetzen:

  • Ein Lexer: Das war mit regulären Ausdrücken fast trivial, nur mit Regex.Match, um Token zu identifizieren und zu teilen.
  • Ein rekursiver Abstiegsparser: Im Grunde genommen eine Funktion für jede Regel in der Grammatik und einige Hilfsmethoden, um Token vorauszusehen und zu konsumieren. Ich habe mir die C # -Grammatik als Inspiration angesehen. Am schwierigsten war es, sich mit den Prioritäten von Arithmetik- und Beziehungsoperatoren zu befassen, ohne auf eine unendliche Rekursion einzugehen.
  • Ein AST-Interpreter: Unter Verwendung des Besucherdesignmusters durchlief ich den vom Parser generierten Baum und führte jeden Befehlsknoten rekursiv aus.

Ich hätte dort angehalten, da fast alles, was ich brauchte, bereits funktionierte, außer einer Sache - Unity3D-Coroutinen tief aus dem rekursiven Interpreter heraus aufzurufen und nachzugeben. Um dieses Problem zu lösen, musste ich die Rekursion loswerden und mich noch einmal dem Buch zuwenden. Dieses Mal habe ich Folgendes hinzugefügt:

  • Ein Compiler: Ein anderer Besucher, der jedoch keinen Code ausführt, sondern eine Liste kleiner atomarer Anweisungen von jedem Knoten des AST generiert (dh eine einfache stapelbasierte benutzerdefinierte Assemblersprache). Operationen wie eine while-Schleife oder eine if-Bedingung werden in Labels und goto-type-Anweisungen konvertiert. An dieser Stelle schreibe ich auch das kompilierte Skript als Binärdatei auf die Festplatte.
  • Ein Bytecode-Interpreter: iteriert einfach über eine flache Liste von Anweisungen. Ohne die Rekursion war es jetzt einfach, Unity3D-Coroutinen zu integrieren.

Der ganze Prozess hat ungefähr 2 Wochen gedauert und hat sehr viel Spaß gemacht :)

PS: Zum Schluss wollte ich noch Syntaxhervorhebung und Intellisense für meine benutzerdefinierte Sprache in unseren Tools hinzufügen. Scintilla war in dieser Hinsicht ein Lebensretter. Ich habe den folgenden Wrapper verwendet:

http://scintillanet.codeplex.com/

David Gouveia
quelle
5

Ich habe diesen Vorschlag gesehen, aber die meisten Leute schlagen lua vor, aber das scheint nicht zu meiner Art der Programmierung zu passen.

OK, probieren wir das mal aus einem anderen Blickwinkel: Was magst du an Lua nicht? Ist es etwas, das leicht zu reparieren ist, oder ist es etwas Grundlegendes?

Verwenden Sie beispielsweise Schlüsselwörter then/do/end, um Codeblöcke anstelle von geschweiften Klammern im C / C ++ - Stil zu kennzeichnen. Wenn das Ihr Problem ist, können Sie es beheben. Alles, was Sie tun müssen, ist, Ihren eigenen kleinen Lua-Dialekt zu definieren und ein einfaches Transformationstool zu schreiben, das Ihre geschweifte Klammersyntax in tatsächliche Lua umwandelt.

Möchtest du + = in irgendeiner Form? Das können Sie auch problemlos in einem Vorverarbeitungssystem tun. Machen Sie einfach Aussagen des Formulars expr1 += expr2zu expr1 = expr1 + expr2.

Zugegeben, Sie müssen einen Weg finden, um festzustellen, ob ein Paar geschweifte Klammern einen Tisch oder ein do/endPaar darstellt. Und würden Sie haben Ihr Pre-Processing - System in Lua Haken durch zwingende dofile, loadstringund andere Standard - Lua Bibliotheksfunktionen. Aber letztendlich ist alles machbar.

Wenn Sie sich um solche kleinen Probleme kümmern und zu sehr mit einem Programmierstil vertraut sind, um nur die Art und Weise zu ändern, in der Sie programmieren (Hinweis: Dies ist im Allgemeinen eine schreckliche Eigenschaft, die Sie als Programmierer haben müssen), ist dies eine weitaus praktikablere Alternative Schreiben Sie Ihre eigene Sprache. Dies würde höchstens ein paar Wochen dauern . Vergleichen Sie das mit den Jahren , die für eine richtige Sprache mit umfassender Unterstützung für das Debuggen und ähnlichem aufgewendet würden.

Wenn Ihre Probleme größer sind (Globals sind die Standardvorgaben und müssen daher localüberall verwendet werden), können einige davon verwaltet werden (indem Sie einfach neue Globals als Fehler deklarieren, indem Sie geänderte Umgebungen und Metatabellen verwenden). Wenn Sie Funktionen wie erstklassige Objekte, Coroutinen, Garbage Collection oder andere grundlegende Elemente von Lua hassen, dann sind Sie in einer Hölle, die Sie selbst gemacht haben;)

Und wenn Sie wirklich, wirklich hardcore sein wollen, können Sie Ihre eigene Sprache schreiben, die Sie in Lua kompilieren . So können Sie zumindest die sehr gut getestete Lua-Laufzeitumgebung, die außergewöhnliche Lua-API und andere grundlegende Lua-Funktionen in Ihrer! Lua-Sprache nutzen. Dies wird einige Zeit dauern, aber es werden immer noch nicht die Jahre sein , die Sie für etwas anderes ausgeben würden.

Nicol Bolas
quelle
Mir scheint, ich könnte die Funktionen einfach codieren, wenn ich Lua verwenden würde. Es fühlt sich an, als würde ich nur Code verschieben.
Skiperic
1
@skiperic: Ich weiß nicht, was du damit meinst. Kannst du ein Beispiel geben?
Nicol Bolas
Siehe Laurents Antwort oben.
Skiperic
2
@skiperic: Das erklärt nicht wirklich, womit du es zu tun hast. Können Sie in Lua programmieren? Ja. Und das Problem ist ...?
Nicol Bolas
1
@BartekBanachewicz: Selbst wenn man annimmt, dass es sich um eine C-API handelt, ist es vielen C ++ -basierten Skript-APIs, die ich gesehen habe, immer noch überlegen. Es ist die einzige Skript-API, die ich tatsächlich in Erwägung ziehen würde, Raw ohne eine Art automatisierten Binder zu verwenden.
Nicol Bolas
3

Um die anderen Antworten zu ergänzen, ist dies keine rein binäre Option. Innerhalb einer bestehenden Skriptsprache, können Sie auch eigene erstellen Domain-specific_language . Die Vorteile dieses Ansatzes sind:

  • Sie müssen sich nicht mit formalen Grammatiken, Parsern, der Implementierung benutzerdefinierter Editoren usw. herumschlagen.
  • Sie erhalten den größten Nutzen aus der Implementierung einer speziellen Skriptsprache, dh einer zusätzlichen Abstraktion, die für Ihr Spiel spezifisch ist.
  • Homebrew: Benutzer, die mit der Skriptsprache Ihrer Wahl vertraut sind, können Ihr DSL sofort nutzen.
  • Klare Sprache: Benutzer, die mit der Skriptsprache nicht vertraut sind, benötigen lediglich DSL-Kenntnisse, um Ihr Spiel zu modifizieren.

Der Hauptnachteil ist, dass Sie das DSL mit den Einschränkungen Ihrer "Basissprache" entwerfen würden.

mikołak
quelle
2

Es könnte sinnvoll , je nach der Mechanik des Spiels machen. Einige Spiele mit einer ausreichend einfachen Mechanik könnten eine interpretierte Sprache verwenden, um sich vor übermäßig komplizierter Lua / Python-Codierung zu schützen, aber die Komplexitätsersparnis ist möglicherweise nicht allzu viel wert. Beispielsweise könnte eines dieser Interactive Novel-Spiele leicht eine speziell geschriebene Skript-Engine verwenden.

Wenn Ihr Spiel eine Physik-Engine, verschiedene Spielkomponenten und eine unterschiedliche Komplexität von Charakteren und Fähigkeiten umfasst, sollten Sie auf jeden Fall andere vorhandene Skriptsprachen in Betracht ziehen, damit Sie nicht mühsam die erforderlichen Funktionen zu Ihrer benutzerdefinierten hinzufügen oder Fehler beheben müssen es. Während Lua wahrscheinlich die schnellste ist, gibt es viele andere, die Sie aufgrund ihrer Syntax vielleicht mehr mögen, und viele von ihnen geben an, wie einfach sie sich in C. Python, Ruby und Angelscript integrieren lassen. (Fühlen Sie sich frei, andere in den Kommentaren zu erwähnen)

Wenn Sie sicherstellen, dass solche Sprachen nur zur "Logiksteuerung" verwendet werden (dh zur Behandlung eines bestimmten Kollisionsfalls für bestimmte Objekttypen, z. B. wenn der Flammenwerfer einen Eisblock berührt), ist die Leistung kaum ein Problem. Wenn Sie sie andererseits für mehr Routine-Code verwenden (indem Sie einen benutzerdefinierten Kollisionsprüfungsalgorithmus erstellen, der jeden Frame ausführt), ist es wahrscheinlicher, dass Sie ins Stocken geraten.

Katana314
quelle
1
Lua ist auch eine sehr beliebte Skriptsprache in der Spieleentwicklung.
Philipp
Ja, Lua wird überall benutzt, aber der OP merkte, dass er es nicht wirklich mochte. Präferenzen des Codierungsstils können wichtig sein.
Katana314
1
" Zum Beispiel könnte eines dieser Interactive Novel-Spiele leicht eine speziell geschriebene Skript-Engine verwenden. " Inform haben Sie offensichtlich nicht gesehen . Selbst für Textabenteuer macht es keinen Sinn, eine eigene Sprache zu erfinden.
Nicol Bolas
1
@ Katana314: " Vorlieben in Bezug auf den Codierungsstil können wichtig sein. " Ehrlich gesagt, die Welt wäre besser dran, wenn Programmierer von ihren hohen Erwartungen in Bezug auf den " Codierungsstil " absteigen würden. Wir wären alle bessere Programmierer, wenn wir aufhören würden zu glauben, dass <bevorzugte Sprache hier einfügen> grundsätzlich besser ist als die <bevorzugte Sprache hier einfügen> aller anderen. Die Verwendung von Sprachen, denen die Syntax von Builds möglicherweise nicht gefällt, hilft dabei, solche Fehler zu vermeiden.
Nicol Bolas
1

Ich sage, mach schon. In einem Lebenslauf wäre es eine zusätzliche Show der Fähigkeit. Denken Sie jedoch daran, dass Sie diese Fähigkeit zuerst benötigen. Es wird nicht einfach, es wird ziemlich schwer. Es gibt Bücher zu diesem Thema und auch Online-Tutorials, aber letztendlich kommt es darauf an, wie ein Compiler funktioniert und wie Code analysiert und übersetzt wird.

Stellen Sie sicher, dass Sie einfach anfangen, häufig testen und an Ihrem Ideal festhalten. Aber denken Sie immer daran, LUA ist für Sie da.

Wolfgang Skyler
quelle
1
Ich denke, die Frage hier ist, ob das Ziel ist, ein Spiel zu machen oder etwas, das in einem Lebenslauf gut aussieht.
Tridus