四.到达行为 4.1 目的
到达行为是寻找行为的特殊情况,靠近目标后,减速并停止在目标位置上
4.2 实现
l寻找目标
l判断与目标的距离是否在arrivalThreshold内,如果在arrivalThreshold内,减速直到停在目标位置
4.3 讨论
在” 2-1-force2.swf ”的示例中,停止移动鼠标 细细观看,你会发现机车一直在鼠标的前后徘徊,这是为什么呢?回头看看我们的算法 可以找到答案.机车想目标的移动一直都是以最大的速度maxSpeed进行移动的,所以,跑过头之后,有以最大的速度再跑回来,又过头,然后又以最大的的速度跑回来,又过头….
当机车在靠近目标时,减速移动,并最后停在目标的位置上,这就是到达行为.
l寻找目标
向seek方法中对目标寻找的算法还是不能少的,但是对速度大小设置上,判断不同的情况,进行不同的设置.
public function arrive(target:Vector2D):void {
var desiredVelocity:Vector2D = target.substract(_position);
//计算desiredVelocity
desiredVelocity.normalize();
//将desiredVelocity单位化
//desiredVelocity = desiredVelocity.multiply(_maxSpeed);
//desiredVelociy乘以最大速度maxSpeed,最大速度向目标前进,这是seeking的算法,在arrive中我们不会直接讲速度设置为大,为了能进行判断,我们增加了一个arrivalThreshold属性,具体请看下一节.
var force:Vector2D = desiredVelocity.substract(_velocity);
//计算转向力
steerForce = _steerForce.add(force);
//讲计算出来的转向力与原转向力叠加
}
l判断与目标的距离是否在arrivalThreshold内
人的视力范围总是有限的,晴天是100米,雾天可能就是40米,当在我的可是范围内出现其他的汽车时,我们肯定会减速慢行,然后在力其他汽车3~4远的地方停下(干嘛要停下?绕过去就好了!嘿嘿,”绕过去”是后面章节的内容,本节只能停下来).在vehicle类中,我们也给机车增加了”可是范围”_arrivalThreshold属性,来让机车”看到”目标后减速慢行:
private var _arrivalThreshold:Number = 20; //机车的视力范围
public function set arrivalThreshold(value:Number):void {
_arrivalThreshold = value;
}
public function get arrivalThreshold():Number {
return _arrivalThreshold;
}
接下来就是当机车看到目标之后的减速慢行,上一节提到过的.
我们分两种情况,a.目标没有出现在机车”视力范围”内时,机车最大速度想目标行驶,b.目标出现在机车”视力范围”内时,机车的速度等于距离目标与”视力范围”的比率乘以最大速度.具体算法如下:
public function arrive(target:Vector2D):void {
var desiredVelocity:Vector2D = target.substract(_position);
//计算desiredVelocity
desiredVelocity.normalize();
//将desiredVelocity单位化
var distance:Number = _position.dist(target);
//机车与目标的距离
if (distance < _arrivalThreshold) {
desiredVelocity = desiredVelocity.multiply(_maxSpeed * distance / _arrivalThreshold);
//机车的速度等于距离目标与”视力范围”的比率乘以最大速度
}else {
desiredVelocity = desiredVelocity.multiply(_maxSpeed);
//desiredVelociy乘以最大速度maxSpeed,最大速度向目标前进
}
var force:Vector2D = desiredVelocity.substract(_velocity);
//计算转向力
steerForce = _steerForce.add(force);
//讲计算出来的转向力与原转向力叠加
}
文档Arrive类,只需要相应的做出一些简单的调整,由seek目标改为arrive目标:
package
{
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import ladeng6666.steering.Vector2D;
import ladeng6666.steering.Vehicle;
import ladeng6666.steering.TargetObj;
public class Arrive extends Sprite
{
private var vech:Vehicle; //机车实例
private var redVech:Vehicle; //添加红色的机车,来seek白色的机车
private var targetObj:TargetObj; //机车到达的目标
public function Arrive()
{
vech = new Vehicle();
vech.position = new Vector2D(100, 200);
vech.edgeBehavior = Vehicle.BOUNCE;
targetObj = new TargetObj();
addChild(vech);
addChild(targetObj);
targetObj.x = Math.random() * 400;
targetObj.y = Math.random() * 400;
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
//按照帧频随速度更新机车的位置
private function enterFrameHandler(e:Event):void {
vech.arrive(targetObj.position);
//由seek目标改为arrive目标
vech.update();
var dis:Vector2D = vech.position.substract(targetObj.position);
if (dis.length < 5) {
targetObj.x = Math.random() * stage.stageWidth;
targetObj.y = Math.random() * stage.stageHeight;
}
}
}
}
运行上面的结果后 ,可以很明显的看到 ,目标在机车 ”视力范围 ”外时 ,蓝色速度的长度最大 ,目标出现在机车 ”视力范围 ”内时 ,机车的蓝色速度明显有变小 ,如下图 .
4-1-arrive.swf (4.13 KB)
本章的源码如下:
chapter4.rar (15.05 KB)