Steering Behaviors: Pursuit and Evade 追逐和躲避

到目前为止,我们研究了seek,flee,arrival,wander行为。在这个教程,会研究追逐和躲避行为。让角色跟随活着躲避。

追踪是指朝着移动目标运动并试图抓住它,这里说的“抓住”很重要,如果只是朝着目标运动,那基本上只是重复目标的运动轨迹。在追踪的时候,追踪者必须做出一定的预判,如果能够预判出目标接下去几秒的位置,就能够调整自己当前的速度来抓住它。可以预测轨迹,减少不必要的路径。

Pursuing

如同Seek章节里说的,运动用欧拉插值法来表示

position = position + velocity

如果游戏个体的位置和速度是可知的,那就可以预测它在未来一段时间 T 之后的位置。假设被预测的物体是以直线方式运动的,并且我们只预测,三次Update之后的位置。那么游戏个体被预测的位置就是:

position = position + velocity * T

预测的关键是找到合适的 T 的值,如果这个值太大了,那么追踪者会追踪一个太过靠前的幽灵,如果T太小了那么追踪者实际追踪当前个体位置,没有预测成分,变成追随行为。

追踪行为和seek行为工作方式基本差不多,位移区别是追踪的目标不是目标本身而是目标未来的位置。

假设游戏中的个体都叫Boid,下面的伪代码实现了基本的追踪原理:

public function pursuit(t :Boid) :Vector3D {
  T :int  = 3;
  futurePosition :Vector3D = t.position + t.velocity * T;
  return seek(futurePosition);
}

在计算完追踪力后,同样它必须和当前速度相加。

public function update() :void {
  steering = pursuit(target)
  steering = truncate (steering, max_force)
  steering = steering / mass
  velocity = truncate (velocity + steering , max_speed)
  position = position + velocity
}
Pursuit behavior

 

追踪者会顺着橙色的路径,追捕目标。

追逐使用T=30,例子是个Flash不展示了;

当T是一个常数时,会有一个问题:在离目标点很近的距离下,追踪的准确度会变得很差。这是因为当追踪者靠近目标后,追踪者还是以常数T时间后的位置进行预测。这和真实的追踪行为相违背,真实的追铺在靠近物体后会停止预测,并且以物体当前实际位置作为目标点。有一个简单的方式来改进我们上面的追捕逻辑,就是用动态的T来替换之前恒定的T。

T = distanceBetweenTargetAndPursuer / MAX_VELOCITY

新的T根据两个角色间的距离计算得出,新的T的意义是,得出根据追踪者的最大速度,需要多少个Update来逮住目标。距离越长,T就越大,这个时候追踪者就会预测得比较远,相反追踪者会预测最近的时间位置。

public function pursuit(t :Boid) :Vector3D {
  var distance :Vector3D = t.position - position;
  var T :int = distance.length / MAX_VELOCITY;
  futurePosition :Vector3D = t.position + t.velocity * T;
  return seek(futurePosition);
}

让T值变为动态。

 

he evade behavior is the opposite of the pursuit behavior. Instead of seeking the target’s future position, in the evade behavior the character will flee that position:

躲避行为是追逐的相反行为。使用flee来替换掉seek。

Evade

代码基本上相同,只是改变最后一行。

public function evade(t :Boid) :Vector3D {
  var distance :Vector3D = t.position - position;
  var updatesAhead :int = distance.length / MAX_VELOCITY;
  futurePosition :Vector3D = t.position + t.velocity * updatesAhead;
  return flee(futurePosition);
}

发表评论

邮箱地址不会被公开。