C++ 如何在不强制转换为派生类的情况下检查几何基类中的冲突

C++ 如何在不强制转换为派生类的情况下检查几何基类中的冲突,c++,inheritance,design-patterns,collision-detection,C++,Inheritance,Design Patterns,Collision Detection,我有这种情况: class Shape{}; class Triangle : public Shape{}; class Rectangle : public Shape{}; class Square : public Rectangle{}; 我想在基类中实现一个虚拟collideWith方法,其工作方式如下: Shape *square = new Square(); Shape *triangle = new Triangle(); bool test = square.c

我有这种情况:

 class Shape{};
 class Triangle : public Shape{};
 class Rectangle : public Shape{};
 class Square : public Rectangle{};
我想在基类中实现一个虚拟collideWith方法,其工作方式如下:

Shape *square = new Square();
Shape *triangle = new Triangle();

bool test = square.collideWith(triangle);
有没有一种方法可以实现此方法,以便在不显式转换do派生类的情况下使用基类

我想创建一个名称空间来实现这一点:

namespace Collision {
  bool isCollisionBetween(const Triangle &triangle, const Square &square) {/* calculus */}
  bool isCollisionBetween(const Rectangle &rect, const Square &square) {/* calculus */}
  // and so on for all combination
}
但我不知道当我有这样的东西时,我该如何应用它

std::set<Shape*> shapesSet;
我想计算这个集合的所有碰撞


是否有可能或始终有必要将Shape类显式地转换为右侧继承的类?

通常,您会按如下方式解决这样的问题:

给Shape一个抽象函数,描述每个子类必须实现的形状。 每个子类根据其所属的特定类型实现此函数。 形状中的collideWith函数使用两种类型的抽象函数来确定属性。 这样,当添加一个形状时,其他形状都不需要更改,并且您不必添加函数将其与其他形状进行比较。只有新形状必须为所有必需的特性提供函数

现在困难的部分是决定每个形状可以提供什么属性。在您的情况下,可能很难为其提供有效的实现

可用于提供碰撞检测的属性示例包括:

多基因表达 矢量图 转换比特图
正如您可以想象的,在您的问题中,可能很难找到适合每个项目的适当表示。然后,您可能必须恢复到了解所有元素的比较。但这实际上是一种反面向对象的模式,当形状或属性的数量增加时,它会导致麻烦

一般来说,您可以按如下方式解决这样的问题:

给Shape一个抽象函数,描述每个子类必须实现的形状。 每个子类根据其所属的特定类型实现此函数。 形状中的collideWith函数使用两种类型的抽象函数来确定属性。 这样,当添加一个形状时,其他形状都不需要更改,并且您不必添加函数将其与其他形状进行比较。只有新形状必须为所有必需的特性提供函数

现在困难的部分是决定每个形状可以提供什么属性。在您的情况下,可能很难为其提供有效的实现

可用于提供碰撞检测的属性示例包括:

多基因表达 矢量图 转换比特图
正如您可以想象的,在您的问题中,可能很难找到适合每个项目的适当表示。然后,您可能必须恢复到了解所有元素的比较。但这实际上是一种反面向对象的模式,当形状或属性的数量增加时,它会导致麻烦

好吧,我的评论有点误导你。我的意思是:

要创建碰撞信息,请创建类似BroadPhase的内容,这是可选的,但非常有用。如果潜在的形状发生碰撞,将其视为预先检查。谷歌因此将二进制空间划分。现在忘掉四叉树或八叉树吧。此阶段将创建潜在联系人及其信息。问问你自己:哪些形状在碰撞?我正在调用哪个冲突解决函数?我应该使用多态性还是函数指针?i、 调用指向静态布尔冲突解析器的函数指针::句柄框b,圆圈c;可通过信息检索/调用。如果发生碰撞,我将调用什么回调?将所有这些信息保存到此信息对象 创建不同的碰撞控制柄函数来处理不同形状之间的碰撞。迭代保存冲突信息的i.e std::vector,并调用现在虚构的函数colIter->resolve,该函数调用冲突句柄函数的正确实现。如果发现碰撞,问问自己:我将调用哪些函数?我能提供什么信息?i、 在碰撞信息中添加额外的信息,或者创建一个新的对象碰撞对等。。。您可以保存碰撞点、法线、形状。。。。 碰撞检测成功,正在调用保存的回调到最终游戏对象。i、 e您可以调用GameObject::OnCollision const ContactPair&p; 希望这比我之前添加的评论对您有所帮助
ps:对于初学者来说,这是一个很好的提示:看看当前开源实现的幕后。i、 好吧,我的评论有点误导你了。我的意思是:

