Como me comunico com um componente IronPython em um jogo C # / XNA?

8

Meu jogo XNA é orientado a componentes e possui vários componentes para posição, representação física, renderização etc., todos os quais estendem uma Componentclasse base . O jogador e os inimigos também têm controladores atualmente definidos em C #. Gostaria de transformá-los em scripts Python via IronPython (uma implementação .NET do Python). Meu problema é que não tenho certeza de como interagir com esses scripts.

Os exemplos em Incorporando o IronPython em um aplicativo C # sugerem que eu teria que criar algo como um componente Script que compila um script Python e chama o método Update do controlador via Python - essencialmente, seria uma classe de wrapper para o C # interagir com o Python .

Sinto que estou perdendo algo em minha pesquisa. Não deve haver uma maneira de carregar um script, instanciar um objeto Python (ou no script Python ou C #) e, em seguida, em seguida, ter uma direta referência a esse objeto Python no meu código C #.

Existe uma maneira de trabalhar diretamente com um objeto IronPython ou é necessário um wrapper?

doppelgreener
fonte

Respostas:

7

Eu descobri como fazer isso. Como eu esperava, como o IronPython é compilado até o CLR, os objetos C # e IronPython podem interagir um com o outro, sem nenhum tratamento especial necessário. Eu criei um script que realmente cria um novo tipo de componente que pode ser referenciado muito bem em C #.

Uma breve palavra sobre a estrutura do meu jogo: Sua solução tem dois projetos: Game e GameEngine. O jogo é o que é compilado em um EXE e o GameEngine é compilado em uma DLL que fica no mesmo diretório.

O script

Atualmente, ele fica no projeto de conteúdo padrão, não tem ação de construção e é copiado para o diretório de saída.

Observe que a classe Component faz parte do GameEngine e, portanto, é compilada no GameEngine.dll . Ele também não tem nada a ver com a classe GameComponent do XNA e seus métodos não precisam receber um 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()

Como o script é compilado e executado

Apenas uma vez dentro do jogo, eu corro o seguinte:

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

Quando o script é executado, ele cria sua própria instância de um PyComponent.

Obviamente, você precisará fazer referência à biblioteca IronPython e ao Microsoft Dynamic runtime. Descobri que só preciso dessas quatro DLLs da pasta raiz do download do IronPython:

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

Adicione essas referências ao seu projeto e, em seguida, essas usinginstruções ao seu código (de acordo com a Incorporação do IronPython em um aplicativo C # ):

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

Obtendo uma referência ao objeto Python

Não sei como obter uma referência diretamente do script, mas tenho uma maneira indireta de fazer isso. No design do meu mecanismo, todos os componentes se registram automaticamente na coleção de componentes do mecanismo, para que eu possa obter uma referência ao objeto por lá. Em um caso mais específico, você pode simplesmente fazer com que novos objetos Python se registrem em uma fila em algum lugar, para criá-los e recuperá-los imediatamente.

doppelgreener
fonte
Minha última atualização deste post será quando descobrir como obter diretamente uma referência ao objeto python.
Doppelgreener 19/04/12