当前位置: 代码迷 >> J2ME >> J2ME Mobile 3D入门教程(3)碰撞初步
  详细解决方案

J2ME Mobile 3D入门教程(3)碰撞初步

热度:2027   发布时间:2013-02-25 21:32:07.0
J2ME Mobile 3D入门教程(三)碰撞初步
前两篇教程写的很仓促,最近又被很多工作缠住,最近才开始给大家带来新的这篇教程。首先向大家道歉。下面言规正传,前面给大家介绍过在JSR-184中物体的创建、移动、旋转。今天我们来说说,更为有用的东西——碰撞检测。不过看过文章后也许你会失望,因为今天我没有给出一行代码,也没有讲解pick()的用法。但是我想要说得是:为了减小系统的开销有些事情是需要我们自己做的。就像碰撞检测并不一定需要系统去做。但是稍候我给大家讲解pick()的用法。

在2维游戏中我们也经常要用到碰撞检测,所以大家都知道45度视角的游戏要比普通横版或竖版游戏更复杂一些,这也是为什么45度视角游戏被称作2.5D游戏的原因。而今天我们要讨论的3D游戏似乎就更复杂了。

别着急让我们来化繁为简,我们现在先来看一个简单的例子。

假设一个物体在一间四壁封锁的屋子里,这个屋子门是紧闭的。不存在物体能从屋子里出来,也不存在物体会跳跃(或者我们假设屋子的天花板是无限高的)。这样一个情况谁都能说出无需碰撞检测,只要限制物体在XZ平面的坐标不超过墙的范围就可以了呀。没错就是这样,我们现在来看图。



图1

图1为上面所描述的3D场景的俯视图。很明显我们只需要显示物体移动的范围的坐标值不要超出墙体的范围就可以了。这确实不需要碰撞检测,不过可不要小看这一思考方式,我下面会告诉你个设计思路就是由他派生出来的。

 

 

图2

在图2中我给出了6个图片,假设白色区域是一个赛车的赛道,黑色区域是非行驶区域,那么我们别把6个区域单独拿出来,按照上面所说的法则去限制赛车的移动,是非常简单的对吧,例如左上角第一张中,我们值限制赛车的X坐标在赛道之间就可以了。现在我们试想一下如果我把这些区域块拼接起来是不是就可构造成一个简单的赛道,当然这里只有直角弯存在,不过已经可以构造出赛道了对吗?同时记录每个区域块所对应的坐标,作为偏移量直接加减到限制条件中;或者赛车不真正移动,只是简单的把赛车从一个区域移动到另一个区域,怎么样?很简单吧?者种设计思路最简单哦,也是最实用的一种。

这个方法虽然很实用,但他有一个很严重的缺点。也许你已经发现了,那就是在拐角处只可以是直角,否则很难判断。那是不是有更好的方法来解决这个问题呢?答案是肯定的。不知道您是否听说过BPS树算法。也许有人要告诉我,那是渲染静态景物用的,这里他有什么用?别着急我们先来简单了解一下BPS树的原理,在BPS树中空间被墙体所在的直线分解为两部分,一部分是墙的前面,一部分是后面,当通过某一点确定摄像机位置后,只渲染墙体正面是对着摄影机的部分墙体。现在思路回来,要移动一个物体,如何判断是否和墙体有碰撞。假设碰撞不存在,物体是任意移动的,如果移动的起点和重点分别在墙的两侧,及分别在墙的正面和反面,结论很简单移动路线和墙体发生交叉了。这样的情况不就是碰撞了吗?现在我们来复习一下数学知识以便我们来分析如何判断物体在墙的片面还是背面



图3

如图3所示,黑线将空间分解为A、B两个部分,假设图中红线为黑线的法线。我们暂定A空间为黑线的正面。现在以o点为起点b点和b’点为终点(b点为正面任意一点,b’为背面任意一点)分别做两条向量,不难法线ob向量与法线向量的夹角永远不可能大于90度,而ob’向量和法线向量的夹角永远不肯能小与90度。这样一来我们很块就能明白某一点是在物体墙体正面还是背面了。也许您会问,如何得到该夹角呢?

在上面的描述中反复的出现的一个次就是向量,现在我们来用向量解角度问题。正如上面说到的,我们只需要判断前面还是背面,那么我也只需要判断是锐角还是钝角。锐角和钝角一个标志性的区分就是他们cos值的取值范围。锐角是大于0的,而钝角恰好是小于0的。向量的点积不恰好是两个向量的莫的乘积乘以向量夹角的cos值吗?而两个莫的乘积必然是大于0的,那么我们就可以通过ob向量和法向量的点积来判断点b是在正面还是背面了。另外向量的点积的运算也很简单

U.V=UXVX+UYVY+UZVZ=|U||V|cosθ

瞧,有了向量后我们只需要简单的3个乘法2个加法就判断出了物体在墙的正面还是后面。

说到现在我只是想给大家一些思路,所以到目前为止我并没有给出一行代码。因为我觉得这次的讲解主要是在讲解数学。还是那句话主要是给大家一个思路。这个思路其实并不局限在JSR-184上,相反这个思路是从DEMO中学过来的。

不过这里也要告诉大家该思路的缺点:

1.  只能判断静态物体和精灵的碰撞

2.  到目前为止我们还没有设计到高度这一维的检测,当然并不是这个思路不可以,仅仅是我觉得没有必要。

我稍候会给大家带来JSR-184中pick用法的讲解,也就是大家一般情况下所说的“碰撞”。