游戏设计----常见的碰撞检测

前言

碰撞检测俗称体积碰撞,这是实时渲染中不可忽视的一面。碰撞检测让客户看来,应该非常我们的日常实际,不被察觉出来是最好的结果。

一、BVTree技术

BVTree技术的出现就是在模型外面建立分层的包围盒,将问题分隔,以略微提升空间的复杂度为代价,大大降低了时间复杂度。BVTree根据实现的不同,可以包含AABBTree,Sphere Tree,OBB Tree,K-Dop Tree等。常见的包围盒大体上有四种:AABB包围盒、包围球Sphere、方向包围盒OBB、固定方向凸包FDH(K-dop)。

1.AABB包围盒

AABB 包围盒就是采用一个长方体将物体包裹起来,进行两个物体的相交性检测时仅检测物体对应包围盒(包裹物体的长方体)的相交性。

另外,AABB 包围盒有一个重要特性,那就是包围盒对应的长方体每一个面都是与某个坐标轴平面平行的,因此,AABB 包围盒又称了 轴对齐包围盒 。

有了上述约定后,确定 AABB 包围盒就简单多了,仅需要记录 6 个值即可,这 6 个值分别代表包围盒在每个坐标轴上的最小值与最大值,即 xmin、xmax、ymin、ymax、zmin、zmax。

2.包围球Sphere

包围球碰撞检测方法是用球体包围整个几何体, 无论是几何体还是相交测试都很简单; 但是它的紧密性太差。因为除了在3 个坐标轴上分布得比较均匀的几何体外, 几乎都会留下较大的空隙, 需要花费大量的预处理时间, 以构造一个好的层次结构逼近对象。当物体变形之后,包围球树需要重新计算。因此,它是使用得比较少的一种包围盒。当对象发生旋转运动时, 包围球不需作任何更新, 这是包围球的较优秀特性; 当几何对象进行频繁的旋转运动时, 采用包围球可能得到较好结果。

3.方向包围盒OBB

OBB是包围对象最小的长方体,这是较为常用的包围盒,可以根据物体表面的顶点,通过主成分分析获得特征向量(即OBB的主轴),以此建立包围盒,相对而言,这种方式的较为紧密,但是生成和相交检测较为复杂。而且OBB可以随着人物的方向旋转,也可以称得上是会旋转的AABB包围盒。

4.固定方向凸包FDH

FDH是 AABB的变体,继承了AABB的简洁,被定义为包含该对象且它的所有面的法向量都取自一个固定的方向集合的凸包,FDH是最为紧密的一种,但是相交检测最为复杂,可以用于软体对象的碰撞检测。在许多环境中,因为性能限制或者因为细节过于细微以至不易察觉,使用包围盒进行碰撞检测的结果直接看作最终结果的无限接近值也是一种选择。在空间中,一般都有许多物体,通过简单的计算,x个物体之间通过暴力求相互之间的碰撞检测需要x(x-1)/2次,时间复杂度为O(x平方),这样的性能开销是难以接受的。

二、GJK Tree

GJK是一个迭代算法,但是如果事先给出穿透/分离向量,则它的收敛会很快,可以在常量时间内完成。在3D环境中,GJK可以取代SAT算法。GJK算法的最初目的是计算两个凸体之间的距离,在两个物体穿透深度比较小的情况下,可用它判定物体之间的碰撞。它也可以和别的算法相结合,用来检测两个物体之间深度穿透时候的碰撞情况。JK算法的优势是:通过support函数,从而支持任何凸体形状之间的碰撞检测;相比SAT算法,你不需要一些额外的操作,比如增加特殊的代码和算法处理曲面形状。

1.Support函数

support函数,给定两个凸体,该函数返回这两个凸体明可夫斯基差形状中的一个点。我们知道,物体1上的一个点,它的位置减去物体2上的一个点的位置,可以得到它们明可夫斯基差形状上的一个点,但我们不希望每次都得到相同的点。如何保证做到这一点呢?我们可以给support函数传递一个参数,该参数表示一个方向(direction),方向不同,得到的点也不同。

