首先,我要假设你已经对一个空间完成了四叉树划分,并得到一棵树( root ),那么对于静态物体,很明显你只需要在预处理阶段一次性插入即可,并且在游戏运行阶段你都无须去关心它们( 除非你用一颗炸弹把它们炸飞,不过那时侯你只要调用树的删除方法就可以了 ).
但是,对于动态物体,你就必须时刻关心它们的动向,因为一旦它们离开了原本所依附的空间节点的区域,而在树中却没有即使的更新,那么就会得到错误的效果,比如渲染错误或碰撞检测错误.
所以我们必须时刻检查移动物体在树中的位置,最笨的方法,我们每次通过物体的id遍历树节点中所有被存放的物体( 不可以通过物体的位置来找原来的节点,因为很可能此时的物体已经不在上一次的位置了,比如悟空的瞬间移动 ),然后我们找到了那个物体,我们需要判断它需不需要被移动到其他节点上,如果需要那最好,如果不需要(还在原来的区域),那么刚才的遍历就全白费了.
这样的效率显然不能忍受,改进方法如下:
对于更新操作,我们所要做的就是把当前物体与原来物体进行比较,看两个物体是否应该在同一个空间区域,如果是,那么就不需更新,如果不是,那么必须把物体从原来的空间节点删除,并连接到新的空间节点下,我们需要的就是找到高效的通过需要被更新的物体来定位这个物体在原来树中的位置,由于当前物体与原来物体在位置上可能已经有很大变化,所以我们不可以利用树来缩小查找范围.
但是我注意到,由于我将每个物体都设定了唯一id(在实例化时指定)那么我们只能利用缓冲存储的方法来加快查找,也就是说,我维护一个存放二元组有序表,二元组为( 物体id, 空间节点指针 ),通过这个二元组把当前树中存在的物体与所存放的位置保存起来.
这样,假设我有3层树构成四叉树,更新物体时,我只需:
(1)为当前物体重新搜索应存放的位置,查找次数为对数级
(2)根据当前物体id从缓冲存储得到物体原来所在空间节点,由于我以id为序来维护它,查找次数为对数级
(3)比较新得到的空间节点与原来的空间节点,如果相同,不需要操作,如果不同,从原来的空间节点中删除当前物体,加入新算出的空间节点下,同时别忘了更新缓存中对应二元组的空间节点
这个方法可以比较好的解决可移动物体由于自身位置的不确定而带来的四叉树重新定位的问题,它利用一定数量的存储空间以及一定程序设计的复杂性换来了时间上的节省.