L'implémentation de votre propre langage de script est-elle viable?

21

Je suis en train de coder un jeu beat 'em up en C ++ et le moment est venu d'implémenter des scripts pour les événements, les déclencheurs, les cinématiques, etc. J'ai lu sur Internet et j'ai obtenu pas mal d'informations. Ma solution de premier choix serait d'implémenter mon propre langage de script comme celui de Cave Story . J'ai vu cela suggéré mais la plupart des gens suggèrent lua mais cela ne semble pas correspondre à mon type de programmation.

Avez-vous créé votre propre langage de script? Pourquoi avez-vous choisi de rouler le vôtre au lieu d'en utiliser un déjà existant? Quelles ressources avez-vous consultées pendant le développement?

skiperic
la source
43
Ma règle d'or personnelle est la suivante: si vous devez demander à d'autres personnes si c'est une bonne idée de lancer votre propre _____, alors ce n'est pas une bonne idée.
sam hocevar
2
Notez que si vous implémentez votre propre langue, les gens doivent l'apprendre et espérer qu'il n'y a pas de bogues dans votre interprète, alors que les langues comme Lua sont plus populaires et beaucoup moins susceptibles d'avoir des bogues.
Nick Caplinger
2
@NickCaplinger le frappe sur la tête. Rouler vous-même signifie qu'il n'y a pas de documentation, pas de communauté, pas de tutoriels tiers, pas de StackExchange, etc. Quelles que soient les avancées mineures que vous obtenez dans la syntaxe ou l'intégration seront compensées par le manque de support, sauf si vous êtes un développeur très connu avec des millions de fans.
Sean Middleditch
4
Gardez également à l'esprit l'outillage. C'est mon problème avec D, Rust, Dart, etc. Votre syntaxe est inutile en elle-même. Vous avez besoin d'un éditeur approprié, de la mise en évidence, de "Intellisense" (complétion de code), de bons diagnostics, d'un support de refactoring, d'un support de documentation en ligne, etc. pour vraiment valoir quoi que ce soit. Sans parler de toutes les fonctionnalités du langage, de l'intégration, de l'efficacité, etc.
Sean Middleditch
1
Si vous êtes un programmeur C ++ et que vous n'aimez pas LUA, essayez plutôt JavaScript.
zeel

Réponses:

42

Non , du moins, probablement pas.

Il s'agit d'un cas très fréquent de réinventer la roue est le développement de jeux, une erreur qui est encore assez populaire.

Si vous posez cette question, vous êtes très susceptible d'être influencé par ce que font les autres, alors regardez simplement ce qu'Epic Games vient de faire avec le moteur Unreal:

  • UE3 avait un truc UnrealScript personnalisé, bizarre, non optimisé et difficile à déboguer,
  • Si la rumeur est vraie, son support est supprimé dans UE4 , au profit des DLL C ++ rechargeables à chaud.

Pensez-vous que vous pouvez faire mieux qu'Epic?

La création de langages de programmation appartient aux créateurs de langages de programmation , pas aux ingénieurs de jeux.

Il faut des années et des années pour qu'une langue atteigne sa pleine maturité, et l'ensemble d'outils qui l'accompagne (compilateur, éditeur de liens, interprète, débogueur ..) est utilisable. De nos jours, vous avez beaucoup de solutions disponibles à portée de main, donc il n'y a absolument aucune vraie raison de commencer une nouvelle chose à partir de zéro, du moins pas si le but est simplement de faire un jeu. Période.

Pour répondre à vos questions secondaires, non, pour ces mêmes raisons, je n'ai jamais implémenté mon propre langage de script. Mais j'ai beaucoup souffert avec certains à moitié cuits. Parce qu'ils ont été créés avec une fonctionnalité très étroite à l'esprit, ils ont toujours eu ces petites bizarreries folles qui vous rendent fou. Souvent, vous vous retrouverez à passer énormément de temps à essayer de contourner les limites du langage au lieu de simplement créer votre jeu.

Si la raison pour laquelle vous voulez créer un langage est parce qu'il est destiné à être utilisé par des personnes qui ne connaissent pas très bien la programmation, ou si vous pensez en avoir besoin parce que vous voulez quelque chose de très spécifique au domaine, permettez-moi de vous dire que ce sont également mauvaises raisons. Vous pouvez écrire une API de très haut niveau avec des fonctions qui do_what_they_say_and_say_what_they_do(), et du code passe-partout très simple qui expose son utilisation de base. Vos utilisateurs peu techniques seront heureux d'apprendre un peu de programmation et vous serez heureux de ne pas être limités par un langage mal implémenté.

