<@乌龟:>[翻译]开放街道下的竞速类游戏人工智能(4)
市民:模拟行人
在一个真实的城市里,行人几乎在城市的各个角落,他们自己走自己的,所以我们游戏中的城市里也不能缺少他们.行人沿着街道行走,有的时候也会穿越街道,他们会避开静态的障碍物,比如说邮箱,路灯,停车计时器;同样他们也会避开动态的障碍物,比如其他行人或者玩家控制的车辆.而且玩家不能撞到行人,或者在其身上得到分数(译者注:在GTA中倒是无所谓..)虽然如此,与行人的交互将会增加玩家作为驾驶者的经验,也会使得游戏更加真实.
行人的模拟范围.就像车辆有一个模拟范围一样,行人也有,而且当这个范围比城市小得多的时候,所有类型的处理都是相似的,在初始化的时候,行人被建造出来并被扔到行人池(Pedestrian pool)中.当玩家进入城市之后,行人将会在他附近放置.在放置的过程中,行人被放在行人模拟范围中的路上,按循环的方式,直到行人池中为空.
行人是根据他与道路中心线的距离按照正态分布的.他们同样分配了往什么地方去,在什么地方开始行走.当行人到达模拟范围的边界的时候,他们简单的向后转,往他们来的地方而去.
在城市中漫步.当他们在城市中行走的时候,行人使用样条来使得行走的路线更加平滑,所有的样条都是在二维的环境下创造出来的,以减少运算复杂度.行人的高度是根据他当前的X,Z坐标值来得到地面的实际坐标值的.
每个行人都有一个目标位置来确定他朝向的位置.这个位置是他所行走样条的前方3米远的位置.在行走中.行人可能在每一帧的时候都会改变一点面朝向的位置,在直走和斜走的过程中,有一个参数来调整行人动画的速度.所以行人在路上漫步的时候,ped对象将会在他每经过一个人行道顶点(sidewalk vertex)的时候,计算一个新的样条.
穿越街道.当行人到达街道的尾端的时候,他必须做一个决定,他到底是应该继续到下一个街道或者穿越这个街道.如果行人决定穿越街道,那么他必须决定穿越哪条街道;当前这条还是下一条.四个状态控制着行人在街道上的导航:漫游(Wander),准备穿越街道(PreCrossStreet),等待穿越街道(WaitToCrossStreet),和穿越街道中(CrossStreet).见图三.
第一个”漫游”,是描述着当前的状态,在城市中漫步.
“准备穿越街道”将会使得行人从街道结束的地方移动到街道的边缘.
“等待穿越街道”告诉行人等到红绿灯允许通行的时候再过去.
“穿越街道中”处理了行人从街道的这一边走或者跑到达街道的另一边.
图三:在这种情况下,PreCrossStreet状态已经将行人移动到了街道的边缘,那么,WaitToCrossStreet状态将会保持直到绿灯.
动画行为: 行人动画的核心部分是基于骨骼动画的.特别说明的,动画在3DMAX中是以每秒30帧建立的,然后用咱们公司的似有导出器导出,然后动画系统根据时间来计算每秒播放的帧数(译者注:由于游戏的FPS不一定就是30,所以需要放慢或者加速播放).
对于每个行人模型来说,一个数据文件关联了动画的顺序.由于数据文件删除了注释的部分.所以数据文件指出了必要的向前或者向后行走的数据.为了移动我们的行人,行人对象对向前走和斜线走都是简单的加上总共的距离乘以每帧的时间(全部的动画都没有从一点到另一个点的移动动画)(译者注:也就是说,动画只是记录了原地走的动画,这个时候只需要把行人按照适当的方式来改变位置,看起来就在走路了).
在动画系统中的两个函数是特别滴有用,Start函数立刻开始播放函数参数中指定的参数.还有Schedule函数将会在当前的动画播放完毕后播放.
躲避超速的玩家.行人的一个主要的规则是总是躲避被撞.我们在两个方面来完成它:
1)如果行人在墙边,那么行人冲向墙壁,并且后背贴着墙.直到车辆远离他而去.(图四)
图四.当迎面而来的车辆威胁着行人的生命时.他们决定跑到最近的墙边.
相反的,如果没有墙在附近,那么行人就面对着到来的车辆,直到车辆已经距离他足够的近了(真是临危不惧-_-),然后在最后关头跑向左边或者右边(见图五)
图五:在没有墙壁在附近时,粉红色的线为行人试图行走的路线,当玩家的车辆导致这场威胁的时候,行人在最后关头决定向左跑还是向右跑.
行人对象决定碰撞即将发生(可以开始逃跑了)的算法如下:取出车辆的前进向量,对其做上一个(自身位置-车辆位置)的点乘,得到的结果将用来表示距离车辆的危险距离,如果这个距离比车辆长度的一半还有短,那么就开始逃跑吧!
下一个需要计算的是车辆将会撞到自己的时间(电脑和人就是不一样,J).在这篇文章中,两个距离的范围是这样定义的:近或者远.在”远”的区域内,行人将会面朝汽车,进入”预测(anticipate)”行为,将会导致他在原地瑟瑟发抖然后找准机会逃跑.在”近”的区域内,行人将会激活”躲避”行为,将会导致行人找一个墙壁去躲着.为了定位墙壁,行人对象将会查看他十米内的区域,如果找到了,那么行人就跑向他,或者跑向汽车将去方向的反方向.(有些时候车子开得太快了,那么行人将会爆发出惊人的爆发力来躲避碰撞).
躲避障碍物.当行人在街道上幸福的行走的时候(-_-),他们将会到达道路中的障碍物.障碍物分为三类:1) 其他行人,2)小玩意例如垃圾桶,路灯,3)玩家停在人行道上的车辆.
为了躲避其他行人.每个行人都会检查他当前格子内的其他行人,执行碰撞检测,运行一些列的运算:
得到当前自己与其他行人距离道路中线的距离,如果两个行人的结果是重叠的,那么碰撞将是可能发生的.
为了帮助他们躲避其他人,一个行人可以停在原地让另一个行人过去,为了实现这个方法:一个行人停在原地最短的时间,另一个行人将目标向左或者向右放到足够远以错过当前的行人.行人如果在人行道上,将会始终决定向左走,否则他将会向右走,如果向右走也会超出人行道的边界,那么行人将会转身继续走.
对于其他的障碍物,处理的方法就差不多了.
累了,明天继续翻译 :)
-----------
乌龟和毛驴的技术小屋原创,转载请注明出处