3

我正在 XNA 中制作矢量图形游戏。我设计了一个 Line 类来围绕中心点旋转以帮助绘制特定的形状。为了保持单一的事实,有没有办法将对形状中心的引用传递给我创建的所有线条,以便更新中心的位置也会更新线条的位置?我认为这样的事情会起作用:

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

2 回答 2

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

这仅允许您共享数据,它实际上并不会通知中心已更改的行。为此,您将需要某种事件。

于 2012-06-13T09:23:05.953 回答
2

用替代解决方案编辑

您遇到的问题是因为 Vector2 是一种值类型,您在方法参数中通过 ref 正确地传递了它,但随后使用分配制作了它的本地副本。

我不完全确定您是否可以按照您的想法维护指向 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));
        }

    }
}
于 2012-06-13T09:23:44.617 回答