转向行为(steering behaviors)这一术语,指的是一系列使对象行动起来像似长有智商的算法。这些行为都归于人工智能或人工生命一类,是让对象呈现出拥有生命一般,对如何移动到目的地、捕捉或逃避其它对象、避开障碍物、寻求路径等做出因地适宜的决定。
介绍行为,了解行为,展示一个实现这些行为的框架。一些行为根据复杂度不同,实现起来有多种不同方式。所有行为都不存在一个标准或者正确的做法,实现上给出的也是很简单的样式。换句话说,仅从介绍和展示的角度去考虑实现。要是用于产品开发的话,提供的代码需要根据要求做大量调整。
行为
首先,预览一下几个基本行为,看看它们是什么,要干什么。
寻找(seek):角色试图移动到一个指定点。该点可以是一个固定点也可以是把另一个角色作为目标的移动点。
避开(flee):与寻找正好相反。角色试图避开一个给定点。同样,这个点也可以是固定点或者移动点。
到达(arrive):和寻找相同,除了角色的速度在接近目的地时会减慢,最终以一个渐变运动恰好停留在目标处。
追捕(pursue):寻找的加强版。由于目标会做加速运动,所以角色会事先预测然后再移动到该点。很明显,由于固定点是不会有速度概念的,所以这里用目标代替点的概念。
躲避(evade):与追捕正好相反。角色对目标的速度做出预测,然后尽可能躲避开来。
漫游(wander):随机但平滑又真实的运动。
对象回避(object avoidance):角色预测出对象的行动路径,然后避开他们。
路径跟随(path following):角色尽可能的沿着自己的路径移动,但要考虑符合一些真实的物理现象,以及使用其它行为后的影响。
除了这些行为,还有复杂的类似鸟群这样的复合行为,它大致上由以下三种简易行为合成:
分离(separation):鸟群中每个角色都试着和相邻角色保持一定的距离。
凝聚(cohesion):每个角色尽量不掉队,不落下太远。
队列(alignment):每个角色尽可能与相邻角色行动于同一方向。
虽然是三个相对简单的行为,但合在一起时就能产生出难以想象的群体效果,像鸟群或是其它生物群体。调整这三个行为中的各个参数会改变群体的性质,有经常分散的松散型队伍,有紧密的小团体,还有有一个带头的率领着的队伍,等等多种变化。
在让对象按照行为行动起来之前,首先要有一个能让它们动起来的方法。
2D向量(Vector2D)类
转向行为已经被各种语言实现过多次了,其最底层是用向量来描述的(也是最常见的实现方式)。
概括的看,一个向量由两部分组成:一个方向和一个大小。比如,一个运动中对象的速度由它要去哪里(方向)和移动快慢(大小)两部分组成。因此,把速度看作一 个向量是最贴切不过的。加速度——任何改变对象速度的作用力——同样也是由力的方向和大小组成(另一个向量)。向量同样也可以用来描述对象间的位置关系, 其中大小代表距离,方向代表角度。
向量还可以用来表示一个角色(脸)的朝向,这种情况下就只管方向,而忽视大小,也可以说大小等于1。这样的向量叫做单位向量(unit vector)。实际上,只有一单位长度的向量,在数学运算上能起到很大的优化作用。
向量的所有这些特性对转向行为来说都很有用,因为速度,队伍方向,对象间距离,对象的朝向都会被大量的使用。
【代码】
对于实现这样的类,在架构上就存在着挑战,比如决定类的方法该如何工作。对这些方法truncate,normalize,reverse,add,substrat,multiple和divide有两种考虑情况:是直接对调用对象做改变呢,还是返回一个新的对象。
举个例子,假设有vectorA(3,2)意思是x等于3,y等于2,和vectorB等于(4,5),然后执行以下代码:
vectorA.add(vectorB);
根据第一种情况,vectorB不变,而vectorA等于(7,7)。
而另一种情况,vectorA和vectorB都不变,但是产生一个新的等于(7,7)的向量,我们让它等于vectorC。
vectorC = vectorA.add(vectorB);
那么哪种做法才合适呢?对此,我前前后后进行了多番审视,最终发现在很多数学运算时,需要把一个对象——比如位置和速度——用向量来表示,而无所谓运算后对象本身的改变。所以,加、减、乘、除不对原对象进行修改。
然而truncate(截断),reverse(倒置)和normalize(单位化)则更注重对象本身的改变,所以这些操作用来直接改变对象要比返回一个新的更有用。
互换以上操作方式也不是很难。如果想把vectorB加在vectorA上,可以这样:
vectorA = vectorA.add(vectorB);
而如果想让normalize返回一个新的对象,可以使用clone(克隆)函数:
normalizedA = vectorA.clone().normalize();
现在,有了向量类可以表示角色的位置,速度和各种群体。还需要一个类用来表示角色。
转向行为(steering behaviors)这一术语,指的是一系列使对象行动起来像似长有智商的算法。这些行为都归于人工智能或人工生命一类,是让对象呈现出拥有生命一般,对如何移动到目的地、捕捉或逃避其它对象、避开障碍物、寻求路径等做出因地适宜的决定。介绍行为,了解行为,展示一个实现这些行为的框架。一些行为根据复杂度不同,实现起来有多种不同方式。所有行为都不存在一个标准或者正确的做法,实现上给出的也是很简单的样式。换句话说,仅从介绍和展示的角度去考虑实现。
行为 首先,预览一下几个基本行为,看看它们是什么,要干什么。
- 寻找(seek):角色试图移动到一个指定点。该点可以是一个固定点也可以是把另一个角色作为目标的移动点。
- 避开(flee):与寻找正好相反。角色试图避开一个给定点。同样,这个点也可以是固定点或者移动点。
- 到达(arrive):和寻找相同,除了角色的速度在接近目的地时会减慢,最终以一个渐变运动恰好停留在目标处。
- 追捕(pursue):寻找的加强版。由于目标会做加速运动,所以角色会事先预测然后再移动到该点。很明显,由于固定点是不会有速度概念的,所以这里用目标代替点的概念。
- 躲避(evade):与追捕正好相反。角色对目标的速度做出预测,然后尽可能躲避开来。
- 漫游(wander):随机但平滑又真实的运动。
- 对象回避(object avoidance):角色预测出对象的行动路径,然后避开他们。
- 路径跟随(path following):角色尽可能的沿着自己的路径移动,但要考虑符合一些真实的物理现象,以及使用其它行为后的影响。
- 除了这些行为,还有复杂的类似鸟群这样的复合行为,它大致上由以下三种简易行为合成:
- 分离(separation):鸟群中每个角色都试着和相邻角色保持一定的距离。
- 凝聚(cohesion):每个角色尽量不掉队,不落下太远。
- 队列(alignment):每个角色尽可能与相邻角色行动于同一方向。
虽然是三个相对简单的行为,但合在一起时就能产生出难以想象的群体效果,像鸟群或是其它生物群体。调整这三个行为中的各个参数会改变群体的性质,有经常分散的松散型队伍,有紧密的小团体,还有有一个带头的率领着的队伍,等等多种变化。
在让对象按照行为行动起来之前,首先要有一个能让它们动起来的方法。