在C#/XNA中使用通用函数进行冲突检测

本文关键字:函数 冲突检测 XNA | 更新日期: 2023-09-27 18:23:35

我正在c#/XNA中制作一个物理引擎,我有三个基本对象。。。

球体立方体平面

都源自

游戏对象

我把我所有的对象都存储在一个GameObjects列表中,我想循环浏览这个列表,并能够调用CheckCollision函数,该函数将转到每对对象的正确函数

例如

go是一个球体,

go2是一种球面

if(CheckCollision(go, go2))
{
  //do stuff
}
bool CheckCollision(Sphere one, Sphere two)
{
  //Check Sphere to Sphere
}
bool CheckCollision(Sphere sphere, Plane plane)
{
  //Check Sphere to Plane
}

我希望它能转到正确的函数,而不必使用if检查。

谢谢。

在C#/XNA中使用通用函数进行冲突检测

您可以使用虚拟调度:

abstract class GameObject
{
    abstract bool CheckCollision (GameObject other);
    abstract bool CheckCollision (Sphere other);
    abstract bool CheckCollision (Cube other);
    abstract bool CheckCollision (Plane other);
}
class Sphere : GameObject
{
    override bool CheckCollision (GameObject other) { return other.CheckCollision(this); }
    override bool CheckCollision (Sphere other) { /* ... implementation ... */ }
    override bool CheckCollision (Cube other) { /* ... implementation ... */ }
    override bool CheckCollision (Plane other) { /* ... implementation ... */ }
}
class Cube : GameObject
{
    override bool CheckCollision (GameObject other) { return other.CheckCollision(this); }
    override bool CheckCollision (Sphere other) { /* ... implementation ... */ }
    override bool CheckCollision (Cube other) { /* ... implementation ... */ }
    override bool CheckCollision (Plane other) { /* ... implementation ... */ }
}
class Plane : GameObject
{
    override bool CheckCollision (GameObject other) { return other.CheckCollision(this); }
    override bool CheckCollision (Sphere other) { /* ... implementation ... */ }
    override bool CheckCollision (Cube other) { /* ... implementation ... */ }
    override bool CheckCollision (Plane other) { /* ... implementation ... */ }
}

编辑

考虑一下当你有这个时会发生什么:

GameObject go1 = new Sphere();
GameObject go2 = new Cube();
bool collision = go1.CheckCollision(go2);
  • 调用转到球体上的抽象GameObject.CheckCollision(GameObject)方法
  • 虚拟调度意味着我们进入Sphere.CheckCollision(GameObject)
  • Sphere.CheckCollision(GameObject)调用多维数据集上的抽象GameObject.CheckColliction(Sphere)方法
  • 虚拟调度意味着我们进入Cube.CheckCollision(Sphere)

因此,不需要类型检查if语句。

编辑2

请参阅Eric Lippert的回答https://stackoverflow.com/a/2367981/385844;第一种选择——访问者模式——本质上就是上面概述的方法。Eric在https://stackoverflow.com/a/9069976/385844也讨论了这个问题。

我担心这是不可能的,除非你用多边形来近似你的形状,这将允许一种通用的方法。如果你使用精确的数学表示,那么你需要为不同的配对找到特殊的解决方案。如果为不同的形状类型(1、2、3)给定数字,则可以用10* go.Number + go2.Number表示一对,并在switch语句中使用此数字。

还要注意,您的方法具有O(n^2)性能,其中n是对象数。考虑使用比列表更合适的数据结构。K-D树通常用于在K维空间中存储对象。它们经常和图形对象的边界框一起使用。每个对象都有一个产生边界框的方法或属性。K-D树将减少所需的碰撞检查次数。请参阅维基百科上的k-d树。