如何向类中添加可选功能?

时间:2012-02-02 22:12:34

标签: c# xna

我目前正在尝试学习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);
    }
}

这里的逻辑是所有Actors都必须有一个位置,但它们不一定要有纹理,因为Actor可以是光源,触发器等等.Dord2D在此类似,除了它被指定为使用2D纹理的Actor。我想要做的是能够根据需要为这些类中的任何一个添加功能。假设我想让Actor2D动画或者如前所述我想为无纹理的Actor添加触发器或光源......有哪些想法可以帮助我实现这些目标?

4 个答案:

答案 0 :(得分:3)

您可以尝试查看decorator pattern,它可以让您“对待”对象的行为。

答案 1 :(得分:1)

如果你真的想要对象&#34;变形&#34;就像在运行时更改其方法集的对象一样,您需要查看mixins。 (教程here
公平警告:这不适合胆小的人。

现在,在编译时你知道所有必须可用的类型,使用各种接口:

  • 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
   }
}

答案 2 :(得分:1)

而不是从Actor2D派生Actor(及其喜欢)。只需将这些派生类更改为自己的类,并为每个具有所有属性的“Actor”创建一个类( - Actor)。 (Actor2D属性...)然后在运行时使用您需要的任何内容。

他们不会占用那么多资源,因为他们在不使用时会指向null

编辑:

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

答案 3 :(得分:1)

所以,经过一番思考和搜索Google / StackOverflow之后。我终于找到了答案。我没有使用传统的OOP方法,而是学会了使用更加面向组件的编程方法。我在基于组件的游戏引擎设计中发现了一个非常棒的链接。

特别感兴趣的是关于T = Machine描述实体系统的5部分系列,它似乎是一种完全符合我要求的方法。对于有兴趣的人,第一篇文章是:http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/