Question

J'ai un petit jeu écrit en C#.Il utilise une base de données comme back-end.C'est un jeu de cartes à collectionner, et je voulais implémenter la fonction des cartes comme un script.

Ce que je veux dire, c'est que j'ai essentiellement une interface, ICard, qu'une classe de carte implémente (public class Card056: ICard) et qui contient une fonction appelée par le jeu.

Maintenant, pour rendre la chose maintenable/moddable, j'aimerais avoir la classe de chaque carte comme code source dans la base de données et la compiler essentiellement lors de la première utilisation.Ainsi, lorsque je dois ajouter/modifier une carte, je l'ajoute simplement à la base de données et je dis à mon application de se rafraîchir, sans avoir besoin de déploiement d'assembly (d'autant plus que nous parlerions d'un assembly par carte, ce qui signifie des centaines d'assemblys) .

Est-ce possible?Enregistrez une classe à partir d'un fichier source puis instanciez-la, etc.

ICard Cards[current] = new MyGame.CardLibrary.Card056();
Cards[current].OnEnterPlay(ref currentGameState);

Le langage est C# mais un bonus supplémentaire s'il est possible d'écrire le script dans n'importe quel langage .NET.

Était-ce utile?

La solution

La solution C# Script d'Oleg Shilo (chez The Code Project) est vraiment une excellente introduction à la fourniture de capacités de script dans votre application.

Une approche différente consisterait à envisager un langage spécifiquement conçu pour les scripts, tel que FerRubis, FerPython, ou Lua.

IronPython et IronRuby sont tous deux disponibles aujourd'hui.

Pour un guide sur l'intégration d'IronPython, lisezComment intégrer la prise en charge des scripts IronPython dans votre application existante en 10 étapes simples.

Lua est un langage de script couramment utilisé dans les jeux.Il existe un compilateur Lua pour .NET, disponible sur CodePlex -- http://www.codeplex.com/Nua

Cette base de code est une excellente lecture si vous souhaitez en savoir plus sur la création d'un compilateur dans .NET.

Un angle complètement différent est d'essayer PowerShell.Il existe de nombreux exemples d'intégration de PowerShell dans une application. Voici un projet approfondi sur le sujet :Tunnel PowerShell

Autres conseils

Vous pourrez peut-être utiliser IronRuby pour cela.

Sinon, je vous suggère d'avoir un répertoire dans lequel vous placez les assemblys précompilés.Ensuite, vous pouvez avoir une référence dans la base de données à l'assembly et à la classe, et utiliser la réflexion pour charger les assemblys appropriés au moment de l'exécution.

Si vous souhaitez vraiment compiler au moment de l'exécution, vous pouvez utiliser CodeDOM, puis utiliser la réflexion pour charger l'assembly dynamique. Article de la documentation Microsoft qui pourrait aider.

