如果我是你,我会先实现一个简单的BSP(二叉空间分区)树。由于你在2D中工作,边界框检查非常快。你基本上需要三个类:CBspTree、CBspNode和CBspCut(不是真正需要的)。
1. CBspTree有一个CBspNode类的根节点实例。
2. CBspNode有一个CBspCut类的实例。
3. CBspCut表示如何将一组物体划分为两个不相交的集合。这可以通过引入多态性来解决(例如CBspCutX或CBspCutY或其他切割线)。CBspCut还有两个CBspNode。
面向分裂世界的接口将通过树类进行,并且最好在其顶部创建另一层,以防您想用例如四叉树替换BSP解决方案。一旦您掌握了它。但是根据我的经验,BSP就足够了。
关于如何在树中存储项目,有不同的策略。我的意思是,您可以选择在每个节点中具有某种容器,其中包含对占用该区域的对象的引用。这意味着(正如您自己问自己的那样),大型项目将占用许多叶子,即大型对象将有许多引用,而非常小的项目将显示在单个叶子中。
在我的经验中,这并没有那么大的影响。当然很重要,但您必须进行一些测试,以检查它是否真的是一个问题。您可以通过简单地将这些项目留在树的分支节点上来避免这种情况,即不会在“叶级别”上存储它们。这意味着在向下遍历树时,您将快速找到这些对象。
至于你的第一个问题。如果您只打算使用此细分进行碰撞测试而没有其他用途,我建议永远不要将永远不可能发生碰撞的物体插入树中。例如,像导弹这样的东西无法与另一个导弹发生碰撞。这意味着您甚至不必将导弹存储在树中。
但是,您可能还想将bsp用于其他方面,您没有指定,请记住这一点(例如使用鼠标选择对象)。否则,我建议您将所有内容存储在bsp中,并稍后解决碰撞。只需向BSP询问某个区域内的对象列表,以获得可能的有限碰撞候选项集,并在此之后执行检查(假设对象知道它们可以与什么碰撞,或者使用其他外部机制)。
如果您想加快速度,您还需要注意合并和拆分,即当树中的内容被移除时,许多节点将变为空或某些节点级别下的项数将减少到某个合并阈值以下。然后,您可以将两个子树合并为包含所有项的一个节点。当您在世界中插入项目时,会发生拆分。因此,当项目数超过某个拆分阈值时,您会引入一种新的分割方式,将世界分成两部分。这些合并和拆分阈值应该是两个常量,您可以使用它们来调整树的效率。
合并和拆分主要用于保持树的平衡,并确保其按照规格尽可能高效地工作。这真的是您需要担心的事情。将物品从一个位置移动并更新树的速度很快。但是,当涉及到合并和拆分时,如果您经常执行此操作,则可能变得昂贵。
可以通过引入某种惰性合并和拆分系统来避免这种情况,即您具有某种脏标记或修改计数。批处理可以批量处理所有可以批量处理的操作,例如移动10个对象和插入5个对象可能是一个批次。完成该批操作后,检查树是否脏,并执行所需的合并和/或拆分操作。
如果您想让我进一步解释,请发布一些评论。
干杯!