Donc, comme cela peut sembler un peu brusque ou même dur, je dirai qu'il y a un cas où cela pourrait avoir un sens: si vous voulez apprendre comment un langage de script est fait. Mais s'il vous plaît, s'il vous plaît, ne forcez pas les autres à l'utiliser.

modifier

Je viens de jeter un œil à la liste de commandes Cave Story que vous avez liée. Aie:

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

Je ne veux pas manquer de respect au développeur derrière Cave Story, mais ceci est un exemple parfait d'une liste de commandes simple qui a muté dans un langage de script personnalisé incontrôlable. Cela peut être encore utilisable pour un seul développeur ou une très petite équipe, mais à ce stade, je vous conseille de passer à un langage Turing complet et bien testé (par exemple Lua), où vous pourriez faire:

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

Cela rendra les choses beaucoup plus faciles lorsque, par exemple, vous aurez besoin d'une condition plus complexe:

if (npc.id == x) or (npc.type == "enemy") then
    jump_to_event(y)
end
Laurent Couvidou
la source
21
+1 "La création de langages de programmation appartient aux créateurs de langages de programmation, pas aux ingénieurs de jeux." Cette citation ne pourrait pas être plus correcte. Ayant suivi un cours de concepts de langage de programmation enseigné par un gars qui était un génie des langages de programmation, ces gens sont d'une race différente. Une classe m'a fait réaliser la quantité de théorie et de mathématiques CS qui entrent dans la création d'un vrai langage de programmation. Cela m'a fait apprécier encore plus ces personnes et leurs compétences. Ils me laissent créer les jeux, je reste en dehors de leur chemin et les laisse créer les langages.
Dean Knight
+1, je ne connais pas lua ou le langage de script personnalisé, mais il était évident de savoir exactement ce qui se passait dans lua et c'est là que la convivialité est importante
RhysW
1
L'un ou l'autre n'a rien de magique qui rend impossible l'apprentissage des deux. Unreal supprime peut-être UnrealScript, mais ils améliorent et remplissent considérablement Kismet pour être un langage de script visuel capable et complet. Ils n'ont pas supprimé UnrealScript parce que c'est un échec, ils le suppriment parce qu'il est dépassé par des fonctionnalités beaucoup plus difficiles (rechargement à chaud C ++, mise à jour de Kismit). Ne prenez pas cela pour dire que je ne suis pas d'accord avec votre argument: écrire votre propre langue est une énorme perte de temps, une source de bugs et une cause de grandes courbes d'apprentissage, etc.
Sean Middleditch
2
@ ott-- Je n'ai pas peur non plus, mon point est que l'extension de cette notation la rendra de plus en plus compliquée, alors que l'utilisation d'un langage approprié en premier lieu aidera à long terme. Les frais généraux ne sont pas pertinents par rapport à la facilité d'utilisation dans ce cas, à mon humble avis.
Laurent Couvidou
1
Notez que UnrealScript est remplacé par Blueprints (mais j'ai parié mes collègues qu'il sera de retour). Les DLL de chargement à chaud sont une fonctionnalité orthogonale.
sam hocevar
9

Avez-vous créé votre propre langage de script et pourquoi avez-vous choisi de rouler le vôtre au lieu d'en utiliser un déjà existant?

Je l'ai, même si j'ai emprunté la syntaxe à d'autres langues. Dans l'ensemble, ce fut une excellente expérience d'apprentissage et dans mon cas, pas si difficile parce que la langue était simple.

Je l'ai fait principalement parce que je voulais utiliser une syntaxe régulière de style C pour mes scripts, car tout le monde dans l'équipe la connaissait.

J'étais également intéressé à en apprendre un peu plus sur la mise en œuvre de langages de programmation, et comme je n'avais besoin que d'un sous-ensemble très simple de fonctionnalités (variables, arithmétique, conditions, boucles et appeler des fonctions ou des coroutines dans le jeu), j'ai décidé de l'essayer.

Quelles ressources avez-vous consultées pendant le développement?

Ma principale ressource était ce livre:

entrez la description de l'image ici

J'ai réussi à apprendre suffisamment de ce livre pour implémenter:

  • Un lexer: qui était presque trivial en utilisant des expressions régulières, en utilisant simplement Regex.Match pour identifier et diviser les jetons.
  • Un analyseur de descente récursif: fondamentalement, une fonction pour chaque règle de la grammaire et quelques méthodes d'assistance pour rechercher et consommer des jetons. J'ai regardé la spécification de grammaire C # pour l'inspiration. La partie la plus difficile a été de traiter les priorités arithmétiques et des relations entre opérateurs sans entrer dans une récursion infinie.
  • Un interpréteur AST: en utilisant le modèle de conception des visiteurs, j'ai parcouru l'arbre généré à partir de l'analyseur et exécuté chaque nœud d'instruction de manière récursive.

