2015-11-13 60 views
0

我工作的一个游戏,将有可能专门针对每个怪物的四肢,所以你可以瞄准头部,腿部,循环...通过父/子结构

我有这个构造函数:

public Humanoid(Race race, Gender gender, string firstname, string lastname = null) 
{ 
    this.Legs = new List<Leg> { new Leg(), new Leg() }; 
    this.Torso = new Torso(); 
    this.Arms = new List<Arm> { new Arm(), new Arm() }; 
    this.Heads = new List<Head> 
    { 
     new Head 
     { 
      Ears = new List<Ear> { new Ear(), new Ear() }, 
      Eyes = new List<Eye> { new Eye(), new Eye() } 
     } 
    }; 
} 

所有这些肢体从接口ILimb继承。

什么是最好的方式能够循环所有的肢体,包括孩子(如适用)?

我可以添加一个protected List<ILimb> { get; set; }然后添加每个,但这是多余的。

任何想法或改进建议?

+1

我会使用具有自定义属性的System.Reflection库。用一些属性标记您的肢体,然后使用反射库获取Humanoid的属性,然后根据自定义属性过滤该列表。那么你有一个你可以通过https://msdn.microsoft.com/en-us/library/a4a92379(v=vs.110).aspx –

+0

进行遍历的所有'ILimb'的列表'Arms'列在一起并循环播放。 –

+0

@MattBurland:你的意思是concat? – Spikee

回答

3

最好的办法是有这样的结构,而不是:

public Humanoid(Race race, Gender gender, string firstname, string lastname = null) 
{ 
    this.Limbs = new List<ILimb>(); 
    this.Limbs.Add(new Legs() { Limbs = new List<Limb>() { new Leg(), new Leg() }); 
    this.Limbs.Add(new Torso()); 
    this.Limbs.Add(new Arms() { Limbs = new List<Limb>() { new Arm(), new Arm() }); 
    this.Limbs.Add(new Heads() { Limbs = new List<Limb>() { new Head() { Limbs = new List<Limb>() .... , ... }); 
} 

你可以整理的代码了,但基本上它应该有四肢的集合,和四肢应该有四肢的集合,这样就可以有头>耳朵>耳朵或任何你想要的层次。

然后在你的ILimb接口,给它一个四肢财产

public interface ILimb 
{ 
    List<ILimb> Limbs { get; set; } 
    List<ILimb> GetAllLimbs { get; } 
} 

而且用这种方法创建一个抽象基类四肢:

public virtual GetAllLimbs() 
{ 
// pseudocode: something like this (basically recurse through the children) 
return this.Limbs().foreach (c => c.GetAllLimbs()).union(this.Limbs()); 
} 

然后,它可以很容易地抓取下来的层次和检索每个肢体。

所以你可以例如做

myHumanoid.GetAllLimbs().Where(c => c is Arm).TakeDamage(5);

+0

躯干和头不是四肢。但除此之外,他们应该改变他们的结构的一般原则并不是一个坏的问题 –

+0

在现实生活中,不,但为了游戏的目的,他们可能是。或者你可以把它改成'BodyPart'或类似的东西。 '头部'的概念也不是真实的东西,它只是作者用来分组多个头部的一个对象。我不认为这是必要的,头可以添加到根对象,并且可以很容易地获得所有头。 – NibblyPig

+0

@SLC:正确,多重头脑的事情是掩盖双头Ogres或类似的东西。或者hydras,但显然这不是人形实现。 – Spikee

0

给定一个legs列表和arms列表,你可以这样做:

IEnumerable<ILimb> limbs = ((IEnumerable<ILimb>)arms).Concat(legs); 

然后遍历它:

foreach (var limb in limbs) 
{ 
    // limb is an ILimb and you can access anything in that interface 
    // for each limb 
} 

另一种方法是,你可以添加一个方法Humanoid是这样的:

public IEnumerable<ILimb> GetLimbs() 
{ 
    foreach (var a in Arms) 
    { 
     yield return a; 
    } 
    foreach (var l in Legs) 
    { 
     yield return l; 
    } 
} 

然后你可以做这样的事情:

foreach(var limb in someHumanoid.GetLimbs()) 
{ 

} 
+0

我会研究它,谢谢! – Spikee

1

有自定义模型,你所有的物体,除了一个......的车型定制集合List<T>是一个好的开始,但它没有你想要的功能。功能你试图投入Humanoid,但并不真正属于那里。

这样实现的东西:

public class LimbList<T> : IList<T> where T : ILimb 
{ 
    // implement IList<T> here 
} 

在这里,您将包括业务逻辑四肢集合。例如:

  • 如果已经有后盾集合中2个Arm对象,与Arm对象调用.Add()时抛出异常。
  • 如果后备集合中已有1 Torso对象,则在使用Torso对象调用.Add()时引发异常。

一个Humanoid会再有一个LimbList<ILimb>属性:

public Humanoid(Race race, Gender gender, string firstname, string lastname = null) 
{ 
    this.Limbs.Add(new Leg()); 
    this.Limbs.Add(new Leg()); 
    this.Limbs.Add(new Torso()); 
    this.Limbs.Add(new Arm()); 
    this.Limbs.Add(new Arm()); 
    this.Limbs.Add(new Head 
     { 
      // as an added exercise, how would you extend this concept to the Head object? 
     }); 
} 

,你可以遍历该列表轻松:这里

foreach (var limb in this.Limbs) 

本质点是一个对象集合本身就是一个对象,机智h像任何其他对象一样定制逻辑。将对象逻辑放入对象中,将集合逻辑放入集合中。有没有规则说你必须只有使用框架中的内置集合。

+0

有趣的建议,我会研究它。 – Spikee