Как добавить дополнительные функции в класс? - PullRequest
3 голосов
/ 03 февраля 2012

В настоящее время я пытаюсь изучить все тонкости XNA / C #, но в настоящее время я застрял в проблеме: я хочу добавить дополнительные функции в класс, и я не знаю, как вообще начать. Для ясности вот мой текущий код:

public class Actor
{
    //Fields
    private Vector3 m_location;

    //Properties
    public Vector3 Location
    {
        get { return m_location; }
        set { m_location = value; }
    }

    //Constructors
    public Actor(float x, float y, float z)
    {
        Location = new Vector3(x, y, z);
    }
    public Actor(Vector3 location)
    {
        Location = location;
    }
}

public class Actor2D : Actor
{
    //Fields
    private Texture2D m_texture;

    //Properties
    public Texture2D Texture
    {
        get { return m_texture; }
        set { m_texture = value; }
    }

    //Constructors
    public Actor2D(float x, float y, float z) : base(x, y, z) {}
    public Actor2D(Vector3 vector) : base(vector) {}

    //Methods
    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(Texture, new Vector2(Location.X, Location.Y), Color.White);
    }
    public void Load(ContentManager content, string asset)
    {
        Texture = content.Load<Texture2D>(asset);
    }
}

Логика здесь в том, что все актеры должны иметь местоположение, но они не обязательно должны иметь текстуру, поскольку актер может быть источником света, триггером и т. Д. И т. П. Actor2D похож на это, за исключением того, что он обозначен как Актер, который использует 2D текстуру. Что я хочу сделать, так это иметь возможность добавлять функциональность к любому из этих классов по мере необходимости. Скажем, я хочу, чтобы Actor2D был анимированным, или, как уже упоминалось ранее, я хочу добавить триггер или источник света к нетекстурированному актеру ... Какие идеи помогут мне достичь этих целей?

Ответы [ 4 ]

3 голосов
/ 03 февраля 2012

Вы можете попробовать взглянуть на шаблон декоратора , который позволяет вам "привязать" поведение к объекту.

1 голос
/ 23 февраля 2012

Итак, после долгих раздумий и поисков в Google / StackOverflow.Я наконец нашел свой ответ.Вместо того, чтобы использовать традиционный подход ООП, я узнал, что я должен использовать более компонентный подход к программированию.Я нашел действительно замечательную ссылку на разработку игрового движка на основе компонентов.

Особый интерес представляет серия из 5 частей на T = Machine, описывающая Entity Systems, которая, кажется, является подходом, который делает именно то, что я искал.Для тех, кто заинтересован, первый пост: http://t -machine.org / index.php / 2007/09/03 / Entity-Systems-is-the-future-of-mmog-development-part-1 /.

1 голос
/ 03 февраля 2012

Вместо того, чтобы Actor2D (и подобные ему) получаются из Actor. Просто измените эти производные классы на собственные классы, и имейте один класс (- Actor) для каждого «Актера» с всеми этих свойств. (Свойство Actor2D ...) Затем используйте то, что вам нужно во время выполнения.

Они не будут занимать столько ресурсов, потому что будут указывать на null, когда они не используются.

EDIT:

class Actor
{
    public Stuff2D stuff2d = new Stuff2D();
    public StuffLightPower lightPower = new StuffLightPower();
    //...
}

class Stuff2D
{
    public int height;
    public int weight;
    //...
}

class StuffLightPower
{
    public int lumen;
    public Color color;
    //...
}

А затем используйте это так:

Actor actor1 = new Actor();

//First it's going to be a 2D.
actor1.stuff2d.weight = 3;
//...

//Now it's changed to a light source.
actor1.stuff2d = null;
actor1.lightPower.color = Color.White;
//...

//And back again.
actor1.lightPower = null;
actor1.stuff2d = new Stuff2D();
//...
1 голос
/ 03 февраля 2012

Если вы действительно хотите, чтобы объект «трансформировался», как в случае объектов, меняющих свой набор методов во время выполнения, вы смотрите на mixins .(учебник здесь )
Справедливое предупреждение: это не для слабонервных.

Теперь, так как во время компиляции вы знаете все типы, которые будут иметьчтобы быть доступным, используйте различные интерфейсы:

  • IHasTexture
  • IDrawable: IHasTexture (это означает, что и IDrawable автоматически должен реализовать IHasTexture, поскольку вы не можете рисовать иначе)
  • ILoadable
  • ... столько, сколько вы хотите.

Затем предоставьте реализацию для каждой комбинации, которая вам нужна.Кроме того, я думаю, что было бы лучше поместить все это в свой бизнес-уровень, если у вас есть какие-либо.

Надеюсь, это поможет,

Баб.

РЕДАКТИРОВАТЬ: пример.

public interface IMovable { void Move(); }

public class MoveMixin : IMovable
{
   public void Move() { Console.WriteLine("I am moving"); }
}

public class SomeDude { }

public static class TestClass
{
   public static Test()
   {
      var myMixinConfiguration = MixinConfiguration.BuildFromActive()
           .ForClass<SomeDude>().AddMixin<MoveMixin>()
           .BuildConfiguration();
      using(myMixinConfiguration.EnterScope())
      {//In this scope, SomeDude implements IMovable, but only if you get an instance through the ObjectFactory
         var myMovableDude = ObjectFactory.Create<SomeDude>(ParamList.Empty);
         ((IMovable)myMovableDude).Move(); //This line compiles and executes just fine, even though the class declaration does not specify anything about Move() !!
      }
      //The SomeDude class no longer implements IMovable
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...