¿Cómo me comunico con un componente IronPython en un juego C # / XNA?

8

Mi juego XNA está orientado a componentes y tiene varios componentes para posición, representación física, renderizado, etc., todos los cuales extienden una Componentclase base . El jugador y los enemigos también tienen controladores que están definidos actualmente en C #. Me gustaría convertirlos en scripts de Python a través de IronPython (una implementación .NET de Python). Mi problema es que no estoy seguro de cómo interactuar con esos scripts.

Los ejemplos en Embedded IronPython en una aplicación C # sugieren que tendría que crear algo así como un componente Script que compila un script Python y llama al método de actualización del controlador a través de Python; esencialmente, sería una clase envolvente para que C # interactúe con Python .

Siento que me falta algo en mi investigación. No debe ser una forma de cargar un script, una instancia de un objeto de Python (ya sea en la secuencia de comandos Python o en C #) y luego luego tener una directa referencia a ese objeto Python en mi código C #.

¿Hay alguna manera de trabajar con un objeto IronPython directamente o se requiere un contenedor?

doppelgreener
fuente

Respuestas:

7

He descubierto cómo hacer esto. Como esperaba, dado que IronPython compila a CLR, los objetos C # y IronPython pueden interactuar entre sí sin ningún tratamiento especial necesario. Creé un script que en realidad crea un nuevo tipo de Componente al que se puede hacer referencia muy bien desde C #.

Una breve palabra sobre la estructura de mi juego: su solución tiene dos proyectos: Game y GameEngine. El juego es lo que finalmente se compila en un EXE, y el GameEngine se compila en una DLL que se encuentra en el mismo directorio.

La secuencia de comandos

Actualmente se encuentra en el proyecto de contenido predeterminado, no tiene acción de compilación y se copia en el directorio de salida.

Tenga en cuenta que la clase Componente es parte de GameEngine y, por lo tanto, se compila en GameEngine.dll . Tampoco tiene nada que ver con la clase GameComponent de XNA y sus métodos no necesitan pasar un objeto GameTime.

import clr
clr.AddReferenceToFileAndPath("GameEngine.dll")
from GameEngine import *
# or: from GameEngine import Component

class PyComponent(Component):
    def __new__(self):
        Component.__new__(self)

    def Initialize(self):
        pass

    def Update(self):
        pass

    def Draw(self):
        pass

pc = PyComponent()

Cómo se compila y ejecuta el script

Solo una vez dentro del juego, ejecuto esto:

// Engine setup stuff. The scope can work with variables in the script by
// adding references, accessing/removing current references, etc.
// Each script COULD have its own scope but I have no reason to do that yet.
ScriptEngine PythonEngine = Python.CreateEngine();
ScriptScope DefaultScope = PythonEngine.CreateScope();

string filename = @"Content\ScriptTest.py";
ScriptSource script = PythonEngine.CreateScriptSourceFromFile(filename, Encoding.ASCII);
script.Execute(scope);

Cuando se ejecuta el script, crea su propia instancia de un PyComponent.

Por supuesto, deberá hacer referencia a la biblioteca IronPython y al tiempo de ejecución dinámico de Microsoft. Descubrí que solo necesito estas cuatro DLL de la carpeta raíz de la descarga de IronPython:

  • IronPython.dll
  • IronPython.Modules.dll
  • Microsoft.Dynamic.dll
  • Microsoft.Scripting.dll

Agregue estas referencias a su proyecto, luego estas usingdeclaraciones a su código (de acuerdo con Embedded IronPython en una aplicación C # ):

using IronPython.Hosting;
using IronPython.Runtime;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;

Obteniendo una referencia al objeto Python

No estoy seguro de cómo obtener una referencia directamente del script, pero tengo una forma indirecta de hacerlo. En el diseño de mi motor, todos los componentes se registran automáticamente con la colección de componentes del motor, por lo que puedo obtener una referencia al objeto a través de allí. En un caso más específico, puede hacer que los nuevos objetos de Python se registren con una cola en alguna parte, de modo que los cree y luego los recupere de inmediato.

doppelgreener
fuente
Mi última actualización de esta publicación será cuando descubra cómo obtener directamente una referencia al objeto python.
doppelgreener