十.群落行为
看大雁,快看快看,一会排成”S”形,一会儿排成”B”形,多么可爱啊!!
哈哈,开个玩笑了,本章的群落行为还没有那么智能,能排出”SB”来,讲到这里我就不用再解释群落行为了吧!
1目的
实现像大雁那样的群落行为
2实现
l计算平均位置averagePosition和平均速度averageVelocity
lSeek平均位置和平均速度,别太远也别太近
3讨论
l计算平均位置averagePosition和平均速度averageVelocity
在一个群落整体中行走,呀,离A有点远了,赶紧追上,有离B有点远,再往B那么去一点,恩?离C怎么那么近啊,不行得离C远点,要不就撞到C了…我要走多快呢?按照A的速度走吧,不行,A走的太快了,会把C落下的,按照B的速度走吧也不行,会被C追上的…
通过上面的思路,大概就应该知道机车改怎么走了;
机车要在A,B,C的平均位置上,这样既不会离A太远,也不会离C太近;
那么速度呢,按照A,B,C的平均速度行驶.这样既不会被落下,也不会被追上.
好了,我们来看看代码是怎么实现的吧,
首先是定义平均变量:
//平均速度
var averageVelocity:Vector2D = _velocity.clone();
//平均位置
var averagePosition:Vector2D = new Vector2D();
//机车能看到的对象个数
然后是计算平均变量:
//收集平均变量
averageVelocity=averageVelocity.add(vehicle.velocity);
averagePosition=averagePosition.add(vehicle.position);
lSeek平均位置和平均速度,别太远也别太近
平均位置和平均速度定下来了,那么就像这个位置以平均速度出发吧
if (inSightCount > 0) {
//<span style="color:#ff0000;">将平均变量平均一下</span>
averageVelocity = averageVelocity.divide(inSightCount);
averagePosition = averagePosition.divide(inSightCount);
seek(averagePosition);
<span style="color:#ff0000;">_steerForce.add(averageVelocity.substract(_velocity));</span>
}
但是也不能太近,否则还是会相撞的:
if (tooClose(dist)) {
//如果离C太近了,就躲开
flee(vehicle.position);
}
public function flock(vehicles:Array):void {
//平均速度
var averageVelocity:Vector2D = _velocity.clone();
//平均位置
var averagePosition:Vector2D = new Vector2D();
//机车能看到的对象个数
var inSightCount:int = 0;
for (var i:int = 0; i < vehicles.length; i++) {
//vehicles数组里存放的是所有的机车
var vehicle:Vehicle = vehicles[i] as Vehicle;
//<span style="color:#ff0000;">与当前机车对象的距离</span>
var <span style="color:#ff0000;">dist:Number </span>= _position.dist(vehicle.position);
if (vehicle != this && inSight(vehicle, dist)) {//非本车的机车如果<span style="color:#ff0000;">在本车的视野之内</span>,继续往下运行
//收集平均变量
averageVelocity=averageVelocity.add(vehicle.velocity);
averagePosition=averagePosition.add(vehicle.position);
if (tooClose(dist)) {
//如果离C太近了,就躲开
flee(vehicle.position);
}
inSightCount++;
}
}
if (inSightCount > 0) {
//将平均变量平均一下
averageVelocity = averageVelocity.divide(inSightCount);
averagePosition = averagePosition.divide(inSightCount);
<span style="color:#ff0000;">seek(averagePosition);</span>
_steerForce.add(averageVelocity.substract(_velocity));
}
}
下面的inSight和tooClose是附带的,.
<span style="white-space:pre"> </span>// <span style="font-family: 'Times New Roman';">distance:Number 是离机车的距离。</span><span style="font-family: 'Times New Roman';">vehicle:Vehicle</span><span style="font-family: 'Times New Roman';"> 是机车 </span>
public function inSight(vehicle:Vehicle, distance:Number):Boolean {
//不再视野范围内,返回FALSE
if (distance > _inSightDist) return false;
//这个算法如果看过wander一章,理解起来就不难了,这里就不再重复了
var heading:Vector2D = _velocity.clone().normalize(); //智能体朝向
var difference:Vector2D = vehicle.position.substract(_position); //机车的位置 减去 智能体的位置
var dotProd:Number = difference.dotProd(heading); //<span style="font-family: 'Times New Roman';">智能体朝向 点乘 朝向机车位置差 得到heading方向的长度</span>
if (dotProd < 0) return false; //视野是180度。在后面自然不在视野范围内。
return true;
}
public function tooClose(distance:Number):Boolean {
//是否太近 <pre name="code" class="plain" style="font-size: 14px; line-height: 21px;"><span style="font-family: 'Times New Roman';">// distance:Number 是离机车的距离。如果小于</span><span style="font-family: 'Times New Roman';">_tooCloseDist 的话则 表示太近了,就flee 离开</span>
return distance < _tooCloseDist; } }