C ++中碰撞检测的多次调度? [关闭]

Posted

技术标签:

【中文标题】C ++中碰撞检测的多次调度? [关闭]【英文标题】:Multiple dispatch for collision detection in C++? [closed] 【发布时间】:2014-01-26 20:37:06 【问题描述】:

我有圆圈、方框和线条。现在我想在它们之间实现碰撞检测。这意味着我必须对两种形状的每种组合都有一个函数。当然,我可以对直线与圆和圆与直线使用相同的方法,但我认为我的观点仍然成立。在 C++ 中实现这一点最优雅的方式是什么?

【问题讨论】:

双重分派是使用访问者模式完成的,如以下 (java) 示例所示:en.wikipedia.org/wiki/Visitor_pattern#Java_example 我会做一个像bool isCOlliding(Circle object1, Line object2);然后bool isCOlliding(Box object1, Circle object2);这样的重载函数,这样你就可以在每个组合上调用相同的函数名 ideone.com/lTsc7M 可能会有所帮助(需要 C++11) 【参考方案1】:

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

【讨论】:

【参考方案2】:

多态性

首先你有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);
...

你也可以试试visitor pattern,不过我觉得这里没用。

【讨论】:

我同意关于访问者模式的评论,但函数重载和多次分派之间的重要区别在于,函数重载只有在编译时知道类型时才有效。这是需要考虑的事情,例如以防对象保存在最顶层类型的容器中(在这种情况下为Shape)。【参考方案3】:

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

#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);

【讨论】:

以上是关于C ++中碰撞检测的多次调度? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

边缘检测 --> CGPath --> SpriteKite 碰撞

JavaScript动画-碰撞检测

canvas游戏和动画中的碰撞检测

基于 SpriteKit 中的碰撞检测更新分数的问题

没有墙壁时的敌人与墙壁的碰撞检测

如何检测精灵套件中的碰撞?