七.漫游行为
“漫游行为”就像它的名字一样,机车在场景中漫无目的的游走,对于漫游的的解释,我就不掺假了,还是完全套用<AdvancED ActionScript3>中的官方解释:
漫游是指角色在场景中毫无目的的移动.这通常用来模拟巡视和觅食,也有纯粹是为了漫游而漫游的.
漫游行为在实现上不像听起来那么容易.简单的使用随机而产生的布朗运动,会让角色感觉像一个神经病的傻瓜.我们需要更自然更平滑的感觉.有个办法,通常设想在角色前方有个圆,然后把圆上任意一点作为目标,每次更新都想这个随机点移动.由于目标点总是落在假象的圆上,所以转向力永远不会一下子就变化很大.可以参照右图加以理解!
7.1 目标
如<AdvancED ActionScript3>的描述,实现机车的漫游行为.
7.2 实现
l创建圆
l在圆上添加随机点,引导机车转向
l向圆上的随机点转向
7.3 讨论
l创建圆
像<AdvancED ActionScriopt3>中描述的那样,在机车的正前方添加一个圆.要添加圆,就一定要有圆心,这一点你不会反对吧.这个圆心处在机车的正前方,也就是说要在velocity的延长线上,通过上面的图解也能看的出来,那这个圆心离机车多远呢?我们定义这个距离为_wanderDistance:
private var _wanderDistance:Number = 50; //机车漫游的圆心位置
public function set wanderDistance(value):void {
_wanderDistance = value;
}
public function get wanderDistance():Number {
return _wanderDistance;
}
然后是圆心的计算 :
var center:Vector2D = _velocity.clone().normalize().multiply(_wanderDistance);
//在机车的正前方_wanderDistance位置,添加圆的圆心
再多啰嗦两句 ,velocity.clone().normalize() 的作用是将 velocity 单位化 , 因为我们要的只是 velocity 的方向 , 然后在velocity 的方向上乘以 _wanderDistance 就是圆心的位置了 ! 另外 , 圆心的位置是实时更新的 , 所以上面的代码在 wander 方法中 , 要和 update 方法一起更新的 .
圆心定下来了 , 下面是圆的半径 :
private var _wanderRadius:Number = 30; //机车漫游目标的范围
public function set wanderRadius(value):void {
_wanderRadius = value;
}
public function get wanderRadius():Number {
return _wanderRadius;
}
l 在圆上添加随机点 , 引导机车转向
这样 , 图中的那个圆我们就 ” 画出来了 ”, 然后 , 就是在圆上添加随机的点 , 引导机车转向 .
所谓随机是相对于圆心来讲的 . 所以随机点的位置可以用圆心矢量 center 加上偏移矢量 offset, 为了让随机点落在圆上 , 我们就把偏移量 offset 的长度限定为半径 wanderRadius. 然后随机化偏移量 offset 的角度就好了 , 代码如下 :
var offset:Vector2D = new Vector2D(0);
//随机点与圆心的偏移量
offset.length = _wanderRadius;
//为是随机点落在圆心上,限定偏移量的长度为_wanderRadius
offset.angle = _wanderAngle;
//随机偏移的角度
_wanderAngle += (Math.random()-0.5);
var force:Vector2D = center.add(offset);
//圆心矢量加偏移矢量确定随机点,随机点确定后,直接添加随机点方向的转向力.
l 向圆上的随机点转向
随机点确定后 , 直接添加随机点方向的转向力 force, 然后这个转向力 force 与之前的 steerForce 叠加即是新的作用力 :
steerForce = _steerForce.add(force);
//讲计算出来的转向力与原转向力叠加
讨论完上面的内容后 , 完整的 wander 方法如下 :
public function wander():void {
var center:Vector2D = _velocity.clone().normalize().multiply(_wanderDistance);
//在机车的正前方_wanderDistance位置,添加圆的圆心
var offset:Vector2D = new Vector2D(0);
//随机点与圆心的偏移量
offset.length = _wanderRadius;
//为是随机点落在圆心上,限定偏移量的长度为_wanderRadius
offset.angle = _wanderAngle;
//随机偏移的角度
_wanderAngle += (Math.random()-0.5);
var force:Vector2D = center.add(offset);
//圆心矢量加偏移矢量确定随机点,随机点确定后,直接添加随机点方向的转向力.
steerForce = _steerForce.add(force);
//讲计算出来的转向力与原转向力叠加
}
文档 Wander 类如下 :
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 Wander extends Sprite
{
private var wanderVehicle:Vehicle; //漫游机车实例
public function Wander()
{
wanderVehicle = new Vehicle();
wanderVehicle.position = new Vector2D(100, 200);
addChild(wanderVehicle);
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
//按照帧频随速度更新机车的位置
private function enterFrameHandler(e:Event):void {
wanderVehicle.wander();
wanderVehicle.update();
}
}
}
运行结果示例如 ” 7-1-Wander.swf”( 如下右图 ).
7-1-Wander.swf (4.37 KB)
7-2-Wander.swf (4.41 KB)
本章源代码:
chapter7.rar (20.46 KB)