Je me serais arrêté là car presque tout ce dont j'avais besoin fonctionnait déjà, sauf une chose - appeler et céder sur les coroutines Unity3D profondément depuis l'intérieur de l'interpréteur récursif. Afin de résoudre ce problème, j'ai dû me débarrasser de la récursivité et je me suis de nouveau tourné vers le livre. Cette fois, j'ai fini par ajouter:

  • Un compilateur: un autre visiteur, mais au lieu d'exécuter du code, il génère une liste de petites instructions atomiques à partir de chaque nœud de l'AST (c'est-à-dire un simple langage d'assemblage personnalisé basé sur la pile). Les opérations comme une boucle while ou une condition if sont converties en étiquettes et en instructions de type goto. À ce stade, j'écris également le script compilé sur le disque sous forme de fichier binaire.
  • Un interpréteur de bytecode: itère simplement sur une liste plate d'instructions. Sans la récursivité, il était désormais facile de s'intégrer aux coroutines Unity3D.

L'ensemble du processus a pris environ 2 semaines sans aucune connaissance et a été très amusant :)

PS: À la fin, je voulais également ajouter la coloration syntaxique et l'intellisense pour mon langage personnalisé sur nos outils. Scintilla a sauvé la vie à cet égard. J'ai utilisé le wrapper suivant:

http://scintillanet.codeplex.com/

David Gouveia
la source
5

J'ai vu cela suggéré mais la plupart des gens suggèrent lua mais cela ne semble pas correspondre à mon type de programmation.

OK, essayons ceci sous un angle différent: qu'est-ce que tu n'aimes pas chez Lua? Est-ce quelque chose qui est facilement réparable, ou est-ce quelque chose de fondamental?

Par exemple, prenez l'utilisation de mots clés tels que then/do/endpour désigner un bloc de code plutôt que de bons accolades de style C / C ++. Si c'est votre problème ... c'est quelque chose que vous pouvez résoudre. Tout ce que vous avez à faire est de définir votre propre petit dialecte de Lua et d'écrire un outil de transformation simple qui convertira votre syntaxe d'accolade en Lua réel.

Voulez-vous + = sous une forme ou une autre? C'est aussi facilement quelque chose que vous pouvez faire dans un système de prétraitement. Transformez simplement les déclarations du formulaire expr1 += expr2en expr1 = expr1 + expr2.

Certes, vous devrez trouver un moyen de détecter si une paire d'accolades représente une table ou une do/endpaire. Et vous devez brancher votre système de pré-traitement en Lua par prépondérants dofile, loadstringet d' autres fonctions de la bibliothèque standard de Lua. Mais tout est finalement réalisable.

