2008-08-01 11 views
61

que tiene un pequeño juego escrito en C#. Utiliza una base de datos como back-end. Es un trading card game, y quería implementar la función de las tarjetas como una secuencia de comandos.Adición de funcionalidad de scripting para aplicaciones .NET

Lo que quiero decir es que, esencialmente, tengo una interfaz, ICard, que implementa una clase de tarjeta (public class Card056 : ICard) y que contiene funciones que son llamadas por el juego.

Ahora, para hacer la cosa mantenible/modificable, me gustaría tener la clase para cada tarjeta como código fuente en la base de datos y, esencialmente, compilarlo en el primer uso. Así que cuando tengo que añadir/cambiar una tarjeta, sólo voy a añadir a la base de datos y decirle a mi solicitud para actualizar, sin necesidad de ningún despliegue de montaje (especialmente ya que estaríamos hablando de montaje 1 por tarjeta que significa cientos de asambleas) .

¿Es posible? Registrar una clase a partir de un archivo de origen y luego instanciarlo, etc.

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

El lenguaje es C#, pero bono extra si es posible escribir el guión en cualquier lenguaje .NET.

+1

Eso es gracioso, yo y un amigo estábamos pensando en escribir un juego de cartas coleccionables en C# hace un tiempo, ¿no crees que todavía tienes la fuente para esto? Interesado en cómo te acercaste a esto. – mattytommo

+0

@mattytommo No, no me queda nada, estaba en las primeras etapas y básicamente funcionaba como lo describí anteriormente. Hoy en día, buscaría en Roslyn para hacer la compilación de C#: http://blogs.msdn.com/b/csharpfaq/archive/2011/10/19/introducing-the-microsoft-roslyn-ctp.aspx - Alternativamente, el uso de JavaScript Jint - http://jint.codeplex.com/ –

+0

ah gracias, pero estaba buscando más la implementación del juego de cartas coleccionables en sí y la estructura que habías usado, a diferencia del motor de scripting. Gracias de todos modos :) – mattytommo

Respuesta

36

Oleg Shilo's C# Script solution (at The Code Project) realmente es una gran introducción a proporcionar capacidades de secuencias de comandos en su aplicación.

Un enfoque diferente sería considerar un lenguaje específicamente creado para scripting, como IronRuby, IronPython o Lua.

IronPython y IronRuby son ambos disponibles en la actualidad.

Para una guía para la incorporación de IronPython leer How to embed IronPython script support in your existing app in 10 easy steps.

Lua es un lenguaje de script utilizado comúnmente en los juegos. Hay un compilador de Lua para .NET, disponible en CodePlex - http://www.codeplex.com/Nua

Ese código base es una gran lectura si quieres aprender sobre la construcción de un compilador en .NET.

un ángulo completamente diferente es tratar PowerShell.Existen numerosos ejemplos de integración de PowerShell en una aplicación: este es un proyecto exhaustivo sobre el tema: Powershell Tunnel

+0

Por cierto, he elegido esta como la respuesta aceptada porque quería de todos modos, en Python e IronPython, por lo que el enfoque de IronPython funciona mejor para * me *. –

+0

LuaInterface es un intérprete lua que funciona fantástico también. – RCIX

+0

Implementé C# Script en un sistema de flujo de trabajo en noviembre de 2009. Nos ha funcionado muy bien. –

4

Sí, pensé en eso, pero pronto me di cuenta de que otro dominio-específico-Language (DSL) sería un poco demasiado.

En esencia, tienen que interactuar con mi gamestate de manera posiblemente impredecibles. Por ejemplo, una tarjeta puede tener una regla "Cuando esto las tarjetas entran en juego, todos sus esbirros no-muertos ganan 3 ataque contra enemigos voladores, excepto cuando el enemigo está bendecida". Como los juegos de cartas coleccionables se basan en turnos, GameState Manager activará eventos de OnStageX y permitirá que las cartas modifiquen otras tarjetas o GameState de la forma que la tarjeta necesite.

Si trato de crear un DSL, tengo que poner en práctica un conjunto de características bastante grande y posiblemente actualizar constantemente, lo que desplaza el trabajo de mantenimiento a otra parte sin tener que retirarlo.

Es por eso que quería quedarse con un lenguaje .NET "real" para ser esencialmente capaz de simplemente disparar el evento y dejar que la tarjeta de manipular el gamestate en cualquier forma (dentro de los límites de la seguridad de acceso a código).

+0

(No es necesario marcar esto; aunque esto debería ser una actualización de comentario/respuesta, pero está protegido desde antes de que esas fueran opciones) – Will

7

