我一直很想知道这个问题。在像GTA这样的游戏中,有成千上万个物体,游戏怎么会立即知道你是否在医疗包附近呢?
显然不可能为每个物体都设置一个事件监听器,迭代也不是好的选择。我只是想知道它是如何实现的。
我一直很想知道这个问题。在像GTA这样的游戏中,有成千上万个物体,游戏怎么会立即知道你是否在医疗包附近呢?
显然不可能为每个物体都设置一个事件监听器,迭代也不是好的选择。我只是想知道它是如何实现的。
关于如何处理大型世界的空间分割方法,通常会使用类似四叉树或kd树的方式进行划分,这样可以使得查找最近邻居的时间复杂度降低到线性以下(分数幂次,或者在3D游戏中为O(N^(2/3)))。这些方法通常被称为二进制空间划分(BSP)。
对于碰撞检测,每个物体通常还有一个与之关联的包围盒网格(由一组构成凸多面体的多边形组成)。这些高度简化的网格(有时只是一个立方体)不绘制,而是用于检测碰撞。最原始的方法是创建一个垂直于连接两个物体中点的线的平面,并将该平面与该线相交于中点处。如果一个物体的包围盒在该平面的两侧都有点,则发生碰撞(只需要测试其中一个包围盒与平面的位置关系)。另一种方法是增强的GJK距离算法。如果您需要一份教程,可以查看NeHe Productions的OpenGL第30课。
顺便提一下,包围盒还可用于其他优化,例如所谓的遮挡查询。这是一种确定哪些物体在其他物体(遮挡者)后面,因此不需要处理/渲染的过程。包围盒还可用于截锥体剔除,即确定哪些物体在透视视图体积之外(太近、太远或超出您的视野角度),因此不需要渲染。
正如Kylotan指出的那样,使用包围体在检测遮挡时可能会产生错误的阳性结果,并且对于某些类型的对象(例如通过甜甜圈孔洞观察)根本不起作用。让这些对象正确地遮挡是关于“门户剔除”的另一个主题。
没错。通常情况下,并不是每个对象都有一个事件监听器。通常在内存中会有一棵非二叉树结构,模拟你的游戏地图。可以想象成地铁/地下铁路地图。
这种内存结构是游戏中物品的集合。包括玩家、怪物、可捡起的物品或可能爆炸并对你造成伤害的物品。因此,当玩家在游戏中移动时,玩家对象指针会在游戏/地图内存结构中移动。
有很多可以使用的优化。
首先-任何物体(以i为索引)被一个立方体所包围,中心坐标为CXi
,CYi
,尺寸为Si
其次-碰撞检测是基于估计值的:
a) 找到所有满足条件的i、j立方体对:Abs(CXi-CXj)<(Si+Sj) AND Abs(CYi-CYj)<(Si+Sj)
b) 现在只处理a)中获取的一组对。我们更准确地计算它们之间的距离,类似于Sqrt(Sqr(CXi-CXj)+Sqr(CYi-CYj))
,现在对象表示为几个简单图形的集合-立方体、球体、圆锥体-并且我们使用几何公式来检查这些图形的交点。
c) b)中具有检测到交点的对象将作为需要进行物理计算等处理碰撞的对象。