【AI-Steering编程】三.避开机车

来源:互联网 发布:淘客助手插件下载mac 编辑:程序博客网 时间:2024/04/30 12:20

三.避开行为3.1目的
避开行为与寻找行为相反,避开指定点
3.2实现
l计算到目标的转向力
l随转向力转向,实现避开行为
3.3讨论
l计算到目标的转向力
关于转向力的计算与寻找算法的一样,可以参考上一章.
l随转向力转向,实现避开行为
寻找行为是把机车向target拉,避开行为则是把机车往target外推,所以把add(force)改成substract(force)即可:

                   public function flee(target:Vector2D):void {
                            var desiredVelocity:Vector2D = target.substract(_position); 
                            //计算desiredVelocity
                            desiredVelocity.normalize();                                                                   
                            //将desiredVelocity单位化
                            desiredVelocity = desiredVelocity.multiply(_maxSpeed);              
                            //desiredVelociy乘以最大速度maxSpeed,最大速度向目标前进
                           
                            var force:Vector2D = desiredVelocity.substract(_velocity);
                            //计算转向力
                            steerForce = _steerForce. substract (force);
                            //将计算出来的转向力与原转向力做矢量差
                   }

文档Flee类与上一章相比,只是将seek改为了flee如下:

                   private function enterFrameHandler(e:Event):void {
                            vech.flee(targetObj.position);
                            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;
                            }
                   }

3-2-flee1.swf (3.62 KB)


效果示例” 3-2-flee1.swf”里,机车一闪而过,那是因为机车一直避开targetObj行驶,所以刚一出来就跑出舞台了.所以我们针对机车行驶到边缘时进行一个处理.
当机车行驶到边缘时,如果不冲出舞台,那么会有两种边缘行为edgeBehavior:折返和卷屏.我们先给这个边缘行为进行定义:

                   private var _edgeBehavior:String = "wrap";//边缘行为,默认为卷屏

                   public function set edgeBehavior(value:String):void {
                            _edgeBehavior = value;
                   }
                   public function get edgeBehavior():String {
                            return _edgeBehavior;
                   }

然后定义两种边缘行为:

                   private function bounce():void {
                            if (stage == null) return;
                           
                            if (_position.x < 0) {
                                     _position.x = 0;
                                     _velocity.x *= -1;
                            }else if (_position.x > stage.stageWidth) {
                                     _position.x = stage.stageWidth;
                                     _velocity.x *= -1;
                            }
                            if (_position.y < 0) {
                                     _position.y = 0;
                                     _velocity.y *= -1;
                            }else if (_position.y > stage.stageHeight) {
                                     _position.y = stage.stageHeight;
                                     _velocity.y *= -1;
                            }
                   }
                   private function wrap():void {
                            if (stage == null) return;
                            if (_position.x < 0) _position.x = stage.stageWidth;
                            if (_position.x > stage.stageWidth) _position.x = 0;
                            if (_position.y < 0) _position.y = stage.stageHeight;
                            if (_position.y > stage.stageHeight) _position.y = 0;
                   }

update方法中添加对边缘行为的判断:

                   public function update():void {
                            velocity = _velocity.add(_steerForce);                //速度与转向力的矢量叠加
                            _position = _position.add(_velocity);                 //位置与速度的矢量叠加
                           
                            this.x = _position.x;
                            this.y = _position.y;
                            //判断并设置边缘行为
                            if (_edgeBehavior == "bounce") {
                                     bounce();
                            }else if (_edgeBehavior == "wrap") {
                                     wrap();
                            }
                            this.rotation = _velocity.angle * 180 / Math.PI;
                   }

运行的结果请参考示例” 3-2-flee2.swf”.
上面的示例看起来有些单调,而且由于机车一直在避开targetObj行驶,这样持续下去,你会发现机车一直贴着边儿走(如下图),
3-1.jpg


3-2-flee2.swf (3.66 KB)
所以为了让示例不那么单调,我又添加了一个红色的机车redVech进去,然后,让红色的机车redVech去寻找白色机车vech,而白色的机车vech避开redVech行驶,来看一下文档Main类代码:

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 Flee extends Sprite
        {
                private var vech:Vehicle;                        //机车实例               
                private var redVech:Vehicle;                //添加红色的机车,来seek白色的机车
               
                public function Flee()
                {
                        vech = new Vehicle();
                        vech.position = new Vector2D(100, 200);
                        vech.edgeBehavior = Vehicle.BOUNCE;//定义机车的边缘运动方式
                       
                        redVech = new Vehicle(0xff0000);
                        redVech.position = new Vector2D(300, 300);
                        redVech.edgeBehavior = Vehicle.BOUNCE;

                        addChild(vech);
                        addChild(redVech);
                       
                        addEventListener(Event.ENTER_FRAME, enterFrameHandler);
                }
                //按照帧频随速度更新机车的位置
                private function enterFrameHandler(e:Event):void {
                        //vech机车追redVech
                        vech.flee(redVech.position);
                        vech.update();
                        //redVech机车追vech机车
                        redVech.seek(vech.position);
                        redVech.update();
                        }
                }
        }
}


讨论到这里,本章的内容就介绍完了,最终的结果如” 3-2-flee3.swf”.
3-2.jpg

3-2-flee3.swf (4.02 KB)


本章的源码如下:
chapter3.rar (23.61 KB)