在” 2-1-force2.swf”的示例中,停止移动鼠标细细观看,你会发现机车一直在鼠标的前后徘徊,这是为什么呢?回头看看我们的算法可以找到答案.机车想目标的移动一直都是以最大的速度maxSpeed进行移动的,所以,跑过头之后,有以最大的速度再跑回来,又过头,然后又以最大的的速度跑回来,又过头….
这说明每帧更新的方式,会出现过头的现象
抵达 Arrive ,有两种实现,一种是:
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);
//讲计算出来的转向力与原转向力叠加
}
核心算法是 _maxSpeed * distance / _arrivalThreshold,和距离成正比,和可视范围成反比,就是在可视范围内就会减速
--------------------------------------
//这种行为是一种操控智能体慢慢减速直至停在目标位置的行为。
//------------------------------------------------------------------------
Vector2D SteeringBehavior::Arrive(Vector2D TargetPos,
Deceleration deceleration)
{
Vector2D ToTarget = TargetPos - m_pVehicle->Pos();
double dist = ToTarget.Length();
if (dist > 0)
{
const double DecelerationTweaker = 0.3;
//距离越小,速度就越小,因为<span style="font-family: 'Times New Roman';">(double)deceleration * DecelerationTweaker结果是一个大于0小于1的小数。</span>
double speed = dist / ((double)deceleration * DecelerationTweaker);
speed = min(speed, m_pVehicle->MaxSpeed());
Vector2D DesiredVelocity = ToTarget * speed / dist;
return (DesiredVelocity - m_pVehicle->Velocity());
}
return Vector2D(0,0);
}
核心算法是:
double speed = dist / ((double)deceleration * DecelerationTweaker);
通过Deceleration 值得到智能体到达目标位置所希望的时间。然后我们可以计算出在给定的时间必须以多大的速度运行才能到达目标位置。