关于碰撞检测系统中的类结构的建议

Advice on class structure in a collision detection system

本文关键字:结构 检测系统 于碰撞 碰撞      更新时间:2023-10-16

C++是我广泛使用的第一个使用面向对象的语言,所以我对这个想法仍然有点陌生。我正在尝试将我正在处理的游戏库从 Go(它使用接口而不是真正的 OOP 系统)移植到 C++。

我有一个使用四种类型的碰撞系统:点、边界、线和多边形。我想做的是让所有这些可以抽象到一个"碰撞体"类中,并有一个能够接受两个碰撞体对象并测试碰撞的函数。它看起来像这样:

bool Collides(Collider obj1, Collider obj2);

最初,我认为我可以为每个碰撞类型提供方法来测试给定另一种类型的碰撞(即方法OnPoint,OnBounding,OnLine和OnPolygon),然后让"Collider"成为需要所有这些方法的虚拟类,但后来我意识到这在C++是不可能的,因为它会使类相互依赖进行编译(对吧?

有点不知所措,不知道我还能做什么。我的设计理念是白日梦吗?

你想要

的是一个函数,它不仅在第一个参数上调度,而且在第二个参数上调度,即双调度。这在C++中不直接支持,但可以模拟。

class Point;
class Line;
class Collider {
public:
  virtual bool Collides(Collider const& x) const = 0;
protected:
  virtual bool Collides(Point const& p) const = 0;
  virtual bool Collides(Line const& l) const = 0;
  friend class Point;
  friend class Line;
};
class Point: public Collider {
public:
  virtual bool Collides(Collider const& x) const {
    // here, the type of this is now Point
    // now, find out what x is and call the overload on this type
    return x.Collides(*this);
  }
protected:
  virtual bool Collides(Point const& p) const {
    return false;
    // we now know that we are a point and checking vs. another point
  }
  virtual bool Collides(Line const& l) const {
    return false;
    // we now know that we are a point and checking vs. a line
  }
};
class Line: public Collider {
public:
  virtual bool Collides(Collider const& x) const {
    // here, the type of this is now Line 
    return x.Collides(*this);
  }
protected:
  virtual bool Collides(Point const& p) const {
    return false;
    // we now know that we are a line and checking vs. a point
  }
  virtual bool Collides(Line const& l) const {
    return false;
    // we now know that we are a line and checking vs. another line
  }
};

现在,检查两个对象将执行两个运行时调度:

Collider* p = new Point();
Collider* l = new Line();
p->Collides(*l);
// first dynamically dispatches on p to call Point::Collides
// in Collides, this (which is p) now has the static Point. 
// now do the second dispatch on l and use *this as the parametet
// to find the overload.

例如,这用于访客设计模式。如果您的对象集是固定的,但您希望对它们执行的操作将更改或扩展,则 Visitor 是一个不错的选择。