要创建碰撞信息,请创建类似BroadPhase的内容,这是可选的,但非常有用。如果潜在的形状发生碰撞,将其视为预先检查。谷歌因此将二进制空间划分。在这个时候,忘掉四叉树或八叉树吧 我此阶段将创建潜在联系人及其信息。问问你自己:哪些形状在碰撞?我正在调用哪个冲突解决函数?我应该使用多态性还是函数指针?i、 调用指向静态布尔冲突解析器的函数指针::句柄框b,圆圈c;可通过信息检索/调用。如果发生碰撞,我将调用什么回调?将所有这些信息保存到此信息对象 创建不同的碰撞控制柄函数来处理不同形状之间的碰撞。迭代保存冲突信息的i.e std::vector,并调用现在虚构的函数colIter->resolve,该函数调用冲突句柄函数的正确实现。如果发现碰撞,问问自己:我将调用哪些函数?我能提供什么信息?i、 在碰撞信息中添加额外的信息,或者创建一个新的对象碰撞对等。。。您可以保存碰撞点、法线、形状。。。。 碰撞检测成功,正在调用保存的回调到最终游戏对象。i、 e您可以调用GameObject::OnCollision const ContactPair&p; 希望这比我之前添加的评论对您有所帮助
ps:对于初学者来说,这是一个很好的提示:看看当前开源实现的幕后。i、 e或

我想您应该创建另一个名为collisionInformation的类,并将数据放在其中进行比较。而不是简单地比较返回的冲突信息…你说的是在基类中实现的某个枚举器,它说我是一个圆,我是一个超级复杂的形状,你在生活中永远不会看到它,在派生类中初始化这个成员值,并用它来检查我应该调用哪个isCollisionBetween函数?我想你应该创建另一个名为collisionInformation的类,并将数据放在那个里进行比较。而不是简单地比较返回的冲突信息…你说的是在基类中实现的某个枚举器,它说我是一个圆,我是一个超级复杂的形状,你在生活中永远不会看到它,在派生类中初始化这个成员值,并使用它来检查我应该调用哪个isCollisionBetween函数?我知道这可能是一个不太好的OO模式,但通过这种方式,我可以执行特定的碰撞检测,比一般的碰撞检测更快。我喜欢以标准格式转换所有形状的想法,但这样我就不能使用特定的碰撞算法,这些算法可能比我想到的多边形的通用算法更快,例如圆形碰撞。因此,我不能加入专门的冲突检测算法的世界,也不能加入格式良好的OO模式中基类的通用性的世界?最后,如果你想变得真正具体,你必须知道类型。您可以使用多个抽象属性进行比较,虽然不理想,但它确实保留了抽象:IsCucularShape radius可以由所有radius实现,其中radius在非圆形类型上返回无效,这应该会让您立即产生“反OO”的感觉。然后,如果比较有两个圆形,则使用半径,否则返回默认实现。否则,我担心你会退回到角色扮演上来。好吧,我会想一个最适合我的问题的方法。感谢您的回复。我知道这可能是一个不太好的OO模式,但通过这种方式,我可以执行特定的碰撞检测,比一般的碰撞检测更快。我喜欢以标准格式转换所有形状的想法,但这样我就不能使用特定的碰撞算法,这些算法可能比我想到的多边形的通用算法更快,例如圆形碰撞。因此,我不能加入专门的冲突检测算法的世界,也不能加入格式良好的OO模式中基类的通用性的世界?最后,如果你想变得真正具体,你必须知道类型。您可以使用多个抽象属性进行比较,虽然不理想,但它确实保留了抽象:IsCucularShape radius可以由所有radius实现,其中radius在非圆形类型上返回无效,这应该会让您立即产生“反OO”的感觉。然后,如果比较有两个圆形,则使用半径,否则返回默认实现。否则,我担心你会退回到角色扮演上来。好吧,我会想一个最适合我的问题的方法。谢谢你的回复。谢谢这很有帮助。谢谢这很有帮助。