2015-10-30 5 views
0

Я делаю игру с использованием Monogame, и я пытался выяснить, как реализовать функцию, которая действует аналогично инструкции AS3 и GML.С заявлением в C#, как в AS3/GML

До сих пор у меня есть система, которая работает, но не полностью так, как я ее хочу. Я храню свои GameObjects в словаре списков. Это значит, что я могу перейти к конкретному типу объекта, к которому я хочу получить доступ, без необходимости перебирать список ВСЕХ объектов. Используемый ключ - это имя типа.

public static Dictionary<string, List<GameObject>> All = 
    new Dictionary<string, List<GameObject>>(); 

Доступ ко всем конкретным типам объектов с использованием AllOf. Если в Словаре существует список, содержащий этот тип, он возвращает этот список, иначе он возвращает пустой список.

public static List<GameObject> AllOf(Type type) 
{ 
    string key = type.Name; 

    if(All.ContainsKey(key)) 
    { 
     return All[key]; 
    } 

    return new List<GameObject>(); 
} 

Пример того, как они реализуются

public override void Update(GameTime gameTime) 
{ 
    List<GameObject> list = Instance.AllOf(typeof(Dummy)); 

    for(int i = 0; i < list.Count; i++) 
    { 
     list[i].Update(gameTime); 
     list[i].foo += bar; 
    } 
} 

Но я предпочел бы использовать что-то похожее на AS3/GML с утверждением, что позволит также для других, кодов, не являющихся членами быть казнены.

with(typeof(Dummy)) 
{ 
    Update(gameTime); 
    foo += bar; 

    int fooBar = 2; 
    someObject.someMemberFunction(fooBar); 
} 

Есть ли способ сделать это? Моя конечная цель состоит в том, чтобы сделать мой код немного чище, и сделать его легче сделать много изменений, не набирая цикл for каждый раз.

ответ

0

попробовать

using(Object myObject = new Object()){ 

} 

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

+0

Я пробовал это, но когда я делаю VS, начинает кричать на меня, говоря: «Вы должны предоставить инициализатор в фиксированном или используемом заявлении оператора» – Gurman8r

+0

извините, сделал предположение, позвольте мне обновить элемент, который вы должны инициализировать элемент в команде «использование», потому что он говорит об использовании этого конкретного объекта, который будет иметь только область видимости этого использования. – Nikerym

+0

Будет ли доступ к одному объекту или всем его экземплярам? Например, я не пытаюсь создавать новые экземпляры. Попытка изменить те, которые уже инициализированы и запущены. – Gurman8r

1

Нет такого синтаксиса не существует в C#, но вы можете методы доступа в пределах for, которые не имеют ничего общего с коллекции:

public override void Update(GameTime gameTime) 
{ 
    List<GameObject> list = Instance.AllOf(typeof(Dummy)); 

    for(int i = 0; i < list.Count; i++) 
    { 
     list[i].Update(gameTime); 
     list[i].foo += bar; 

     int fooBar = 2; 
     someObject.someMemberFunction(fooBar); 
    } 
} 

Заметим, что вы можете также использовать foreach, который является мало очиститель, если вам не нужно индексатор:

foreach(var item in list) 
{ 
    item.Update(gameTime); 
    item.foo += bar; 

    int fooBar = 2; 
    someObject.someMemberFunction(fooBar); 
} 
+0

Хорошо, спасибо за разъяснение. Кроме того, я обычно должен использовать стандарт для цикла, потому что в цикле foreach мне удалили проблемы в прошлом при удалении объектов. – Gurman8r

0

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

Вы можете сделать что-то очень похожее на GML with(x){}, используя некоторую форму делегата в качестве параметра для статического метода и передавая лямбда в качестве этого параметра. Функция может быть даже обобщена, и вы можете вызвать ее без имени класса в инструкции using static. Вам нужно будет явно указать типизированный/именованный параметр, но это возможно. Вам нужно будет подключить его к собственным типам, но общая идея:

namespace NiftyStuff { 
    public static class With { 
     public static void with<T>(Action<T> proc) where T : GameObj { 
      var typeName = typeof(T).Name; 
      foreach (var item in GameObj.AllOf(typeName)) { proc((T)item); } 
     } 
    } 

    public class GameObj { 
     private static Dictionary<string, List<GameObj>> All = new Dictionary<string, List<GameObj>>(); 
     public static List<GameObj> AllOf(string name) { 
      return All.ContainsKey(name) ? All[name] : null; 
     } 
     public static void Add(GameObj foo) { 
      string typeName = foo.GetType().Name; 
      List<GameObj> foos = All.ContainsKey(typeName) ? All[typeName] : (All[typeName] = new List<GameObj>()); 
      foos.Add(foo); 
     } 
     public float x, y, angle; 
     public GameObj() { x = y = angle = 0; } 
     public void Destroy() { AllOf(GetType().Name)?.Remove(this); } 
    } 

    public class Enemy : GameObj { 
     public float maxHealth, curHealth; 
     public Enemy() : base() { maxHealth = curHealth = 300; } 
     public Enemy(float health) : base() { maxHealth = curHealth = health; } 
     public bool Damage(float amt) { 
      if (curHealth > 0) { 
       curHealth -= amt; 
       return curHealth <= 0; 
      } 
      return false; 
     } 
    } 

    public class Pumpkin : GameObj { 
     public bool exists = false; 
     public Pumpkin() : base() { exists = true; } 
     public bool LookAt() { return (exists = !exists); } 
    } 
} 

На самом деле, используя приведенный выше код будет работать следующим образом:

using NiftyStuff; 
using static NiftyStuff.With; 

//... 

    with ((Enemy e) => { 
     if (e.Damage(50)) { 
      Log("Made a kill!"); // Whatever log function you have... 
     } 
    }); 

    with ((Pumpkin p) => { 
     if (p.LookAt()) { 
      Log("You see the pumpkin"); 
     } else { 
      Log("You no longer see the pumpkin"); 
     } 
    }); 

Хотя не совсем, как GML-х with заявление, он, по крайней мере, позволит вам запускать код со всех зарегистрированных объектов определенного типа.

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

Надеюсь, что это поможет, несмотря на то, что 2 года устарели.