游戏追踪算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
利用向量计算实现游戏中的追踪算法
游戏中的追踪效果很常见,如飞行游戏中各种敌方战机会追着玩家跑,这样的算法有很多,本文介绍了一种利用向量计算来实现的追踪算法。
l讨论之前
假设有对象:(对象类型为自定义的Sprite型。具体定义请参照例程)
m_pPrey:被追踪者
m_pAtta:追踪者
我们主要关心它们的如下成员变量,其他在此可以不必去追究:
1.速度:表示其移动速度。POINT型,其中x与y分量分别表示x与y方向的速度。
2.位置:RECT型,表示其位置。
3.此外还有一个Update成员函数,其功能是根据对象的速度与当前位置来更新其位置,产生移动。此函数由游戏引擎的循环在每次刷新时调用。
即:
新位置=旧位置+速度
注:以下讨论均假定窗口左上角为原点,x向右递增,y向下递增。
图1.坐标系说明
l产生追逐效果的最简单算法
图2.简单追逐算法
追逐就是要使追逐者m_pAtta朝着一个目标点方向移动,而这个目标点就是被追逐的对象m_pPrey。最简单的方法就是比较它们两个的位置坐标,如果m_pAtta在m_pPrey左边,则让m_pAtta的x速度为正,反之负。如果m_pAtta在m_pPrey下边,则使m_pAtta的y速度减小成为负值,反之增加成为正值。程序如下:
程序说明:
n函数SetVelocity(x,y)用来设定X,Y方向的速度大小。
n函数GetVelocity()用来获得移动速度,返回值为POINT型。
n函数GetPosition()用来获得对象的位置,返回值为RECT型。
n使用max与min函数来限定速度的最大最小值,防止速度过大或过小。
这个算法虽能够实现简单的追踪。但是很多情况下效果却不够理想。下面将介绍一种称为视线追踪的改进算法。
l 视线追踪算法
如图3所示,在每一时刻追踪者会沿着其与被追踪者之间的直线方向运动。即所谓的视线追踪。
a
c=a-b c
X
Y b
图3.视线追踪 图4.向量减法 此问题的关键在于求出连接追踪者与猎物之间的直线。由向量知识可以知道:两个向量相减关系如图4所示。
所以,可以分别用追踪者与猎物的位置坐标构造出两个向量,假设b 代表追踪者位置向量,a 代表猎物位置向量。做向量减法a-b 便得到了向量c ,将c 的起点置于追踪者的位置上,就得到了一条指向猎物的向量c 。
此时,令:
追踪者X 方向速度 追踪者Y 方向速度 =c 向量x 轴分量 c 向量y 轴分量 追踪者就会按照向量c 的方向移动。即朝向猎物直线移动。程序如下:
注:关于Vector类的定义及内容,请见例程
l拦截追踪
前两种追踪方法实现简单,但是有缺点,就是追踪者走的距离较长,如果追踪者的速度小于猎物的速度,那么就不会追上猎物,只会跟在猎物后面移动。在一个足球类游戏中,如果防守队员使用了视线追踪很可能就会错过最佳的防守时机。在现实生活中,我们总是会先判断对方的速度和方向并计算出最佳的拦截点,于是我们向着此点移动,就会很快追上对方。除非对方速度比自己大很多。
图5.拦截追踪
这并不是求一个点到一条直线最短直线的问题,因为也许当追踪者到达S1点的时候,猎物已经超过S1点了。所以最佳的拦截点并不一定是S1。我们假设最佳拦截点是S2,由速度与位移的关系很容易知道 S2=Sp+t*V。其中t是追踪者追上猎物的时间。接下来问题变为一个简单的追击问题,求追击时间t。
两个火车同向而行,速度已知,问多久能够相遇。这个问题相信是再熟悉不过了,两个火车的距离差除以速度差就是追上所用的时间。二维的追击问题也是如此。首先我们建立追踪者与猎物的速度向量Va与Vp,及位置向量Sa与Sp。
设速度差向量 Vd =Vp-Va 。称为靠拢速度。
设距离差向量 Sd =Sp-Sa 。称为靠拢距离。
于是,靠拢时间 t=|Sd|/|Vd| 。即路程除以速度等于时间。
套用公式S2=Sp+t*V 就得到了拦截点S2,剩下的过程就与视线追踪一样了。只是目标点变为了拦截点S2。程序如下:
注:程序在GameEngine.cpp文件的RunAI()函数中。
参考资料:
l David M. Bourg, Glenn Seeman ·《AI for Game Developers》·O'Reilly·July 2004
作者:冰里的虫子(Luo Chong)
Email:Chong.l85@ cluo85@
QQ:23806653