AS3 緩動與彈性運動_第1頁
AS3 緩動與彈性運動_第2頁
AS3 緩動與彈性運動_第3頁
AS3 緩動與彈性運動_第4頁
AS3 緩動與彈性運動_第5頁
已閱讀5頁,還剩14頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、緩動與彈性運動成比例運動 緩動(ease與彈性(spring聯(lián)系緊密。這兩種方法都是將對象(通常指 Sprite 或 MovieClip)從某一點移動到目標點。使用緩動運動(Easing,如同讓影片滑動到目標并停止。使用彈性運動(Springing,會產(chǎn)生向前或向后的反彈,最終停止在目標點位。兩種方法具有一些共同點: 需要一個目標點; 確定到目標點的距離; 成比例地將影片移動到目標點距離越遠,移動速度越快。 緩動運動(easing與彈性運動(springing的不同之處在于移動的比例。緩動運動時,速度與距離成正比,離目標越遠,物體運動速度越快。當物體與目標點非常非常接近時,就幾乎不動了。 彈性

2、運動時,加速度與距離成正比。如果物體與目標離得很遠,再用上加速度,會使移動速度非常快。當物體接近目標時,加速度會減小,但依然存在!物體會飛過目標點,隨后再由反向加速度將它拉回來。最終,用摩擦力使其靜止。 下面,我們分別看一下這兩種方法,先從緩動(easing開始。 緩動(Easing 首先說明緩動的種類不只有一種。在 Flash IDE 中,制作補間動畫時,我們就可以看到 “緩動輸入”(ease in) 和 “緩動輸出”(ease out)。下面所討論的緩動類型與運動補間的 “緩動輸出”相似。在本章后面的 “高級緩動”一節(jié),將會給大家一個網(wǎng)站連接,在那里可以學(xué)習(xí)制作所有緩動的效果。 簡單緩動

3、簡單緩動是個非?;A(chǔ)概念,就是將一個物體移到別處去。創(chuàng)建這個“運動效果”時,希望物體能在幾幀內(nèi)慢慢移動到某一點。我們可以求出兩點之間的夾角,然后設(shè)置速度,再使用三角學(xué)計算出 vx 和 vy,然后讓物體運動。每一幀都判斷一下物體與目標點的距離,如果到達了目標則停止。這種運動還需要一定條件的約束才能實現(xiàn),但如果要讓物體運動得很自然,顯然這種方法是行不通的。 問題在于物體沿著固定的速度和方向運動,到達目標點后,立即停止。這種方法,用于表現(xiàn)物體撞墻的情景,也許比較合適。但是物體移動到目標點的過程,就像是某個人明確地知道他的目的地,然后向著目標有計劃地前進,起初運動的速度很快,而臨近目標點時,速度就開始

4、慢下來了。換句話講,它的速度向量與目標點的距離是成比例的。 先來舉個例子。比如說我們開車回家,當離家還有幾千米的距離時,要全速前進,當離開馬路開進小區(qū)時速度就要稍微慢一點兒。當還差兩座樓時就要更慢一點兒。在進入車庫時,速度也許只有幾邁。當進入停車位時速度還要更慢些,在還有幾英尺的時候,速度幾乎為零。 如果大家注意觀察就會發(fā)現(xiàn),這種行為就像關(guān)門、推抽屜一樣。開始的速度很快,然后逐漸慢下來。 在我們使用緩動使物體歸位時, 運動顯得很自然。簡單的緩動運動實現(xiàn)起來也非常簡單,比求出夾角,計算 vx,vy 還要簡單。下面是緩動的實現(xiàn)策略: 1. 確定一個數(shù)字作為運動比例系數(shù),這是個小于 1 的分數(shù); 2

5、. 確定目標點; 3. 計算物體與目標點的距離; 4. 用距離乘以比例系數(shù),得出速度向量; 5. 將速度向量加到當前物體坐標上; 6. 重復(fù) 3 到 5 步。圖 8-1 解釋了這一過程。 圖 8-1 簡單緩動 我們先來解釋一下這個過程,看看在 ActionScript 中是怎樣實現(xiàn)的。 首先,確定一個分數(shù)作為比例系數(shù)。我們說過,速度與距離是成比例的。也就是說速度是距離的一部分。比例系數(shù)在 0 和 1 之間,系數(shù)越接近 1,運動速度就會越快;系數(shù)越接近 0,運動速度就會越慢。但是要小心,系數(shù)過小會使物體無法到達目標。開始我們以 0.2 作為系數(shù),這個變量名就叫 easing。初始代碼如下: va

6、r easing:Number = 0.2; 接下來,確定目標。只需要一個簡單的 x,y 坐標,選擇舞臺中心坐標再合適不過了。 var targetX:Number = stage.stageWidth / 2; var targetY:Number = stage.stageHeight / 2; 下面,確定物體到達目標的距離。假設(shè)已經(jīng)有一個名為 ball 影片,只需要從 ball 的 x,y 坐標中減去目標的 x,y。 var dx:Number = targetX - ball.x; var dy:Number = targetY - ball.y; 速度等于距離乘以比例系數(shù): vx =

7、 dx * easing; vy = dy * easing; 129 130下面,大家知道該怎么做了吧: ball.x += vx; ball.y += vy; 最后重復(fù)步驟 3 到步驟 5,因此只需加入 enterFrame 處理函數(shù)。 讓我們再看一下這三個步驟,以便將它們最大程度地簡化: var dx:Number = targetX - ball.x; var dy:Number = targetY - ball.y; vx = dx * easing; vy = dy * easing; ball.x += vx; ball.y += vy; 把前面四句簡化為兩句: vx = (ta

8、rgetX - ball.x * easing; vy = (targetY - ball.y * easing; ball.x += vx; ball.y += vy; 如果大家覺得還不夠精簡,還可以進一步縮短: ball.x += (targetX - ball.x * easing; ball.y += (targetY - ball.y * easing; 在開始學(xué)習(xí)使用緩動時,也許大家會比較喜歡用詳細的句型,讓程序看上去更加清晰。但是當你使過幾百次后,就會更習(xí)慣用第三種寫法。下面,我們選用第二種句型,以加強對速度的理解。 現(xiàn)在就來看一下腳本動作,依然延用 Ball 類。以下是文檔類

9、Easing1.as: package import flash.display.Sprite; import flash.events.Event; public class Easing1 extends Sprite private var ball:Ball; private var easing:Number=0.2; private var targetX:Number=stage.stageWidth / 2; private var targetY:Number=stage.stageHeight / 2; public function Easing1( trace(targ

10、etX,targetY; init(; private function init(:void ball=new Ball ; addChild(ball; addEventListener(Event.ENTER_FRAME,onEnterFrame; private function onEnterFrame(event:Event:void var vx:Number=(targetX - ball.x * easing; var vy:Number=(targetY - ball.y * easing; 131ball.x+= vx; ball.y+= vy; 試改變 easing 的

11、值,觀察運動效果。 下面,大家可以讓小球變成可以拖拽的,與第七章所做的拖拽與拋落效果很像。在點擊小球時開始拖拽,同時,刪除 enterFrame 處理函數(shù)并且用 stage 偵聽 mouseUp。在 mouseUp 函數(shù)中,停止拖拽,刪除 mouseUp 方法,并重新開始 enterFrame。下面是文檔類 Easin2.as : package import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; public class Easing2 extends Sprite p

12、rivate var ball:Ball; private var easing:Number=0.2; private var targetX:Number=stage.stageWidth / 2; private var targetY:Number=stage.stageHeight / 2; public function Easing2( init(; private function init(:void ball=new Ball ; addChild(ball; ball.addEventListener(MouseEvent.MOUSE_DOWN,onMouseDown;

13、addEventListener(Event.ENTER_FRAME,onEnterFrame; private function onMouseDown(event:MouseEvent:void ball.startDrag(; removeEventListener(Event.ENTER_FRAME,onEnterFrame; stage.addEventListener(MouseEvent.MOUSE_UP,onMouseUp; private function onMouseUp(event:MouseEvent:void ball.stopDrag(; addEventList

14、ener(Event.ENTER_FRAME,onEnterFrame; stage.removeEventListener(MouseEvent.MOUSE_UP,onMouseUp; private function onEnterFrame(event:Event:void var vx:Number=(targetX - ball.x * easing; var vy:Number=(targetY - ball.y * easing; ball.x+= vx; ball.y+= vy; 132緩動何時停止 在物體緩動運動到目標點時,物體最終會到達目標點并且完成緩動效果。但是,即使不顯

15、示該對象,緩動代碼仍在執(zhí)行中,這一來浪費了 CPU 資源。當物體到達目標時,應(yīng)該停止執(zhí)行代碼。判斷物體是否到達目標的方法非常簡單,就像這樣: if(ball.x = targetX && ball.y = targetY / code to stop the easing 但是這里要注意一些技巧。 我們所討論的緩動類型涉及到了著名的 Xeno 悖論。Xeno 也是位希臘人,愛好測量實驗。Xeno 將運動分解為下面幾個步驟:物體要從 A 點到達 B 點,它首先要移動到兩點間一半的距離。然后物體再從該點出發(fā),到達與 B 點距離一半的距離。然后再折半。每次只移動離目標一半的距離,但永

16、遠無法準確地達到目標。 這個悖論聽起來是非常符合邏輯的。但是很明顯,我們確實將物體從一點移動到了另一點,這樣看來他的說法有些問題。到 Flash 中看看,影片在 x 軸上的位置為 0,假設(shè)要將它移動到 x 軸為 100 的位置。按照悖論所說,設(shè)緩動系數(shù)為 0.5,這樣每次運動到離目標一半的距離。過程如下: 從 0 點開始,經(jīng)過 1 幀,到達 50。 第 2 幀,到達 75。 剩下的距離是 25。它的一半是 12.5 ,所以新的距離就是 87.5。 按照這種順序,位置將變化為 93.75, 96.875, 98.4375 等等。20 幀以后,將到達 99.999809265。 從理論上講位置越來

17、越接近目標,但是永遠無法準確地到達目標點。然而,在代碼中進行試驗時,結(jié)果就發(fā)生了一些微妙的變化。歸根結(jié)底問題就在于“一次最少能移動多少個像素”,答案是 1/20。事實上,二十分之一像素有個特有的名字:twip (緹。在 Flash 內(nèi)部計算單位都采用 twip 像素,包括所有 Sprite 影片,影片剪輯和其它舞臺對象。因此,在顯示影片位置時,這個數(shù)值永遠是 0.05 的倍數(shù)。 下面舉個例子,一個影片要到達 100 的位置,而它所到達的最接近的位置事實上是 99.5。再分隔的距離,就是加上 (100 99.95 /2。相當于加上了 0.025,四十分之一像素。 超出了 twip 是能夠移動的最

18、小值, 因此無法加上 “半個 twip” , 結(jié)果是只增加了 0 像素。如果大家不信的話,可以親自試一下(提示:將代碼放入框架類中的 init 方法): var sprite:Sprite; sprite = new Sprite(; addChild(sprite; sprite.x = 0; var targ:Number = 100; for(var i:Number = 0; i < 20; i+ trace(i + ": " + sprite.x; sprite.x += (targ - sprite.x * .5; 循環(huán) 20 次,將影片移動離目標一半的距

19、離,這是基本緩動應(yīng)用。將代碼放入 for 循環(huán),只是為了測試其位置,并不在于觀察物體運動。循環(huán)到第 11 次時,影片已經(jīng)到達了 99.95,這已經(jīng)是它能夠到達的最遠的地方了。 長話短說,影片并非無限地接近目標,但是它確實永遠無法準確地到達目標點。這樣一來,緩動代碼就永遠不會停止。我們要回答的問題是 “哪里才是物體最接近的目標位置?”,這需要確定到目標點的距離是否小于某個范圍。我發(fā)現(xiàn)在很多軟件中,如果物體與目標點的距離相差在一個像素以內(nèi),就可以說它已經(jīng)到達了目標點,即可停止緩動了。 在處理二維坐標時,可以使用第三章所介紹的公式來計算點間距離: distance = Math.sqrt(dx *

20、dx + dy * dy 133如果只處理一維坐標點,如只移動一個軸的位置,就需要使用距離的絕對值,因為它有可能是個負數(shù),使用 Math.abs 方法。 OK,說得很多了,來寫代碼吧。這個簡單的文檔類,演示了如何關(guān)閉緩動運動(EasingOff.as): package import flash.display.Sprite; import flash.events.Event; public class EasingOff extends Sprite private var ball:Ball; private var easing:Number = 0.2; private var ta

21、rgetX:Number = stage.stageWidth / 2; public function EasingOff( init(; private function init(:void ball = new Ball(; addChild(ball; ball.y = stage.stageHeight / 2; addEventListener(Event.ENTER_FRAME, onEnterFrame; private function onEnterFrame(event:Event:void var dx:Number = targetX - ball.x; if (M

22、ath.abs(dx < 1 ball.x = targetX; removeEventListener(Event.ENTER_FRAME, onEnterFrame; trace("done" else var vx:Number = dx * easing; ball.x += vx; 此例中,將緩動公式分解使用,首先計算出距離,因為我們需要知道是否該停止緩動。大家應(yīng)該知道為什么要使用 dx 的絕對值了吧。如果小球在目標點的右邊,dx 的值總是負的,if (dx < 1 的結(jié)果永遠為真,這就會使緩動停止。而使用 Math.abs,就可以判斷實際距離是否小于

23、 1。 記住,如果將拖拽與緩動相結(jié)合,要在放開小球時,將運動代碼重新啟用。 移動的目標 上面例子中的目標點都是單一且固定的,這些似乎還不能滿足我們的要求。事實上,F(xiàn)lash 并不關(guān)心物體是否到達目標,或目標是否還在移動。它只會問 “我的目標在哪里?距離有多遠?速度是多少?”,每幀都如此。因此,我們可以很容易將目標點改為鼠標所在的位置,只需將原來 targetX 和 targetY 的地方,改成鼠標的坐標 (mouseX 和 mouseY。以下是一個比較簡單的版本(EaseToMouse.as): package 134import flash.display.Sprite; import fl

24、ash.events.Event; public class EaseToMouse extends Sprite private var ball:Ball; private var easing:Number = 0.2; public function EaseToMouse( init(; private function init(:void ball = new Ball(; addChild(ball; addEventListener(Event.ENTER_FRAME, onEnterFrame; private function onEnterFrame(event:Eve

25、nt:void var vx:Number = (mouseX - ball.x * easing; var vy:Number = (mouseY - ball.y * easing; ball.x += vx; ball.y += vy; 移動鼠標觀察小球跟隨情況,是不是距離越遠速度越快。 試想還有沒有其它可移動的目標。當然還可以是一個影片向著另一個影片緩動。在早先的 Flash 時代,鼠標追蹤者(mouse trailers)即一串影片跟蹤者鼠標的效果曾經(jīng)風(fēng)靡一時。緩動就是制作這種效果的方法之一。第一個影片緩動到鼠標上,第二個影片緩動到第一個影片上,第三個再緩動到第二個上,依此類推。大家

26、不妨一試。 緩動不僅限于運動 本書中,有很多簡單的例子程序。在這些例子中,我們主要是計算影片所用變量的值。通常,使用 x,y 屬性控制物體的位置。不過別忘了 Sprite 影片,影片剪輯以及各種顯示對象還有很多其它可以操作的屬性,而且基本都是用數(shù)字表示的。所以在讀例子程序時,也應(yīng)該試用其它屬性代替這個例子中的屬性。下面給大家一些啟發(fā)。 透明度 將緩動用在 alpha 屬性上。開始設(shè)置為 0 ,目標設(shè)置為 1 : ball.alpha = 0; var targetAlpha:Number = 1; 在 enterFrame 函數(shù)中,使用緩動可以實現(xiàn)影片淡入效果: ball.alpha += (

27、targetAlpha - ball.alpha * easing; 若將 0 和 1 顛倒過來就可以實現(xiàn)影片的淡出效果。 135旋轉(zhuǎn) 設(shè)置一個 rotation 屬性和一個目標 rotation。當然,還需要一個能夠表現(xiàn)旋轉(zhuǎn)對象,比如一個箭頭(arrow: arrow.rotation = 90; var targetRotation:Number = 270; arrow.rotation += (targetRotation - arrow.rotation * easing; 顏色 如果大家想挑戰(zhàn)一下,可以在 24 位色彩中使用緩動。設(shè)置好 red,green,blue 的初始值,使用

28、緩動單獨表現(xiàn)每一色彩元素的值,然后將它們再組合成 24 位色彩值。例如,我們可以從 red 緩動到 blue。初始顏色如下: red = 255; green = 0; blue = 0; redTarget = 0; greenTarget = 0; blueTarget = 255; 在 enterFrame 處理函數(shù)中的每一幀執(zhí)行緩動。這里只表現(xiàn)一個 red 值: red += (redTarget - red * easing; 再將這三個數(shù)值組合為一個數(shù)(如第四章介紹的): col = red << 16 | green << 8 | blue; 最后可以在

29、ColorTransform (見第四章),線條顏色或填充色中使用該顏色值。 高級緩動 現(xiàn)在我們已經(jīng)看到簡單的緩動效果是如何實現(xiàn)的了, 大家也許正在考慮如何使用更復(fù)雜的緩動公式制作一些效果。例如,在開始時比較緩慢,然后漸漸開始加速,最后在接近目標時再將速度慢下來?;蛘呦M谝欢螘r間或若干幀內(nèi)完成緩動效果。 Robert Penner 以收集、編制和實現(xiàn)緩動公式而出名。我們可以在 中找到他的緩動公式。在他寫這些內(nèi)容時 AS 3 版本還沒有出現(xiàn),但是用我們前面幾章所學(xué)知識,將它們轉(zhuǎn)化為 AS 3 版本的也是件非常容易的事。 OK,下面進入 Flash 中我最喜歡的一個主題:彈性運動(Springi

30、ng)。 彈性運動 一直以來,我都認為彈性運動將是 ActionScript 動畫中最強大和最有用的物理學(xué)概念。幾乎所有的物體都可以使用彈性運動。下面就來看看什么是彈性運動以及在 Flash 編程中的應(yīng)用。 如同本章開始時所提到的,彈性的加速度與物體到目標點的距離成正比例。想象一下現(xiàn)實中彈簧的性質(zhì)。把一個小球拴在橡皮圈一頭,再將另一頭系在一個固定的地方。當小球懸在半空時,在沒有施加外力的情況下,小球就處在目標點的位置上。再將小球微微拉動,松手后橡皮圈會對其施加一些外力,又將小球拽回了目標點。如果用最大力量將小球挪遠,那么橡皮圈就會對小球施加很大的力。小球急速向目標點飛去,并朝著另一面運動。這時

31、,小 136球的速度非???。當它越過了目標點時,橡皮圈開始把它向回拉改變其速度向量。這時,小球會繼續(xù)運動,但是它運動得越遠,所受到的拉力就越大。然后,速度向量為零,方向相反,一切再重新開始。最終,在反彈了幾次后,速度逐漸慢下來直到停止停在目標點上。 下面我們將這個過程翻譯成 ActionScript。為了簡化這個過程,我們先在一維坐標上進行實驗。 一維坐標上的彈性運動 這里我們?nèi)匀皇褂每梢酝献У男∏蜃鳛橹黧w。默認位置還是 x 軸的 0 點,使它具有運動到中心點的彈性。像使用緩動一樣,需要一個變量保存彈性的數(shù)值。可以認為這個數(shù)同距離的比例,較大的彈性值會使彈性運動顯得十分僵硬。較小的彈性值會使彈

32、性運動像一條松緊帶。我們選用 0.1 作為彈性 (spring : private var spring:Number = 0.1; private var targetX:Number = stage.stageWidth / 2; private var vx:Number = 0; 不要擔(dān)心物體當前的位置,只需要知道如何確定這些變量與表達式就可以了。 然后加入運動代碼并且找出與目標點的距離: var dx:Number = targetX - ball.x; 下面計算加速度。加速度與距離成正比,也就是距離乘以 spring 的值: var ax:Number = dx * spring;

33、 得到了加速度以后,我們就回到了熟悉的地方,把加速度加到速度向量中。 vx += ax; ball.x += vx; 在寫代碼前,先來模擬一下運行時的數(shù)據(jù)。假設(shè)物體的 x 坐標為 0, vx 為 0,目標 x 為 100,spring 值為 0.1。執(zhí)行過程如下: 1. 距離(100 乘以 spring,得到 10。將它加入 vx 中,此時 vx 變?yōu)?10。再將 vx 加入到速度向量上使得 x 位置變?yōu)?10。 2. 下一次,距離(100-10 等于 90。加速度為 90 乘以 0.1,結(jié)果為 9。將結(jié)果加入 vx ,使 vx 變?yōu)?19。 x 坐標變?yōu)?29。 3. 下一次,距離為 71,加速度為 7.1,將結(jié)果加到 vx 中,使 vx 變成 26.1。 x 坐標變?yōu)?55.1。 4. 下一次,距離為 44.9,加速度為 4.49, vx 變成 30.59。 x 坐標變?yōu)?85.69。 注意, 每次的加速度隨著物體越接近目標,變得越來越小,但是速度向量仍在不斷增漲。雖然漲幅不像啟初那樣快,但是速度卻越來越快。 幾次過后,物體就超過了目標點,到達了 117 的位置?,F(xiàn)在的距離是 100 117,等于 -17。將這一部分加入到速度向量中,會使物體的移動稍稍慢下來

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論