在某个方向上选择最远的点有重要作用,因为这样产生的单纯形包含最大的空间区域,增加了算法快速返回的可能。另外,通过这种方式返回的点都在明可夫斯基差形状的边上。如果我们不能通过一个过原点的方向在单纯形上增加一个点,则明可夫斯基差不过原点,这样在物体不想交的情况下,算法会很快退出。

 public Point support(Shape shape1, Shape shape2, Vector d) {
 // d is a vector direction (doesn't have to be normalized)
 // get points on the edge of the shapes in opposite directions
 Point p1 = shape1.getFarthestPointInDirection(d);
 Point p2 = shape2.getFarthestPointInDirection(d.negative());
 // perform the Minkowski Difference
 Point p3 = p1.subtract(p2);
 // p3 is now a point in Minkowski space on the edge of the Minkowski Difference
 return p3;
 }

2.明可夫斯基和(Minkowski Sum)

GJK算法中使用了明可夫斯基和的概念。明可夫斯基和很好理解,假设有两个物体,它们的明可夫斯基和就是物体1上的所有点和物体2上的所有点的和集。用公式表示就是:
A + B = {a + b|a∈A, b∈B}
如果两个物体都是凸体,它们的明可夫斯基和也是凸体。

对于减法,明可夫斯基和的概念也成立,这时也可称作明可夫斯基差。
A – B = A + (-B) = {a + (– b)|a∈A, b∈B} = {a – b)|a∈A, b∈B}

3.单纯形(Simplex)

我们不需要显式计算物体之间的明可夫斯基差,只要知道它们的明可夫斯基差是否包含原点就ok了。如果包含原点,物体之间就相交,否则,则不相交。
我们可以在明可夫斯基差形成的物体内迭代的形成一个多面体(或多变形),并使这个多面体尽量包围原点。如果这个多面体包含原点,显然明可夫斯基差形成的物体必然包括原点。这个多面体就称作单纯形。

总结

同样的还有以前常用的BSP Tree,这个还涉及到相应的检测方式,我将在我的下一篇文章详细简绍。

GJK算法参考:heyuchang666 博主

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
推箱子是一种经典的益智游戏,HTML5提供了丰富的功能和工具,可以用于设计开发推箱子游戏。以下是一些关键步骤和技术,帮助您开始设计HTML5推箱子游戏: 1. 游戏场景设计:确定游戏界面大小和样式。使用HTML5的Canvas元素来绘制游戏场景,并使用CSS样式来美化界面。 2. 关卡设计设计不同难度的关卡,包括地图布局、箱子位置、目标位置等。可以使用数组或JSON对象来表示关卡信息。 3. 状态管理:使用JavaScript来管理游戏的状态,包括玩家位置、箱子位置、目标位置等。通过监听用户输入事件,实现玩家移动和箱子推动的逻辑。 4. 碰撞检测:实现玩家和箱子与墙壁、其他物体之间的碰撞检测。可以使用碰撞框或像素级碰撞检测算法来判断物体是否重叠。 5. 动画效果:为了增加游戏的可玩性和视觉效果,可以使用CSS3或JavaScript动画库来实现平滑的移动和箱子推动效果。 6. 存档和关卡编辑器:实现游戏的存档功能,让玩家可以保存当前进度或分享给其他人。另外,开发一个关卡编辑器可以让玩家自定义和分享自己设计的关卡。 7. 移动设备适配:考虑到HTML5游戏可在移动设备上进行游玩,需要做好响应式设计和触摸事件处理,以提供良好的移动端体验。 这些是设计HTML5推箱子游戏的一些基本步骤和技术要点。当然,根据您的实际需求和创意,您还可以添加更多功能和特性,以打造出独特的推箱子游戏体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值