【问题标题】:Using polymorphism for collision detection in an elegant way以优雅的方式使用多态性进行碰撞检测
【发布时间】:2012-09-06 17:03:24
【问题描述】:

我正在尝试设置一些简单的 2D 形状,这些形状可以使用鼠标在窗口周围拖动。当我将一个拖入另一个时,我希望这些形状能够记录碰撞。我有一个界面。

interface ICollidable
{
    bool CollidedWith(Shape other);
}

然后我有一个抽象类 Shape 实现了上述接口。

abstract class Shape : ICollidable
{
    protected bool IsPicked { private set; get; }
    protected Form1 Form { private set; get; }

    protected int X { set; get; } // Usually top left X, Y corner point
    protected int Y { set; get; } // Used for drawing using the Graphics object

    protected int CenterX { set; get; } // The center X point of the shape
    protected int CenterY { set; get; } // The center X point of the shape

    public Shape(Form1 f, int x, int y)
    {
        Form = f;
        X = x; Y = y;
        Form.MouseDown += new MouseEventHandler(form_MouseDown);
        Form.MouseMove += new MouseEventHandler(Form_MouseMove);
        Form.MouseUp += new MouseEventHandler(Form_MouseUp);
    }

    void Form_MouseMove(object sender, MouseEventArgs e)
    {
        if(IsPicked)
            Update(e.Location);
    }

    void Form_MouseUp(object sender, MouseEventArgs e)
    {
        IsPicked = false;
    }

    void form_MouseDown(object sender, MouseEventArgs e)
    {
        if (MouseInside(e.Location))
            IsPicked = true;
    }

    protected abstract bool MouseInside(Point point);
    protected abstract void Update(Point point);
    public abstract void Draw(Graphics g);
    public abstract bool CollidedWith(Shape other);
}

然后我有十个具体类 Circle、Square、Rectangle 等,它们扩展了 Shape 类并实现了抽象方法。 我想做的是想出一些干净优雅的方式来进行碰撞检测,而不是在 CollidedWith 方法中使用大量的 if 语句,例如

public bool CollidedWith(Shape other)
{
    if(other is Square)
    {
        // Code to detect shape against a square
    }
    else if(other is Triangle)
    {
        // Code to detect shape against a triangle
    }
    else if(other is Circle)
    {
        // Code to detect shape against a circle
    }
    ...   // Lots more if statements
}

有任何想法。这是我之前想过的问题,现在才付诸实践。

【问题讨论】:

  • 如果您能解释一下您是如何定义碰撞的,以及它在子类之间的变化方式,将会很有帮助。 Shape 是否还会包含有关实例坐标的任何信息?
  • @Mick C. 我已经更改了插入 Shape 类的整个代码的代码

标签: c# .net polymorphism collision-detection


【解决方案1】:

碰撞检测是否如此“特定于形状”,以至于对于

的每个排列都有不同的实现
Circle vs. Other Circle
Circle vs. Other Square
Circle vs. Other Triangle
Square vs. Other Circle
...

听起来您正在尝试创建一个包含所有可能性的矩阵,但如果您想出 10 个新形状,总共 20 个,那么您就有 400 个可能性。

相反,我会尝试在您的抽象类中提出一个通用的Shape.Overlaps(Shape other) 方法来满足所有这些要求。

如果这只是 2D 几何,那么判断任何形状的边缘路径是否相交应该很容易。

【讨论】:

    【解决方案2】:

    不是特定的形状,而是PathsRegions

    正方形只是一个有 4 个点的多边形,它们恰好成直角。然后只需编写一个Path.CollidesWith(Path) 方法就可以了。

    查看一些related questions

    【讨论】:

      【解决方案3】:

      Double dispatch在这种情况下常用。

      【讨论】:

      • 如果你仔细想想,这与带有大 if 语句的 OP 的 CollideWith 方法并没有什么不同。唯一的区别是框架将为您处理切换逻辑。另一个问题是,这种方法仍然需要您修改每个子类并为创建的每个新类型提供新的实现,这将导致维护负担呈指数级增长。
      猜你喜欢
      • 2010-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多