Si de petits problèmes comme celui-ci vous préoccupent et que vous êtes trop attaché à un style de programmation pour changer simplement la façon dont vous codez (remarque: c'est généralement une qualité terrible à avoir en tant que programmeur), c'est une alternative beaucoup plus viable que simplement écrire votre propre langue. Cela prendrait peut-être quelques semaines tout au plus . Comparez cela aux années qui seraient consacrées à un langage approprié, avec un support de débogage riche, etc.

Si vos problèmes sont plus importants que cela (les globaux étant la valeur par défaut, vous obligeant ainsi à l'utiliser localpartout), certains d'entre eux peuvent être gérés (faites simplement de la déclaration de nouveau global une erreur, en utilisant des environnements et des métatables modifiés). Si vous détestez les fonctions comme objets de première classe, coroutines, garbage collection ou autres éléments de base de Lua ... eh bien, vous êtes dans un enfer de votre propre fabrication;)

Et si vous voulez vraiment, vraiment être hardcore à ce sujet, vous pouvez écrire votre propre langue que vous compilez dans Lua. Ainsi, vous pourrez au moins tirer parti du runtime Lua très bien testé, de l'API Lua exceptionnelle et d'autres fonctionnalités de base de Lua, le tout à partir de votre langue! Lua. Cela prendra du temps, mais ce ne seront toujours pas les années que vous consacrerez à autre chose.

Nicol Bolas
la source
Pour moi, il semble que je pourrais simplement coder les fonctions si je devais utiliser Lua. J'ai l'impression de déplacer du code.
skiperic
1
@skiperic: Je ne sais pas ce que tu veux dire par là. Pouvez-vous donner un exemple?
Nicol Bolas
Voir la réponse de Laurent ci-dessus.
skiperic
2
@skiperic: Cela n'explique pas vraiment ce qui vous préoccupe. Pouvez-vous coder en Lua? Oui. Et le problème est ...?
Nicol Bolas
1
@BartekBanachewicz: Même en acceptant qu'il s'agit d'une API C, elle est toujours supérieure à de nombreuses API de script basées sur C ++ que j'ai vues. C'est la seule API de script que j'envisagerais d'utiliser raw , sans aucun classeur automatisé.
Nicol Bolas
3

Pour compléter les autres réponses, ce n'est pas une option strictement binaire. Dans un langage de script existant, vous pouvez également créer votre propre langage spécifique au domaine . Les avantages de cette approche sont:

  • Vous n'avez pas vraiment à vous soucier des grammaires formelles, des analyseurs, à implémenter des éditeurs personnalisés, etc.
  • Vous tirez le meilleur parti de l'implémentation d'un langage de script spécialisé, c'est-à-dire une abstraction supplémentaire, spécifique à votre jeu.
  • vs homebrew: les utilisateurs qui connaissent le langage de script de votre choix pourront immédiatement utiliser votre DSL.
  • par rapport à un langage simple: les utilisateurs qui ne connaissent pas le langage de script n'auront besoin que de la connaissance de la DSL pour modifier votre jeu.

Le principal inconvénient est que vous seriez en train de concevoir la DSL avec les contraintes de votre langue "de base".

mikołak
la source
2

Cela peut avoir du sens selon la mécanique de votre jeu. Certains jeux avec une mécanique assez simple pourraient utiliser un langage interprété pour se sauver d'un codage Lua / Python trop compliqué, mais les économies de complexité pourraient ne pas valoir trop. Par exemple, l'un de ces jeux de roman interactif pourrait facilement utiliser un moteur de script personnalisé.

Si votre jeu implique un moteur physique, divers composants du jeu et une complexité variable des personnages et des capacités, vous devriez certainement envisager de regarder d'autres langages de script existants, afin de ne pas vous efforcer d'ajouter des fonctionnalités nécessaires à votre langage personnalisé ou de corriger des bogues avec il. Bien que Lua soit probablement le plus rapide, il y en a beaucoup d'autres qui pourraient vous plaire davantage pour leur syntaxe, et beaucoup d'entre eux se vantent de la facilité avec laquelle ils s'intègrent à C. Python, Ruby et Angelscript en sont quelques-uns. (N'hésitez pas à en mentionner d'autres dans les commentaires)

Si vous vous assurez que ces langages ne sont utilisés que pour le "contrôle logique" (c'est-à-dire la gestion d'un cas de collision spécifique pour certains types d'objets, comme le lance-flammes touchant un bloc de glace), les performances ne seront presque jamais un problème. Bien sûr, d'un autre côté, si vous les utilisez pour du code plus routinier (en créant un algorithme de vérification des collisions personnalisé qui exécute chaque trame), il est plus probable que cela vous gêne.

Katana314
la source
1
Lua est également un langage de script très populaire dans le développement de jeux.
Philipp
Ouaip, Lua est utilisé partout, mais l'OP a noté qu'il n'aimait pas vraiment ça. Les préférences de style de codage peuvent être importantes.
Katana314
1
" Par exemple, l'un de ces jeux de roman interactif pourrait facilement utiliser un moteur de script personnalisé. " Vous n'avez évidemment pas vu Inform . Vraiment, même pour les aventures textuelles, il est inutile de créer votre propre langue.
Nicol Bolas
1
@ Katana314: "Les préférences de style de codage peuvent être importantes. " Honnêtement, le monde serait mieux si les programmeurs se débarrassaient de leurs grands chevaux sur le "style de codage". Nous serions tous de meilleurs programmeurs si nous arrêtions de penser que <insérer la langue préférée ici> était fondamentalement meilleur que <insérer la langue préférée ici>. Utiliser des langages que vous n'aimez peut-être pas la syntaxe des caractères de builds et permet d'éviter ce genre de bug.
Nicol Bolas
1

Je dis, allez-y. Sur un CV, ce serait une démonstration supplémentaire de capacité. Cependant, gardez à l'esprit que vous avez d'abord besoin de cette capacité. Ça ne va pas être facile, ça va être assez dur. Il y a des livres sur le sujet et des tutoriels en ligne aussi, mais ultimement, cela dépendra de vous et de votre compréhension du fonctionnement d'un compilateur et de la façon dont le code est analysé et traduit.

Assurez-vous de commencer simplement, testez fréquemment et maintenez votre idéal. Mais souvenez-vous toujours, LUA est là pour vous.

Wolfgang Skyler
la source
1
Je suppose que la question ici est de savoir si l'objectif est de créer un jeu ou de créer quelque chose qui a l'air bien sur un CV.
Tridus