Si vous ne souhaitez pas utiliser le DLR, vous pouvez utilisez Boo (qui a un interprète) ou vous pourriez envisager le projet Script.NET (S#) sur CodePlex.Avec la solution Boo, vous pouvez choisir entre des scripts compilés ou utiliser l'interpréteur, et Boo est un joli langage de script, possède une syntaxe flexible et un langage extensible via son architecture de compilateur ouverte.Script.NET a également l'air sympa, et vous pouvez facilement étendre ce langage ainsi qu'il s'agit d'un projet open source et utilise un générateur de compilateur très convivial (Ironie.net).

Vous pouvez utiliser n'importe lequel des langages DLR, qui permettent d'héberger très facilement votre propre plate-forme de script.Cependant, vous n’êtes pas obligé d’utiliser un langage de script pour cela.Vous pouvez utiliser C# et le compiler avec le fournisseur de code C#.Tant que vous le chargez dans son propre AppDomain, vous pouvez le charger et le décharger à votre guise.

Je suggérerais d'utiliser Interface Lua car il a entièrement implémenté Lua où il semble que Nua n'est pas complet et n'implémente probablement pas certaines fonctionnalités très utiles (coroutines, etc.).

Si vous souhaitez utiliser certains des modules Lua préemballés externes, je vous suggère d'utiliser quelque chose du type 1.5.x par opposition à la série 2.x qui construit du code entièrement géré et ne peut pas exposer l'API C nécessaire.

J'utilise LuaInterface1.3 + Lua 5.0 pour une application NET 1.1.

Le problème avec Boo est que chaque fois que vous analysez/compilez/évaluez votre code à la volée, il crée un ensemble de classes boo afin que vous obteniez des fuites de mémoire.

Lua, en revanche, ne fait pas ça, donc il est très très stable et fonctionne à merveille (je peux passer des objets de C# à Lua et inversement).

Jusqu'à présent, je ne l'ai pas encore mis en PROD, mais cela semble très prometteur.

J'ai eu des problèmes de fuites de mémoire dans PROD en utilisant LuaInterface + Lua 5.0, j'ai donc utilisé Lua 5.2 et connecté directement en C# avec DllImport. Les fuites de mémoire se trouvaient à l'intérieur de la bibliothèque LuaInterface.

Lua 5.2 :depuis http://luabinaries.sourceforge.net et http://sourceforge.net/projects/luabinaries/files/5.2/Windows%20Libraries/Dynamic/lua-5.2_Win32_dll7_lib.zip/download

Une fois cela fait, toutes mes fuites de mémoire ont disparu et l’application était très stable.

L'application principale vendue par ma division fait quelque chose de très similaire pour fournir des personnalisations aux clients (ce qui signifie que je ne peux publier aucune source).Nous avons une application C# qui charge des scripts VB.NET dynamiques (bien que n'importe quel langage .NET puisse être facilement pris en charge - VB a été choisi parce que l'équipe de personnalisation venait d'un environnement ASP).

En utilisant CodeDom de .NET, nous compilons les scripts de la base de données, en utilisant le VB CodeDomProvider (ce qui est ennuyeux, c'est que la valeur par défaut est .NET 2, si vous souhaitez prendre en charge les fonctionnalités 3.5, vous devez transmettre un dictionnaire avec "CompilerVersion" = "v3.5" à son constructeur).Utilisez le CodeDomProvider.CompileAssemblyFromSource méthode pour le compiler (vous pouvez transmettre des paramètres pour le forcer à se compiler en mémoire uniquement.

Cela entraînerait des centaines d'assemblys en mémoire, mais vous pourriez rassembler le code de tous les classes dynamiques dans un seul assembly et recompiler le tout en cas de changement.Cela présente l'avantage que vous pouvez ajouter un indicateur pour compiler sur le disque avec un BPD lorsque vous testez, vous permettant de déboguer via le code dynamique.

Oui, j'y ai pensé, mais j'ai vite compris qu'un autre langage spécifique au domaine (DSL) serait un peu trop.

Essentiellement, ils doivent interagir avec mon état de jeu de manière éventuellement imprévisible.Par exemple, une carte pourrait avoir une règle "Lorsque cette carte entre en jeu, tous vos serviteurs morts-vivants gagnent +3 en attaque contre les ennemis volants, sauf lorsque l'ennemi est béni".Comme les jeux de cartes à collectionner se déroulent au tour par tour, GameState Manager déclenchera des événements OnStageX et permettra aux cartes de modifier d'autres cartes ou le GameState de la manière dont la carte a besoin.

Si j'essaie de créer un DSL, je dois implémenter un ensemble de fonctionnalités assez important et éventuellement le mettre à jour en permanence, ce qui déplace le travail de maintenance vers une autre partie sans pour autant le supprimer.

C'est pourquoi je voulais rester avec un "vrai" langage .NET pour pouvoir simplement déclencher l'événement et laisser la carte manipuler l'état du jeu de quelque manière que ce soit (dans les limites de la sécurité d'accès au code).

La prochaine version de .NET (5.0 ?) a beaucoup parlé de l'ouverture du "compilateur en tant que service", ce qui rendrait possibles des choses comme l'évaluation directe de scripts.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top