Comment puis-je communiquer avec un composant IronPython dans un jeu C # / XNA?

8

Mon jeu XNA est axé sur les composants et comprend divers composants pour la position, la représentation physique, le rendu, etc., qui étendent tous une Componentclasse de base . Le joueur et les ennemis ont également des contrôleurs qui sont actuellement définis en C #. Je voudrais les transformer en scripts Python via IronPython (une implémentation .NET de Python). Mon problème est que je ne sais pas comment interagir avec ces scripts.

Les exemples de l' incorporation d'IronPython dans une application C # suggèrent que je devrais créer quelque chose comme un composant de script qui compile un script Python et appelle la méthode de mise à jour du contrôleur via Python - essentiellement, ce serait une classe wrapper pour C # pour interfacer avec Python .

Je sens que je manque quelque chose dans mes recherches. Il doit y avoir un moyen de charger un script, d'instancier un objet Python (soit dans le script Python soit en C #), puis d'avoir une référence directe à cet objet Python dans mon code C #.

Existe-t-il un moyen de travailler directement avec un objet IronPython ou un wrapper est-il requis?

doppelgreener
la source

Réponses:

7

J'ai compris comment faire ça. Comme je m'y attendais, puisque IronPython se compile en CLR, les objets C # et IronPython peuvent très bien interagir sans aucun traitement spécial nécessaire. J'ai créé un script qui crée en fait un nouveau type de composant qui peut être référencé très bien à partir de C #.

Un petit mot sur la structure de mon jeu: Sa solution a deux projets: Game et GameEngine. Le jeu est ce qui est finalement compilé dans un EXE, et le GameEngine est compilé dans une DLL qui se trouve dans le même répertoire.

Le scénario

Cela se trouve actuellement dans le projet de contenu par défaut, n'a aucune action de génération et est copié dans le répertoire de sortie.

Notez que la classe Component fait partie de GameEngine et est donc compilée dans GameEngine.dll . Il n'a également rien à voir avec la classe GameComponent de XNA et ses méthodes n'ont pas besoin de passer un objet 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()

Comment le script est compilé et exécuté

Une seule fois dans le jeu, je lance ceci:

// 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);

Lorsque le script est exécuté, il crée sa propre instance d'un PyComponent.

Bien sûr, vous devrez référencer la bibliothèque IronPython et le runtime Microsoft Dynamic. J'ai découvert que je n'avais besoin que de ces quatre DLL du dossier racine du téléchargement IronPython:

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

Ajoutez ces références à votre projet, puis ces usinginstructions à votre code (selon Embedding IronPython dans une application C # ):

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

Obtention d'une référence à l'objet Python

Je ne sais pas comment j'obtiendrais une référence directement à partir du script, mais j'ai une façon détournée de le faire. Dans ma conception de moteur, tous les composants s'enregistrent automatiquement dans la collection de composants du moteur, afin que je puisse obtenir une référence à l'objet par là. Dans un cas plus spécifique, vous pouvez simplement demander à de nouveaux objets Python de s'inscrire quelque part dans une file d'attente, vous devez donc les créer, puis les récupérer immédiatement.

doppelgreener
la source
Ma dernière mise à jour de ce message sera quand je trouverai comment obtenir directement une référence à l'objet python.
doppelgreener