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

时间:2014-04-06 20:09:20

标签: c++ oop visitor-pattern double-dispatch

C ++是我用过的第一种使用面向对象的语言,所以我对这个想法还有点新意。我正在尝试将我正在使用的游戏库(使用接口而不是真正的OOP系统)移植到C ++。

我有一个使用四种类型的碰撞系统:一个点,一个边界,一条线和一个多边形。我想要做的是将所有这些都抽象化为“Collider”类,并且具有能够获取两个Collider对象并测试碰撞的函数。它看起来像这样:

bool Collides(Collider obj1, Collider obj2);

最初我以为我可以为每种碰撞类型设置方法,以测试另一种类型的碰撞(即方法OnPoint,OnBounding,OnLine和OnPolygon),然后让“Collider”成为需要所有这些的虚拟类方法,但后来我意识到在C ++中是不可能的,因为它会使类依赖于彼此进行编译(对吧?)。

对于我还能做些什么,我有点不知所措。我的设计理念是个梦想吗?

1 个答案:

答案 0 :(得分:1)

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

class Collider {
public:
    virtual bool Collides(Collider const& x) const = 0;

private:
    virtual bool Collides(Point const& p) const = 0;
    virtual bool Collides(Line const& l) const = 0;
};

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
        x.Collides(*this);
    }

private:
    virtual bool Collides(Point const& p) const {
        // we now know that we are a point and checking vs. another point
    }

    virtual bool Collides(Line const& l) const {
        // 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 
        x.Collides(*this);
    }

private:
    virtual bool Collides(Point const& p) const {
        // we now know that we are a line and checking vs. a point
    }

    virtual bool Collides(Line const& l) const {
        // 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 design pattern中使用。如果您的对象集是固定的,但您希望对它们进行的操作将会改变或扩展,那么访问者是一个不错的选择。