我正在为2D游戏开发基础。我的总体设计是这样的:
class Entity:
Every object class (like a wall, an enemy, floor etc.) derives
from this class. Most of the functions are pure virtual. There is
a hitbox as well.
class Scene:
Contains pointers to Entity-objects. When an Entity-pointer is added,
it will be given a Scene-pointer to its parent so it may access that.
场景还具有碰撞检测功能:
getIntersections<T> (Entity *)
getIntersections<T...> (Entity *)
(both return a std::vector<Entity *>)
这基本上会使所有Entity *
与参数相交 - Entity *
(通过检查命中框),然后尝试dynamic_cast<T *>
它们。然后返回所有匹配的Entity *
s(不是已转换的)。可变参数模板用于检查多个交叉类。
我背后的基本想法是,如果我有一个Player
- 类(显然代表了玩家),以及其他一些类,如Enemy
,Wall
等,它检查Player
- 对象是否与其中一个(或多个)碰撞是一件容易的事:
// (inside Player::tick(); quick and dirty)
{
if ( (this->parentScene->getIntersections<Wall>(this)).empty() )
// player does not collide with a wall, just move.
else
// player does collide with a wall, do whatever.
}
但是,我有两个问题:
dynamic_cast<T *>
作为instanceof
的替代品的缺陷(例如Java中的内容)Scene
基本上遍历它包含的每个 Entity *
,检查它是否与给定的Entity *
发生碰撞并最终投射它以检查它是否存在来自另一个给定的类。如果
醇>
答案 0 :(得分:0)
在性能部分,最好用原始类型在单独的向量中分隔实体。不仅你可以专门测试一个平面与一个球体,例如它不需要完全使用dynamic_cast( - >额外的加速)。此外,由于您已经将向量中的类型分开,因此您可以忽略虚拟函数并进行非虚拟调用,从而提供额外的性能提升; 所以你的场景看起来像这样:
class scene
{
std::vector<PlaneEntity> m_planes;
std::vector<CircleEntity> m_circles;
};
关于设计,在交叉原始时选择正确的算法要容易得多: 这是基于此设计的基本碰撞检查的示例:
void colide(const PlaneEntity & e)
{
for each plane
call plane vs plane collision
for each circle
call plane vs circle collision;
};
void colide(const CircleEntity & e)
{
for each plane
call plane vs circle collision;
for each circle
call circle vs circle collision;
};
所以回答你的问题:
1:使用或不使用dynamic_cast不是规则天气,众所周知,不使用它对性能更好。
2:上述设计完全没有效果。你的动态演员设计也更慢。为了改善这一点,你需要研究加速结构(这是一个很大的主题,所以我不能在这里解释所有内容)来加速碰撞检测。它们基本上减少了每个原语的冲突检查次数,从而大大提高了性能。基本结构是KD-Tree,Quad-Trees,Spacial-Hash,Grid等。你可以通过google来找到每个代码的大量代码。
希望这有帮助, Raxvan。