Использование динамического кода в C # с событиями? - PullRequest
1 голос
/ 20 декабря 2010

В настоящее время я реализую движок сценариев в игре, которую я написал, используя функцию C # «dynamic».

Система должна работать при вызове скрипта, она должна регистрировать события, которые она прослушивает, а затем возвращать управление приложению.Затем, когда происходит событие, которое ожидает сценарий, сценарий должен выполняться.Одна вещь, которую я действительно хотел бы реализовать в скриптовом движке, - это чтобы методы с определенными именами автоматически связывались с событиями.Например, прослушиватель onTurnStart () должен автоматически связываться с событием turnStart.

Сценарии в основном должны выполнять существующие методы и изменять значения переменных в классах;такие вещи, как player.takeDamage () и player.HP = somevalue.Большинству сценариев необходимо дождаться начала хода игроков и конца хода игроков, прежде чем они будут выгружены.

Сложная часть заключается в том, что эти скрипты нужно менять, не внося никаких изменений в код игры.(Кроме безопасности) текущий план предусматривает автоматическую загрузку всех изменений сценария при запуске игры, чтобы все игроки использовали одну и ту же версию сценариев.

Однако у меня есть три вопроса:
1) Как мне зарегистрировать и отменить регистрацию слушателей событий сценария?
2) Может ли динамический код прослушивать события?
3) (Как) можно динамически регистрировать события?

Я впервые использую динамическую функцию C #, поэтому любая помощь будет принята с благодарностью.

Спасибо
- Михаил

1 Ответ

2 голосов
/ 20 декабря 2010

Я не уверен, что у вас есть правильный конец флешки с динамическим ключевым словом.Само по себе это не позволяет интерпретировать новый код во время выполнения.Все это позволяет обойти статическую проверку типов, откладывая разрешение операций до времени выполнения.

Если вы хотите «написать сценарий» своей игре, вы, вероятно, захотите взглянуть на интеграцию Lua, IronPython,или один из других языков DLR: -

В противном случае, обычно нужно иметь что-то вроде: -

interface IBehavior
{
  // Binds whatever events this behaviour needs, and optionally adds
  // itself to a collection of behaviours on the entity.
  void Register(Entity entity);
}

// Just an example
public abstract class TurnEndingDoSomethingBehavior
{
  public void Register(Entity entity)
  {
    entity.TurnEnding += (s, e) => DoSomething();
  }

  private abstract void DoSomething();
}

Вопрос в том, хотите ли вы иметь возможность добавлять совершенно новые поведения после компиляции-время?Если это так, вам нужно будет раскрыть некоторые или все ваши игровые состояния на языке сценариев.

Или этого достаточно, чтобы иметь возможность составлять существующие поведения во время выполнения?


После вашего редактирования

Я все еще не уверен, если честно, о ваших требованиях к динамическому ключевому слову и DLR.Средство запуска вашей игры может загрузить библиотеку классов, полную поведений, так же легко, как и набор сценариев!(Это то, что делает пусковая установка Minecraft, если память работает)

Если вам абсолютно необходимо использовать DLR, то посмотрите ссылки, которые я разместил.Вам придется выставлять столько игрового состояния, сколько необходимо для одного из языков DLR.События представляются как свойства функции первого порядка.Вам даже не нужно ключевое слово «dynamic» для базовых вещей.

Быстрый пример в IronPython: -

def DoSomethingWhenDamageTaken(*args):
  #do whatever...

player.DamageTaken += DoSomethingWhenDamageTaken

Класс игрока: -

public class Player
{
  public event EventHandler DamageTaken;

  // ...
}

Вы устанавливаете его следующим образом: -

ScriptEngine engine = Python.CreateEngine();
ScriptRuntime runtime = engine.Runtime;
ScriptScope scope = runtime.CreateScope();

// In an actual application you might even be
// parsing the script from user input.
ScriptSource source = engine.CreateScriptSourceFromFile(...); 

Player p = new Player();
scope.SetVariable("player", p);
source.Execute(scope);

Некоторые ссылки, с которых можно начать: -

...