C ++中的碰撞检测多次调度?

时间:2014-01-08 16:10:59

标签: c++ multiple-dispatch

我有圆圈,盒子和线条。现在我想在它们之间实现碰撞检测。这意味着我必须为两种形状的每种组合提供一个功能。当然我可以使用相同的线对圆和圆对线,但我认为我的观点仍然有效。在C ++中实现它的最优雅的方法是什么?

3 个答案:

答案 0 :(得分:1)

Modern C++ Design一书中,Multimethods章节解释了如何实现它们并记录了如何使用[Loki库提供的实现] [2]。还有Boost.Multimethod proposal,但它还没有。这本书展示了多方法在对象碰撞主题上的强大功能。

答案 1 :(得分:0)

<强>多态性

首先你有Shape和所有其他子类:

class Shape;

class Circle : Shape;
class Square : Shape;
...etc

并且你希望它们全部实现相互交叉,因此有一个通用函数:

class Shape{
    bool isIntersect(const Shape&)
    {
        return isIntersecting(this, shape);
    }
};

现在重载isIntersecting与所有对选项,因为每个案例都是唯一的,你在这里没有太多的选择,但实现每个案例:

bool isIntersecting(Circle, Square);
bool isIntersecting(Circle, Line);
...

您也可以尝试访问者模式,但我认为这里没用。

答案 2 :(得分:0)

您可以在场景中进行碰撞检测,而不是处理两个形状的每个事件。 此外,你将面临一些问题。其中包括类型省略和登记几何形状:

#include <iostream>
#include <map>

class Shape
{
    public:
    struct Type {
        public:
        typedef unsigned Identifier;

        const char* name;
        Identifier id;

        Type(const char* name)
        :   name(name), id(register_name(name))
        {}

        private:
        static Identifier register_name(const char*);
    };


    virtual const Type& get_type() const = 0;

    virtual ~Shape() {}
};

Shape::Type::Identifier Shape::Type::register_name(const char* name) {
    typedef std::map<const char*, Identifier> Types;
    static std::map<const char*, Identifier> types;
    auto& id = types[name];
    if( ! id) id = types.size();
    return id;
}


class Scene
{
    public:
    typedef bool (*CollisionDetector)(const Shape&, const Shape&);
    void register_collision_detector(CollisionDetector, const Shape::Type&, const Shape::Type&);
    bool collision(const Shape& a, const Shape&, bool strict = false) const;

    private:
    typedef std::pair<Shape::Type::Identifier, Shape::Type::Identifier> Identifier;
    typedef std::map<Identifier, CollisionDetector> CollisionDetectors;
    CollisionDetectors m_detectors;
};

void Scene::register_collision_detector(
    CollisionDetector detector,
    const Shape::Type& t0,
    const Shape::Type& t1)
{
    m_detectors[Identifier(t0.id, t1.id)] = detector;
}

bool Scene::collision(const Shape& s0, const Shape& s1, bool strict) const {
    const Shape::Type::Identifier i0 = s0.get_type().id;
    const Shape::Type::Identifier i1 = s1.get_type().id;
    auto pos = m_detectors.find(Identifier(i0, i1));
    if(pos == m_detectors.end() && ! strict && i0 != i1)
        pos = m_detectors.find(Identifier(i1, i0));
    if(pos != m_detectors.end())
        return pos->second(s0, s1);
    else return false;
}


class Circle : public Shape
{
    public:
    static const Type type;
    virtual const Type& get_type() const  { return type; }
};
const Shape::Type Circle::type("Circle");

class Rectangle : public Shape
{
    public:
    static const Type type;
    virtual const Type& get_type() const { return type; }
};
const Shape::Type Rectangle::type("Rectangle");

bool circle_rectangle_collision(const Shape& circle, const Shape& rectangle) {
    std::cout << "circle_rectangle_collision" << std::endl;
    return false;
}


int main()
{
    Scene scene;
    scene.register_collision_detector(circle_rectangle_collision, Circle::type, Rectangle::type);
    Circle circle;
    Rectangle rectangle;
    scene.collision(circle, rectangle);
    scene.collision(rectangle, circle);
}