日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

“AS3.0高级动画编程”学习:第二章转向行为(上)

發布時間:2023/11/27 生活经验 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 “AS3.0高级动画编程”学习:第二章转向行为(上) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

因為這一章的內容基本上都是涉及向量的,先來一個2D向量類:Vector2D.as (再次強烈建議不熟悉向量運算的童鞋,先回去惡補一下高等數學-07章空間解釋幾何與向量代數.pdf)

package {import flash.display.Graphics;public class Vector2D {private var _x:Number;private var _y:Number;//構造函數public function Vector2D(x:Number=0,y:Number=0) {_x=x;_y=y;}//繪制向量(以便于顯示)public function draw(graphics:Graphics,color:uint=0):void {graphics.lineStyle(0,color);graphics.moveTo(0,0);graphics.lineTo(_x,_y);}//克隆對象public function clone():Vector2D {return new Vector2D(x,y);}//位置歸零public function zero():Vector2D {_x=0;_y=0;return this;}//是否在零位置public function isZero():Boolean {return _x==0&&_y==0;}//獲得向量的角度public function get angle():Number {return Math.atan2(_y,_x);}//設置向量的模(即大小)public function set length(value:Number):void {var a:Number=angle;_x=Math.cos(a)*value;_y=Math.sin(a)*value;}//獲取向量大小的平方public function get lengthSQ():Number {return _x*_x+_y*_y;}//獲取向量的模(即大小)public function get length():Number {return Math.sqrt(lengthSQ);}//設置向量的角度public function set angle(value:Number):void {var len:Number=length;_x=Math.cos(value)*len;_y=Math.sin(value)*len;}	//截斷向量(設置向量模最大值)public function truncate(max:Number):Vector2D {length=Math.min(max,length);return this;}//交換x,y坐標public function reverse():Vector2D {_x=- _x;_y=- _y;return this;}//定義二個向量的加法運算public function add(v2:Vector2D):Vector2D {return new Vector2D(_x+v2.x,_y+v2.y);}//定義二個向量的減法運算public function subtract(v2:Vector2D):Vector2D {return new Vector2D(_x-v2.x,_y-v2.y);}//向量模的乘法運算public function multiply(value:Number):Vector2D {return new Vector2D(_x*value,_y*value);}//向量模的除法運算public function divide(value:Number):Vector2D {return new Vector2D(_x/value,_y/value);}//判定二個向量(坐標)是否相等public function equals(v2:Vector2D):Boolean {return _x==v2.x&&_y==v2.y;}//設置x軸坐標public function set x(value:Number):void {_x=value;}//返回x軸坐標public function get x():Number {return _x;}//設置y軸坐標public function set y(value:Number):void {_y=value;}//返回y軸坐標public function get y():Number {return _y;}//單位化向量(即設置向量的模為1,不過這里用了一種更有效率的除法運算,從而避免了lengh=1帶來的三角函數運算)public function normalize():Vector2D {if (length==0) {_x=1;return this;}//建議大家畫一個基本的3,4,5勾股定理的直角三角形即可明白下面的代碼var len:Number=length;_x/=len;_y/=len;return this;}		//判定向量是否為單位向量public function isNormalized():Boolean {return length==1.0;}//點乘(即向量的點積)public function dotProd(v2:Vector2D):Number {return _x*v2.x+_y*v2.y;}//叉乘(即向量的矢量積)public function crossProd(v2:Vector2D):Number {return _x*v2.y-_y*v2.x;}//返回二個向量之間的夾角public static function angleBetween(v1:Vector2D,v2:Vector2D):Number {if (! v1.isNormalized()) {v1=v1.clone().normalize();}if (! v2.isNormalized()) {v2=v2.clone().normalize();}return Math.acos(v1.dotProd(v2));//建議先回顧一下http://www.cnblogs.com/yjmyzz/archive/2010/06/06/1752674.html中提到的到夾角公式}//判定給定的向量是否在本向量的左側或右側,左側返回-1,右側返回1public function sign(v2:Vector2D):int {return perp.dotProd(v2)<0?-1:1;}//返回與本向量垂直的向量(即自身順時針旋轉90度,得到一個新向量)public function get perp():Vector2D {return new Vector2D(- y,x);//建議回顧一下"坐標旋轉"}//返回二個矢量末端頂點之間的距離平方public function distSQ(v2:Vector2D):Number {var dx:Number=v2.x-x;var dy:Number=v2.y-y;return dx*dx+dy*dy;}//返回二個矢量末端頂點之間的距離public function dist(v2:Vector2D):Number {return Math.sqrt(distSQ(v2));}//toString方法public function toString():String {return "[Vector2D (x:"+_x+", y:"+_y+")]";}}
}

有幾個地方稍加解釋:

1、向量夾角的計算


上圖為向量的夾角公式,再來對照一下代碼部分:

public static function angleBetween(v1:Vector2D,v2:Vector2D):Number {if (! v1.isNormalized()) {v1=v1.clone().normalize();}if (! v2.isNormalized()) {v2=v2.clone().normalize();}return Math.acos(v1.dotProd(v2));
}

首先對向量v1,v2做了單位化處理,使其變成(模為1的)單位向量,這樣夾角公式中的|a|×|b|(即分母)自然也就是1,公式演變成cos(θ)=a.b(即夾角余弦 等于 向量a與b的點乘),然后再對其取反余弦Math.acos,最終得到夾角

2、垂直向量的取得

上圖是坐標(順時針)旋轉的標準公式,如果把α設置為90度,則

,即:

public function get perp():Vector2D {return new Vector2D(- y,x);
}

3、判定其它向量是在自身的左側還是右側

如上圖,先取得A的垂直向量,然后計算其它向量跟垂直向量的點積(點乘的公式,在物理上的表現之一為 W = |F|*|S|Cos(θ) ),如果其它向量與該垂直向量的夾角小于90度,點乘的值必為正,反之為負,所以也就能判定左右了(注意:這里的左右是指人站在坐標原點,順著向量A的方向來看的)

再來定義一個機車類Vehicle.as

package {import flash.display.Sprite;public class Vehicle extends Sprite {//邊界行為:是屏幕環繞(wrap),還是反彈{bounce}protected var _edgeBehavior:String=WRAP;//質量protected var _mass:Number=1.0;//最大速度protected var _maxSpeed:Number=10;//坐標protected var _position:Vector2D;//速度protected var _velocity:Vector2D;//邊界行為常量public static const WRAP:String="wrap";public static const BOUNCE:String="bounce";public function Vehicle() {_position=new Vector2D  ;_velocity=new Vector2D  ;draw();}protected function draw():void {graphics.clear();graphics.lineStyle(0);graphics.moveTo(10,0);graphics.lineTo(-10,5);graphics.lineTo(-10,-5);graphics.lineTo(10,0);}public function update():void {//設置最大速度_velocity.truncate(_maxSpeed);//根據速度更新坐標向量_position=_position.add(_velocity);			//處理邊界行為if (_edgeBehavior==WRAP) {wrap();} else if (_edgeBehavior==BOUNCE) {bounce();}//更新x,y坐標值x=position.x;y=position.y;//處理旋轉角度rotation=_velocity.angle*180/Math.PI;}//反彈private function bounce():void {if (stage!=null) {if (position.x>stage.stageWidth) {position.x=stage.stageWidth;velocity.x*=-1;} else if (position.x<0) {position.x=0;velocity.x*=-1;}if (position.y>stage.stageHeight) {position.y=stage.stageHeight;velocity.y*=-1;} else if (position.y<0) {position.y=0;velocity.y*=-1;}}}//屏幕環繞private function wrap():void {if (stage!=null) {if (position.x>stage.stageWidth) {position.x=0;}if (position.x<0) {position.x=stage.stageWidth;}if (position.y>stage.stageHeight) {position.y=0;}if (position.y<0) {position.y=stage.stageHeight;}}			}//下面的都是屬性定義public function set edgeBehavior(value:String):void {_edgeBehavior=value;}public function get edgeBehavior():String {return _edgeBehavior;}public function set mass(value:Number):void {_mass=value;}public function get mass():Number {return _mass;}public function set maxSpeed(value:Number):void {_maxSpeed=value;}public function get maxSpeed():Number {return _maxSpeed;}public function set position(value:Vector2D):void {_position=value;x=_position.x;y=_position.y;}public function get position():Vector2D {return _position;}public function set velocity(value:Vector2D):void {_velocity=value;}public function get velocity():Vector2D {return _velocity;}override public function set x(value:Number):void {super.x=value;_position.x=x;}override public function set y(value:Number):void {super.y=value;_position.y=y;}}
}

沒有什么新東西,都是以前學到的知識,測試一下上面這二個類:

package {	import flash.display.Sprite;import flash.display.StageAlign;import flash.display.StageScaleMode;import flash.events.Event;public class VehicleTest extends Sprite {private var _vehicle:Vehicle;public function VehicleTest() {stage.align=StageAlign.TOP_LEFT;stage.scaleMode=StageScaleMode.NO_SCALE;_vehicle=new Vehicle  ;addChild(_vehicle);_vehicle.position=new Vector2D(100,100);_vehicle.velocity.length=5;_vehicle.velocity.angle=Math.PI/4;//45度addEventListener(Event.ENTER_FRAME,onEnterFrame);}private function onEnterFrame(event:Event):void {_vehicle.update();}}
}

OK,現在可以進入正題了:(下面是從原書上直接抄過來的)

轉向行為(steering behaviors)這一術語,指的是一系列使對象行動起來像似長有智商的算法。這些行為都歸于人工智能或人工生命一類,是讓對象呈現出擁有生命一般,對如何移動到目的地、捕捉或逃避其它對象、避開障礙物、尋求路徑等做出因地適宜的決定。??

一、尋找行為(Seek)

簡單點講,就是角色本身試圖移動(包括轉向)到目標位置(這個位置可能是固定的,也可能是移動的)。

先定義一個從Vehicle繼承的子類:具有轉向能力的機車SteeredVehicle.as

package {import flash.display.Sprite;//(具有)轉向(行為的)機車public class SteeredVehicle extends Vehicle {private var _maxForce:Number=1;//最大轉向力private var _steeringForce:Vector2D;//轉向速度public function SteeredVehicle() {_steeringForce = new Vector2D();super();}public function set maxForce(value:Number):void {_maxForce=value;}public function get maxForce():Number {return _maxForce;}override public function update():void {_steeringForce.truncate(_maxForce);//限制為最大轉向速度,以避免出現突然的大轉身_steeringForce=_steeringForce.divide(_mass);//慣性的體現_velocity=_velocity.add(_steeringForce);_steeringForce = new Vector2D();super.update();}}
}

代碼不難理解:僅增加了最大轉向力maxForce(主要是為了防止機車一瞬間就突然移動到目標位置,會引起視覺上的動畫不連貫);另外對update做了重載處理,在更新機車x,y坐標及朝向(即rotation)之前,累加了轉向速度并考慮到了物體的慣性。

再來考慮“尋找(seek)”行為,先看下面這張圖:

根據向量運算,可以先得到機車期望的理想速度(desireVolocity)--注:如果用這個速度行駛,物體立馬就能到達目標點。當然我們要體現物體是逐漸靠近目標點的,所以顯然不可能用理想速度前行,而是要計算出轉向速度force,最終再把轉向速度force疊加到自身的速度_velocity上,這樣機車就能不斷向目標點移動了。

//尋找(Seek)行為
public function seek(target: Vector2D):void {var desiredVelocity:Vector2D=target.subtract(_position);desiredVelocity.normalize();desiredVelocity=desiredVelocity.multiply(_maxSpeed);//注:這里的_maxSpeed是從父類繼承得來的var force:Vector2D=desiredVelocity.subtract(_velocity);_steeringForce=_steeringForce.add(force);
}

把這段代碼加入到SteeredVehicle.as中就能讓SteeredVehicle類具有seek行為,下面是測試代碼:

package {import SteeredVehicle;import Vector2D;import flash.display.Sprite;import flash.display.StageAlign;import flash.display.StageScaleMode;import flash.events.Event;public class SeekTest extends Sprite {private var _vehicle:SteeredVehicle;public function SeekTest() {stage.align=StageAlign.TOP_LEFT;stage.scaleMode=StageScaleMode.NO_SCALE;_vehicle = new SteeredVehicle();addChild(_vehicle);addEventListener(Event.ENTER_FRAME, onEnterFrame);}private function onEnterFrame(event:Event):void {_vehicle.seek(new Vector2D(mouseX, mouseY));//以當前鼠標位置為目標點_vehicle.update();}}
}

二、避開(flee)行為

它跟尋找(seek)行為正好是相反的,可以通俗的理解為:“既然發現了目標,那么就調頭逃跑吧”,所以代碼上只要改一行即可

//避開(flee)行為
public function flee(target: Vector2D):void {var desiredVelocity:Vector2D=target.subtract(_position);desiredVelocity.normalize();desiredVelocity=desiredVelocity.multiply(_maxSpeed);var force:Vector2D=desiredVelocity.subtract(_velocity);_steeringForce=_steeringForce.subtract(force);//這是唯一與seek行為不同的地方,一句話解釋:既然發現了目標,那就調頭就跑吧!
}

同樣,把上述代碼加入到SteeredVehicle.as中就能讓SteeredVehicle類具有flee行為,測試代碼:

package {import SteeredVehicle;import Vector2D;import flash.display.Sprite;import flash.display.StageAlign;import flash.display.StageScaleMode;import flash.events.Event;public class FleeTest extends Sprite {private var _vehicle:SteeredVehicle;public function FleeTest() {stage.align=StageAlign.TOP_LEFT;stage.scaleMode=StageScaleMode.NO_SCALE;_vehicle = new SteeredVehicle();_vehicle.position = new Vector2D(stage.stageWidth/2,stage.stageHeight/2);_vehicle.edgeBehavior = Vehicle.BOUNCE;addChild(_vehicle);addEventListener(Event.ENTER_FRAME, onEnterFrame);}private function onEnterFrame(event:Event):void {_vehicle.flee(new Vector2D(mouseX, mouseY));//避開鼠標當前位置_vehicle.update();}}
}

seek行為與flee行為組合起來,可以完成類似“警察抓小偷”的效果

package {import SteeredVehicle;import Vector2D;import Vehicle;import flash.display.Sprite;import flash.display.StageAlign;import flash.display.StageScaleMode;import flash.events.Event;import flash.text.TextField;import flash.text.TextFormat;public class SeekFleeTest1 extends Sprite {private var _seeker:SteeredVehicle;//尋找者(可理解為:警察)private var _fleer:SteeredVehicle;//躲避者(事理解為:小偷)private var _seekerSpeedSlider:SimpleSlider ;//警察的最大速度控制滑塊private var _txtSeekerMaxSpeed:TextField;private var _fleerSpeedSlider:SimpleSlider ;//小偷的最大速度控制滑塊private var _txtFleerMaxSpeed:TextField;public function SeekFleeTest1() {stage.align=StageAlign.TOP_LEFT;stage.scaleMode=StageScaleMode.NO_SCALE;_seeker = new SteeredVehicle(0xff0000);_seeker.position=new Vector2D();_seeker.edgeBehavior=Vehicle.BOUNCE;addChild(_seeker);_seeker.maxSpeed = 5;_fleer = new SteeredVehicle(0x0000ff);_fleer.position=new Vector2D(stage.stageWidth*Math.random(),stage.stageHeight*Math.random());_fleer.edgeBehavior=Vehicle.BOUNCE;addChild(_fleer);addEventListener(Event.ENTER_FRAME, onEnterFrame);addSpeedControl();}//添加速度控制組件private function addSpeedControl():void{_seekerSpeedSlider = new SimpleSlider(5,25,10);_seekerSpeedSlider.rotation = 90;_seekerSpeedSlider.x = 150;_seekerSpeedSlider.y = 20;_seekerSpeedSlider.backColor = _seekerSpeedSlider.backBorderColor = _seekerSpeedSlider.handleColor = _seekerSpeedSlider.handleBorderColor =  0xff0000;addChild(_seekerSpeedSlider);_seekerSpeedSlider.addEventListener(Event.CHANGE,onSeekerSpeedChange); _txtSeekerMaxSpeed = new TextField();var _tfseeker:TextFormat = new TextFormat();_tfseeker.color = 0xff0000;_txtSeekerMaxSpeed.defaultTextFormat = _tfseeker;_txtSeekerMaxSpeed.text = "10";addChild(_txtSeekerMaxSpeed);_txtSeekerMaxSpeed.y = _seekerSpeedSlider.y -6;_txtSeekerMaxSpeed.x = _seekerSpeedSlider.x +3;_fleerSpeedSlider = new SimpleSlider(5,25,10);_fleerSpeedSlider.rotation = 90;_fleerSpeedSlider.x = 480;_fleerSpeedSlider.y = 20;_fleerSpeedSlider.backColor = _fleerSpeedSlider.backBorderColor = _fleerSpeedSlider.handleColor = _fleerSpeedSlider.handleBorderColor =  0x0000ff;addChild(_fleerSpeedSlider);_fleerSpeedSlider.addEventListener(Event.CHANGE,onFleerSpeedChange); _txtFleerMaxSpeed = new TextField();			var _tffleer:TextFormat = new TextFormat();_tffleer.color = 0x0000ff;			_txtFleerMaxSpeed.defaultTextFormat = _tffleer;_txtFleerMaxSpeed.text = "10";addChild(_txtFleerMaxSpeed);_txtFleerMaxSpeed.y = _fleerSpeedSlider.y -6;_txtFleerMaxSpeed.x = _fleerSpeedSlider.x +3;}function onSeekerSpeedChange(e:Event):void{_seeker.maxSpeed = _seekerSpeedSlider.value;_txtSeekerMaxSpeed.text = _seekerSpeedSlider.value.toString();}function onFleerSpeedChange(e:Event):void{_fleer.maxSpeed = _fleerSpeedSlider.value;_txtFleerMaxSpeed.text = _fleerSpeedSlider.value.toString();}private function onEnterFrame(event:Event):void {_seeker.seek(_fleer.position);//警察 抓 小偷_fleer.flee(_seeker.position);//小偷 躲 警察_seeker.update();_fleer.update();}		}
}

調整紅色滑塊和藍色滑塊,可改變seeker與fleer的最大速度。(注:代碼中的SimpleSlider在Flash/Flex學習筆記(46):正向運動學中能找到) 如果愿意,您還可以加入碰撞檢測,比如當“警察”抓住“小偷”時,顯示一個提示:“小樣,我抓住你了!”

如果加入更多的物體,比如A,B,C三個,讓A追逐B同時躲避C,B追逐C同時躲避A,C追逐A同時躲避B,將是下面這副模樣:

package {import flash.display.Sprite;import flash.display.StageAlign;import flash.display.StageScaleMode;import flash.events.Event;public class SeekFleeTest2 extends Sprite {private var _vehicleA:SteeredVehicle;private var _vehicleB:SteeredVehicle;private var _vehicleC:SteeredVehicle;public function SeekFleeTest2() {stage.align=StageAlign.TOP_LEFT;stage.scaleMode=StageScaleMode.NO_SCALE;_vehicleA=new SteeredVehicle(0xff0000)  ;_vehicleA.position=new Vector2D(stage.stageWidth*Math.random(),stage.stageHeight*Math.random());_vehicleA.edgeBehavior=Vehicle.BOUNCE;addChild(_vehicleA);_vehicleB=new SteeredVehicle(0x0000ff)  ;_vehicleB.position=new Vector2D(stage.stageWidth*Math.random(),stage.stageHeight*Math.random());_vehicleB.edgeBehavior=Vehicle.BOUNCE;addChild(_vehicleB);_vehicleC=new SteeredVehicle(0x00ff00)  ;_vehicleC.position=new Vector2D(stage.stageWidth*Math.random(),stage.stageHeight*Math.random());_vehicleC.edgeBehavior=Vehicle.BOUNCE;addChild(_vehicleC);addEventListener(Event.ENTER_FRAME,onEnterFrame);}private function onEnterFrame(event:Event):void {//A追求B,躲避C_vehicleA.seek(_vehicleB.position);_vehicleA.flee(_vehicleC.position);			//B追求C,躲避A_vehicleB.seek(_vehicleC.position);_vehicleB.flee(_vehicleA.position);//C追求A,躲避B_vehicleC.seek(_vehicleA.position);_vehicleC.flee(_vehicleB.position);_vehicleA.update();_vehicleB.update();_vehicleC.update();}}
}

Flash動畫的邊界,猶如人世間的一張網,將你我他都罩住,我們都在追尋一些東西,同時也在逃避一些東西,于是乎:愛我的人我不愛,我愛的人愛別人······ 現實如此,程序亦如此。

三、到達(arrive)行為

到達行為其實跟尋找行為很相似,區別在于:尋找行為發現目標后,不斷移動靠近目標,但速度不減,所以會出現最終一直在目標附近二頭來回跑,停不下來。而到達行為在靠近目標時會慢慢停下來,最終停在目標點。(這個咋這么熟悉?對了,這就是以前學習過來的緩動動畫,詳見Flash/Flex學習筆記(38):緩動動畫)

//到達(arrive)行為
public function arrive(target: Vector2D):void {var desiredVelocity:Vector2D=target.subtract(_position);desiredVelocity.normalize();var dist:Number=_position.dist(target);if (dist>_arrivalThreshold) {desiredVelocity=desiredVelocity.multiply(_maxSpeed);} else {desiredVelocity=desiredVelocity.multiply(_maxSpeed*dist/_arrivalThreshold);}var force:Vector2D=desiredVelocity.subtract(_velocity);_steeringForce=_steeringForce.add(force);
}

當然這里的比例因子:_arrivalThreshold需要先定義,同時為了方便動態控制,還要對外以屬性的形式暴露出來

private var _arrivalThreshold:Number=100;//到達行為的距離閾值(小于這個距離將減速)public function set arriveThreshold(value: Number):void {_arrivalThreshold=value;
}public function get arriveThreshold():Number {return _arrivalThreshold;
}

把上面這二段代碼加入SteeredVehicle.as中,然后測試一把:

package {import flash.display.Sprite;import flash.display.StageAlign;import flash.display.StageScaleMode;import flash.events.Event;public class ArriveTest extends Sprite {private var _vehicle:SteeredVehicle;public function ArriveTest() {stage.align=StageAlign.TOP_LEFT;stage.scaleMode=StageScaleMode.NO_SCALE;_vehicle=new SteeredVehicle  ;addChild(_vehicle);addEventListener(Event.ENTER_FRAME,onEnterFrame);}private function onEnterFrame(event:Event):void {_vehicle.arrive(new Vector2D(mouseX,mouseY));_vehicle.update();}}
}

四、追捕(pursue)行為

追捕跟尋找很類似,不過區別在于:尋找(seek)是發現目標后,以預定的速度向目標靠攏,不管目標跑得多快還是多慢,所以如果目標比尋找者(seeker)要移動得快,seeker永遠是追不上的;而追捕行為是要在目標前進的路上,提前把目標攔截到,也可以理解為先預定一個(target前進路線上的)目標位置,然后再以尋找行為接近該位置,所以只要預定目標位置計算得合理,就算追捕者的速度要慢一點兒,也是完全有可能把目標給抓住的。

代碼:

//追捕(pursue)行為
public function pursue(target:Vehicle):void {var lookAheadTime:Number=position.dist(target.position)/_maxSpeed;//假如目標不動,追捕者開足馬力趕過去的話,計算需要多少時間var predictedTarget:Vector2D=target.position.add(target.velocity.multiply(lookAheadTime));seek(predictedTarget);
}

解釋:假如目標不動的話,我們先計算二者之間的距離,然后以最大速度狂奔過去,大概需要lookAheadTime這么長時間,然后根據這個時間,得到預定的目標位置,再以該位置為目標,尋找(seek)過去。(當然這種算法并不精確,但是處理起來比較簡單,重要的是:配合Enter_Frame事件后,它確實管用!)

測試代碼:

package {import flash.display.Sprite;import flash.display.StageAlign;import flash.display.StageScaleMode;import flash.events.Event;import flash.events.MouseEvent;import flash.text.TextField;public class PursueTest extends Sprite {private var _seeker:SteeredVehicle;private var _pursuer:SteeredVehicle;private var _target:Vehicle;private var _isRun:Boolean = false;private var _text:TextField;public function PursueTest() {stage.align=StageAlign.TOP_LEFT;stage.scaleMode=StageScaleMode.NO_SCALE;_seeker = new SteeredVehicle(0x0000ff);				addChild(_seeker);_pursuer = new SteeredVehicle(0xff0000);			addChild(_pursuer);_target = new Vehicle(0x000000);			_target.velocity.length=15;//目標對象跑得快一點,這樣才能看出區別addChild(_target);		_seeker.edgeBehavior = _target.edgeBehavior = _pursuer.edgeBehavior = Vehicle.BOUNCE;stage.addEventListener(MouseEvent.CLICK,stageClick);_text = new TextField();_text.text = "點擊鼠標開始演示";_text.height = 20;_text.width = 100;			_text.x = stage.stageWidth/2 - _text.width/2;_text.y = stage.stageHeight/2 - _text.height/2;addChild(_text);}private function onEnterFrame(event:Event):void {_seeker.seek(_target.position);_seeker.update();_pursuer.pursue(_target);_pursuer.update();_target.update();}private function stageClick(e:MouseEvent):void{			if (!_isRun){_target.position=new Vector2D(stage.stageWidth/2,stage.stageHeight/2);addEventListener(Event.ENTER_FRAME, onEnterFrame);				_isRun = true;removeChild(_text);				}else{removeEventListener(Event.ENTER_FRAME, onEnterFrame);_isRun = false;_target.position = _seeker.position = _pursuer.position = new Vector2D(0,0);addChild(_text);_text.text = "點擊鼠標重新開始";				}			}}
}

這里為了區別“追捕行為”與"尋找行為",我們同時加入了追捕者(_pursuer-紅色)與尋找者(_seeker-藍色),通過下面的演示可以看出,(紅色)追捕者憑借算法上的優勢,始終能更接近目標。

五、躲避(evade)行為

躲避跟追捕正好相反,可以理解為:如果我有可能擋在目標前進的路線上了,我就提前回避,讓開這條道。(俗話:好狗不擋道)

//躲避(evade)行為
public function evade(target: Vehicle):void {var lookAheadTime:Number=position.dist(target.position)/_maxSpeed;var predictedTarget:Vector2D=target.position.add(target.velocity.multiply(lookAheadTime));flee(predictedTarget);//僅僅只是這里改變了而已
}

把前面學到的這些個行為放在一起亂測一通吧:

package {import flash.display.Sprite;import flash.display.StageAlign;import flash.display.StageScaleMode;import flash.events.Event;import flash.events.MouseEvent;import flash.text.TextField;public class PursueEvadeTest extends Sprite {private var _pursuer:SteeredVehicle;private var _evader:SteeredVehicle;private var _target:SteeredVehicle;private var _seeker:SteeredVehicle;private var _fleer:SteeredVehicle;private var _pursuer2:SteeredVehicle;private var _evader2:SteeredVehicle;private var _text:TextField;private var _isRun:Boolean = false;public function PursueEvadeTest() {stage.align=StageAlign.TOP_LEFT;stage.scaleMode=StageScaleMode.NO_SCALE;_pursuer=new SteeredVehicle(0xff0000);addChild(_pursuer);_evader=new SteeredVehicle(0x00ff00);			addChild(_evader);_target=new SteeredVehicle(0x000000);_target.velocity.length=15;			addChild(_target);_seeker=new SteeredVehicle(0xff00ff);addChild(_seeker);_fleer=new SteeredVehicle(0xffff00);			addChild(_fleer);_pursuer2 = new SteeredVehicle();addChild(_pursuer2);_evader2 = new SteeredVehicle();			addChild(_evader2);_evader2.edgeBehavior = _pursuer2.edgeBehavior = _target.edgeBehavior = _evader.edgeBehavior = _pursuer.edgeBehavior = _fleer.edgeBehavior = _seeker.edgeBehavior = Vehicle.BOUNCE;_text = new TextField();_text.text="點擊鼠標開始演示";_text.height=20;_text.width=100;_text.x=stage.stageWidth/2-_text.width/2;_text.y=stage.stageHeight/2-_text.height/2;addChild(_text);stage.addEventListener(MouseEvent.CLICK,stageClick);}private function stageClick(e:MouseEvent):void {if (! _isRun) {_target.position=new Vector2D(stage.stageWidth/2,stage.stageHeight/2);_fleer.position=new Vector2D(400,300);_evader2.position=new Vector2D(400,200);_evader.position=new Vector2D(400,100);addEventListener(Event.ENTER_FRAME, onEnterFrame);_isRun=true;removeChild(_text);} else {_pursuer2.position =_evader2.position = _evader.position = _pursuer.position = _target.position=_seeker.position=_pursuer.position=	new Vector2D(0,0);removeEventListener(Event.ENTER_FRAME, onEnterFrame);_isRun=false;				addChild(_text);_text.text="點擊鼠標重新開始";}}private function onEnterFrame(event:Event):void {_seeker.seek(_target.position);_fleer.flee(_target.position);_pursuer.pursue(_target);_evader.evade(_target);_pursuer2.pursue(_evader2);_evader2.evade(_pursuer2);_target.update();_seeker.update();_pursuer.update();_fleer.update();_evader.update();_pursuer2.update();_evader2.update();}}
}

對于這個示例,也許看不出”避開(flee)“與“躲避(evade)”的區別,反正都是不擋道嘛,沒關系,下面會有機會看到區別的

六、漫游(wander)行為

顧名思義,就是要讓物體在屏幕上漫不經心的閑逛。可能大家首先想到的是讓速度每次隨機改變一些(類似布朗運動),但很快您就會發現這樣做的結果:物體象抽風一樣在屏幕上亂動,一點都不連續,體現不出“漫不經心”閑逛的特征。所以我們需要一種更為平滑的處理算法:

如上圖,先在物體運動的正前方,畫一個指定半徑的圈,然后讓向量offset每次隨機旋轉一個小小的角度,這樣最終能得到轉向力向量force=center+offset,最終把向量force疊加到物體的速度上即可.

private var _wanderAngle:Number=0;
private var _wanderDistance:Number=10;
private var _wanderRadius:Number=5;
private var _wanderRange:Number=1;//漫游
public function wander():void {var center:Vector2D=velocity.clone().normalize().multiply(_wanderDistance);var offset:Vector2D=new Vector2D(0);offset.length=_wanderRadius;offset.angle=_wanderAngle;_wanderAngle+=(Math.random()-0.5)*_wanderRange;var force:Vector2D=center.add(offset);_steeringForce=_steeringForce.add(force);
}public function set wanderDistance(value:Number):void {_wanderDistance=value;
}public function get wanderDistance():Number {return _wanderDistance;
}public function set wanderRadius(value:Number):void {_wanderRadius=value;
}public function get wanderRadius():Number {return _wanderRadius;
}public function set wanderRange(value:Number):void {_wanderRange=value;
}public function get wanderRange():Number {return _wanderRange;
}

雖然這次增加的代碼看上去比較多,但是大部分是用于封裝屬性的,關鍵的代碼并不難理解。好了,做下基本測試:

package {	import flash.display.Sprite;import flash.display.StageAlign;import flash.display.StageScaleMode;import flash.events.Event;public class WanderTest extends Sprite {private var _vehicle:SteeredVehicle;public function WanderTest() {stage.align=StageAlign.TOP_LEFT;stage.scaleMode=StageScaleMode.NO_SCALE;_vehicle = new SteeredVehicle();_vehicle.maxSpeed = 3;_vehicle.wanderDistance = 50;_vehicle.position=new Vector2D(200,200);//_vehicle.edgeBehavior = Vehicle.BOUNCE;addChild(_vehicle);addEventListener(Event.ENTER_FRAME, onEnterFrame);}private function onEnterFrame(event:Event):void {_vehicle.wander();_vehicle.update();}}
}

如果讓漫游行為跟前面提到的行為組合,效果會更好一些:

package {import flash.display.Sprite;import flash.display.StageAlign;import flash.display.StageScaleMode;import flash.events.Event;import flash.events.MouseEvent;import flash.text.TextField;public class FleeEvadeWanderTest extends Sprite {private var _pursuer:SteeredVehicle;private var _evader:SteeredVehicle;private var _target:SteeredVehicle;private var _seeker:SteeredVehicle;private var _fleer:SteeredVehicle;		private var _text:TextField;private var _isRun:Boolean = false;public function FleeEvadeWanderTest() {stage.align=StageAlign.TOP_LEFT;stage.scaleMode=StageScaleMode.NO_SCALE;			_evader=new SteeredVehicle(0x00ff00);//躲避者(綠色)			addChild(_evader);_target=new SteeredVehicle(0x000000);//目標(黑色)			_target.velocity.length = 20;addChild(_target);		_fleer=new SteeredVehicle(0xffff00);//避開者(黃色)			addChild(_fleer);_target.edgeBehavior =  _evader.edgeBehavior =  _fleer.edgeBehavior = Vehicle.BOUNCE;_text = new TextField();_text.text="點擊鼠標開始演示";_text.height=20;_text.width=100;_text.x=stage.stageWidth/2-_text.width/2;_text.y=stage.stageHeight/2-_text.height/2;addChild(_text);stage.addEventListener(MouseEvent.CLICK,stageClick);}private function stageClick(e:MouseEvent):void {if (! _isRun) {_target.position=new Vector2D(50,50);_evader.position = _fleer.position=new Vector2D(stage.stageWidth/2,stage.stageHeight/2);				addEventListener(Event.ENTER_FRAME, onEnterFrame);_isRun=true;removeChild(_text);} else {_evader.position = _target.position=_fleer.position=new Vector2D(0,0);removeEventListener(Event.ENTER_FRAME, onEnterFrame);_isRun=false;				addChild(_text);_text.text="點擊鼠標重新開始";}}private function onEnterFrame(event:Event):void {_target.wander();			_fleer.flee(_target.position);			_evader.evade(_target);_target.update();			_fleer.update();_evader.update();}}
}

前面提到了flee(避開)與evade(躲避)很難看出區別,但在這個示例里,大概能看出一些細節上的些許不同:flee算法是以目標當前的位置為做基點避開的,而evade是以目標前進方向上未來某個時時間點的位置做為基點避開的,所以相對而言,(綠色的)evader更有前瞻性--即所謂的先知先覺,而(黃色的)fleer只是見知見覺,最終在視覺效果上,evader總是希望跟目標以反方向逃開(這樣能躲得更遠,更安全一點)。

注:博客園的nasa(微軟MVP),對于本章內容也有相應的Sliverlight實現,推薦大家對照閱讀。

?

轉載于:https://www.cnblogs.com/yjmyzz/archive/2010/07/07/1773140.html

總結

以上是生活随笔為你收集整理的“AS3.0高级动画编程”学习:第二章转向行为(上)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产aⅴ爽av久久久久成人 | 91精品国产日韩91久久久久久 | 精品国产乱码久久久人妻 | 日韩午夜视频在线观看 | 五月综合视频 | 欧美xxxx少妇| 久久青青国产 | 久久久亚洲综合 | 日韩性xx | h视频在线免费看 | 超碰在线公开免费 | 护士的小嫩嫩好紧好爽 | 综合色av | 成年网站免费观看 | 毛茸茸日本熟妇高潮 | 欧美特级黄色录像 | 凹凸国产熟女精品视频 | 日韩综合av | 中文字幕乱码在线观看 | 亚洲中文字幕在线观看 | 亚洲 精品 综合 精品 自拍 | 中文字幕导航 | 欧美 日韩 国产 成人 在线 91 | 天堂av2021 | 欧美美女视频 | 日本少妇一区 | 中字幕视频在线永久在线观看免费 | 亚洲狼人av | 中文字幕乱码亚洲无线三区 | 丰满雪白极品少妇流白浆 | 自拍21区 | 91丝袜呻吟高潮美腿白嫩 | 精品97人妻无码中文永久在线 | 欧美精品乱码久久久久久按摩 | 国产xxxxx在线观看 | 亚洲免费观看高清完整版在线 | 麻豆综合网 | 丁香婷婷九月 | 91精品综合久久久久久五月天 | 伊人成综合网 | 国产青青草| 天堂av资源网 | 国产伦精品一区 | 中国女人黄色大片 | 高清视频免费在线观看 | 五月天激情视频 | 欧美日韩 一区二区三区 | 徐锦江一级淫片免费看 | 国产精品黄在线观看 | 黄色网址最新 | xxxxxx黄色| 精品午夜一区二区三区 | 夜夜操天天干 | 熟女少妇精品一区二区 | 日本精品人妻无码免费大全 | 国产剧情精品在线 | 国产午夜精品福利视频 | 亚洲永久无码7777kkk | 深夜激情网站 | 亚洲人成色777777精品音频 | 成av人在线观看 | 国产探花视频在线观看 | 日韩精品免费一区二区在线观看 | 在线久久| 日韩精品三区 | 国产一级视频免费观看 | 偷拍一区二区三区四区 | 中文亚洲av片在线观看 | 欧美国产乱视频 | 高清视频在线播放 | 亚洲视频黄| 久久亚洲AV无码专区成人国产 | 狠狠躁18三区二区一区传媒剧情 | 亚洲成人网在线 | 亚洲欧洲无码一区二区三区 | 婷婷精品一区二区三区 | 黄色片美女 | 精品一区二区三区成人免费视频 | 日韩中文字幕国产 | 一本色道久久加勒比精品 | 国产精品xxx视频 | 亚洲天天做 | 一本色道久久综合熟妇 | 欧洲毛片 | 国产最新网址 | 影音先锋中文字幕第一页 | 日本一区视频在线 | 日本一区视频在线 | 久热精品视频 | 天天摸天天插 | 成人一级生活片 | 国模大胆一区二区三区 | 国产一区二区视频在线免费观看 | 久久久久久亚洲av毛片大全 | 中文字幕在线网站 | 欧美成人黄色 | a久久久久 | 久久久999久久久 | 日韩黄色一区二区 |