2015-11-13 61 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