2012-06-13 55 views
3

我正在XNA中製作矢量圖形遊戲。我設計了一個Line類來圍繞中心點旋轉以幫助繪製特定的形狀。爲了保持單一的事實真相,是否有辦法將形狀中心的引用傳遞給我創建的所有行,以便更新中心的位置也將更新行的位置?我認爲這樣的事情會起作用:C#XNA通過構造函數中的引用類

class Line 
{ 
    private Vector2 start; 
    private double length; 
    private double angle; 

    public Line(ref Vector2 start, double length, double angle){ 
     this.start = start; 
     this.length = length; 
     this.angle = angle; 
    } 
} 




class Obj 
{ 
    private Vector2 center; 
    private Line[] lines; 
    public Obj(){ 
     center = new Vector2(50,50); 
     lines = new Lines[5]; 
     for (int i = 0; i < 5; i++){ 
      lines[i] = new Line(ref center,30, (i/5 * 2 * Math.PI)); 

     } 

    } 
} 

但是當我移動中心時線條不更新。我究竟做錯了什麼?

回答

4

雖然struct正確按引用傳遞到Line,當你在內部分配給它:

public Line(ref Vector2 start, double length, double angle){ 
    this.start = start; 
} 

你實際上走的是struct副本

如果您發現自己需要引用類型語義struct而不是將其傳遞給單個方法,那麼您可能需要重新考慮使用class

您可以重新實現在一個類的類型或類包裹Vector2和使用:

class Vector2Class 
{ 
    public Vector2 Centre; 

    public Vector2Class(Vector2 inner) 
    { 
     Centre = inner; 
    } 
} 

class Line 
{ 
    private Vector2Class _centre; 

    public Line(Vector2Class centre) 
    { 
     _centre = centre;  
    } 
} 

要知道,你還在對副本的工作,但如果你分享類你們都會在的同樣副本上工作。

就個人而言,我會避免包裝,並讓我自己的類代表「中心」。這得到了很大程度上被接受的想法的支持,struct類型應該是不可變的,但您似乎需要改變值以保持表示的真實性。

class CentreVector<T> 
{ 
    public <T> X { get; set; } 
    public <T> Y { get; set; } 
} 

這隻會讓你分享數據,它實際上並沒有通知,該中心已經改變了線路。爲此,你需要某種事件。

2

編輯與替代解決方案

您遇到的問題是,因爲Vector2是值類型,你正確地傳遞給它由裁判在你的方法參數,但隨後與製作它的本地副本分配。

我不完全確定你是否可以以你想的方式維持一個指向Vector2的指針,但是你可以創建自己的Vector2類,它將是一個引用類型。

class ObjectVector2 
{ 
    public float X { get;set; } 
    public float Y { get; set; } 
} 

我想提出一個稍微不同的方式,通過控股的OBJ該線的一部分的參考實現同樣的結果。

class Line 
{ 

    private Vector2 Center { get { return parent.center; } } 
    private double length; 
    private double angle; 
    Obj parent; 

    public Line(Obj parent, double length, double angle) 
    { 
     this.parent = parent; 
     this.length = length; 
     this.angle = angle; 
    } 
} 

class Obj 
{ 
    public Vector2 center; 
    private Line[] lines; 
    public Obj() 
    { 
     center = new Vector2(50, 50); 
     lines = new Lines[5]; 
     for (int i = 0; i < 5; i++) 
     { 
      // passing the reference to this Obj in the line constructor. 
      lines[i] = new Line(this, 30, (i/5 * 2 * Math.PI)); 
     } 

    } 
} 
+0

您可以創建一個簡單的類StructWrapper 這將更通用。 (這與拳擊相似) – MattDavey

+1

是的,我實際上並不喜歡創建一個新的Vector2,因爲有很多方法使用Vector2並需要轉換,所以最好將ref保存到父對象並使用它的屬性。 – Andy

+1

您也可以採用基於事件的方法,其中父對象在中心點更改時引發事件。不知道基於事件的模型在遊戲中有多受歡迎:) – MattDavey