Es posible que pueda utilizar IronRuby para eso.

De lo contrario, le sugiero que tenga un directorio en el que coloca ensamblajes precompilados. Entonces podría tener una referencia en el DB para el ensamblaje y la clase, y usar el reflejo para cargar los ensamblajes apropiados en el tiempo de ejecución.

Si realmente desea compilar en tiempo de ejecución podría usar el CodeDOM, entonces podría usar el reflejo para cargar el ensamblaje dinámico. MSDN article which might help.

5

Puede usar cualquiera de los lenguajes DLR, que proporcionan una forma de alojar fácilmente su propia plataforma de scripting. Sin embargo, no tiene que usar un lenguaje de scripting para esto. Podría usar C# y compilarlo con el proveedor del código C#. Siempre y cuando lo cargue en su propio Dominio de aplicación, puede cargarlo y descargarlo a su gusto.

6

Si no desea utilizar el DLR, puede use Boo (which has an interpreter) o puede considerar the Script.NET (S#) project on CodePlex. Con la solución Boo puede elegir entre scripts compilados o usar el intérprete, y Boo crea un buen lenguaje de scripting, tiene una sintaxis flexible y un lenguaje extensible a través de su arquitectura de compilación abierta. Script.NET también se ve bien, y usted puede ampliar fácilmente ese idioma, así como también es un proyecto de código abierto y utiliza un generador de compiladores muy amigable (Irony.net).

4

La aplicación principal que vende mi división hace algo muy similar para proporcionar personalizaciones del cliente (lo que significa que no puedo publicar ninguna fuente). Tenemos una aplicación C# que carga scripts VB.NET dinámicos (aunque cualquier lenguaje .NET podría ser fácilmente compatible, se eligió VB porque el equipo de personalización provenía de un fondo ASP).

Usando .NET's CodeDom compilamos los scripts de la base de datos, usando el VB CodeDomProvider (molestamente se usa el predeterminado .NET 2, si quiere soportar 3.5 características necesita pasar un diccionario con "CompilerVersion" = "v3. 5 "a su constructor). Utilice el método CodeDomProvider.CompileAssemblyFromSource para compilarlo (puede pasar configuraciones para forzarlo a compilar solo en memoria.

Esto daría como resultado cientos de ensamblajes en memoria, pero podría poner todos los códigos de las clases dinámicas juntas en un solo ensamblaje y recompile todo cuando haya algún cambio. Esto tiene la ventaja de que puede agregar un indicador para compilar en el disco con un PDB para cuando esté probando, lo que le permite depurar a través del código dinámico.

5

sugiera usar LuaInterface ya que ha implementado Lua completamente donde parece que Nua no está completo y es probable que no implemente algunas funciones muy útiles (corutinas, etc.)

Si desea utilizar algunos de los módulos Lua preenvasados ​​externos, le sugiero que use algo similar a 1.5.x en comparación con la serie 2.x que crea código completamente administrado y no puede exponer la API C necesaria.

3

La próxima versión de .NET (5.0?) Se ha hablado mucho acerca de abrir el "compilador como servicio", lo que haría posible la evaluación directa del script.

+0

Creo que esto se refiere a Roslyn? http://en.wikipedia.org/wiki/Microsoft_Roslyn –

+2

Sí. Aunque Roslyn todavía está en el horizonte, [Mono.CSharp (disponible en NuGet)] (http://blog.davidebbo.com/2012/02/quick-fun-with-monos-csharp-compiler-as.html) paquetes la misma funcionalidad –

+0

Agregando una actualización para mantener las opciones relevantes: La plataforma .NET Compiler ("Roslyn") está disponible. Entonces es una alternativa viable a todos los demás mencionados. https://github.com/dotnet/roslyn. – Riv

5

Estoy usando LuaInterface1.3 + Lua 5.0 para una aplicación NET   1.1.

El problema con Boo es que cada vez que analiza/compila/evalúa su código sobre la marcha, crea un conjunto de clases de boo para que tenga pérdidas de memoria.

Lua por otro lado, no hace eso, por lo que es muy estable y funciona maravilloso (puedo pasar objetos desde C# a Lua y hacia atrás).

Hasta ahora no lo he puesto todavía en PROD, pero parece muy prometedor.

Tuve problemas de pérdida de memoria en PROD usando LuaInterface + Lua 5.0, por lo tanto, utilicé Lua 5.2 y lo vinculé directamente a C# con DllImport. Las pérdidas de memoria estaban dentro de la biblioteca LuaInterface.

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

Una vez que hice esto, todas mis pérdidas de memoria se habían ido y la aplicación era muy estable.

Cuestiones relacionadas