使用DragonBones开发FLASH骨骼动画入门教程
轉(zhuǎn)自:使用DragonBones開發(fā)FLASH骨骼動畫入門教程
本文轉(zhuǎn)載(并略作修改)自黃竣的教程,URL是:http://dragonbones.github.com/getting_started_cn.html全文如下:
DragonBones是什么?
DragonBones是一套開源的 2D骨骼動畫框架和工具,它包含了基于Flash Pro的骨骼動畫編輯面板Skeleton Animation Design Panel及骨骼動畫ActionScript框架。
它可以讓開發(fā)者運(yùn)用熟悉的Flash Pro元件及時間軸編輯方式,快速創(chuàng)建2D骨骼動畫,并運(yùn)用到Flash或其他技術(shù)的應(yīng)用中。
【朱先忠注】?Flash2Cocos2d-x正是由RainyNote(博客地址是:http://rainynote.com/2012/09/cocos2d-x-%E5%8A%A8%E7%94%BB%E5%B7%A5%E5%85%B7/)開發(fā)出的直接操作FLASH骨骼動畫及其相關(guān)文件的coco2d-x擴(kuò)展框架。
Features
-
動畫基于Flash pro時間軸,可以使用Flash傳統(tǒng)動畫方式制作游戲動畫;
-
骨骼綁定可以讓動畫更精準(zhǔn),更真實(shí)自然,并可通過程序動態(tài)控制;
-
可設(shè)置單個骨骼的動畫時間縮放和延時播放,使用較少的關(guān)鍵幀就可以表現(xiàn)復(fù)雜生動的動畫效果;
-
動畫各部分采用拼接方式,動畫有緩動補(bǔ)間,占用位圖/內(nèi)存資源少;
-
骨骼顯示對象與骨骼的邏輯分離,可在不影響動畫播放的情況下動態(tài)更換;
-
能方便用于傳統(tǒng)DisplayList、Starling及其他技術(shù)的2D應(yīng)用。
下載與安裝設(shè)置
開源項(xiàng)目地址:http://dragonbones.github.com
-
從這兒獲取Adobe Flash Pro 5.5或以上版本
-
下載最新的DragonBones release 包,安裝支持Flash Pro的骨骼面板擴(kuò)展插件SkeletonDesignPanel.zxp (注:此插件目前僅支持Flash Pro5.5及以上版本), 獲取骨骼動畫ActionScript庫SkeletonAnimationLibrary。
- 在后續(xù)的教程中,我們將使用這套框架來動態(tài)顯示由Flash Pro設(shè)計的骨骼動畫。
教程源碼下載
接下來,我們將通過幾個簡單的教程快速了解DragonBones的用法。
請從這里下載本教程相關(guān)源碼。
教程1:針對設(shè)計師 使用DragonBones在Flash Pro中創(chuàng)建骨骼動畫
作為設(shè)計師,你只需要準(zhǔn)備好動畫角色的各個部分,在Flash Pro的時間軸中把他們有序組裝起來、設(shè)置好動作關(guān)鍵幀并運(yùn)用DragonBones的骨骼動畫編輯面板搞定一切。
在下載并安裝完畢骨骼面板的Flash Pro擴(kuò)展插件后,啟動Flash Pro。打開教程源碼下載包中的DragonBones_tutorial_Start.fla文件。
打開庫面板,你可以看到此示例的相關(guān)資源。
在parts目錄中包含的是組成動畫Dragon的各個元件,從命名可以直觀的了解到它們對應(yīng)的龍的各個部分。良好的元件命名是個好習(xí)慣,不是么?:)
雙擊庫面板中的MovieClip元件Dragon進(jìn)入時間軸編輯模式。我們需要詳細(xì)了解這個動畫的組成,它有助于后面骨骼動畫編輯。
注意:1,請留意時間軸上的各層的命名,我們是以骨骼各個部分來命名的。骨骼動畫面板將自動根據(jù)層的命名來識別組成骨骼的各個部分。
,2,需要注意的是層label,我們添加了標(biāo)簽“walk”用來說明當(dāng)前時間軸表示的動作。如果由多個動作,請在對應(yīng)動作起始位置添加標(biāo)簽來說明。這一步非常重要!骨骼動畫面板將按照標(biāo)簽來讀取并設(shè)定動作。你發(fā)現(xiàn)時間軸上并沒有添加補(bǔ)間?是的,你僅僅需要在時間軸上設(shè)置關(guān)鍵幀上各元件的位置,剩下的工作都可以在骨骼面板中完成。
當(dāng)然,作為設(shè)計師的你,可以按你的習(xí)慣做好完整的補(bǔ)間動畫,骨骼面板同樣可以按照你的動畫原樣導(dǎo)入。(注:目前版本的DragonBones僅支持傳統(tǒng)補(bǔ)間,新補(bǔ)間將在后續(xù)版本中支持)
當(dāng)你按上述要求準(zhǔn)備好動畫,就可以點(diǎn)擊Flash Pro菜單中的Window>Other Panels>SkeletonAnimationDesignPanel打開骨骼動畫編輯面板。我們將在接下來的操作中詳細(xì)說明骨骼動畫編輯面板的使用。
在此面板中點(diǎn)擊“Import”按鈕,此時將出現(xiàn)下圖所示窗口:
在導(dǎo)入面板中你可以設(shè)置貼圖排序、貼圖高度及貼圖間距。在導(dǎo)入選項(xiàng)中,你可以導(dǎo)入選中的庫元件、所有庫元件以及通過骨骼面板導(dǎo)出的PNG/SWF/ZIP文件等。
選中Flash Pro庫中的MovieClip元件Dragon,然后在骨骼動畫編輯面板中選擇導(dǎo)入選中的項(xiàng)目,點(diǎn)擊OK按鈕。
骨骼動畫編輯面板導(dǎo)入動畫元件Dragon后如下圖:
Armature List: 導(dǎo)入動畫MovieClip的列表,與MovieClip在庫中的名稱一致,程序中將以此名稱來創(chuàng)建動畫對象。每個包含動作的MovieClip,在DragonBones里我們稱之為“骨架”(Armature)。
Behavior. List: 對應(yīng)動畫對象的各個動作/行為名稱,與MovieClip中幀標(biāo)簽名稱一致,程序中將以此名稱來動態(tài)播放各種動作。
Bone Tree: 動畫對象的各個骨骼組成部分,與MovieClip中各層名稱一致。
Texture List: 動畫對象中各部分對應(yīng)的材質(zhì)名稱。
對于每個動作,首先要設(shè)置的參數(shù)如下:
Total Frame: 當(dāng)前動作的總幀數(shù)。幀數(shù)越大,動作越慢。
Tween Frame: 設(shè)置其他動作切換到此動作需要的幀數(shù)。比如,你的游戲角色有個動作為蹲下,此動作在時間軸上僅有1幀。假如設(shè)置此參數(shù)為6,那么當(dāng)游戲中從其他動作切換到蹲下時候,程序會自動增加6幀的過渡,讓各個動作切換更加自然。
Keyframe. Ease: 當(dāng)前動作各關(guān)鍵幀之間的緩動系數(shù)。
Loop: 當(dāng)前動作是否循環(huán)播放。比如角色的走、跑步等。
A當(dāng)設(shè)置好上述參數(shù),你可以在左下方的預(yù)覽區(qū)域中看到當(dāng)前編輯動作的動畫。
預(yù)覽窗口左上角可以縮放預(yù)覽對象,便于觀察的動作。
OK,接下來我們在Bone Tree面板中設(shè)置動作中各個骨骼的從屬關(guān)系。下圖可以看到在默認(rèn)導(dǎo)入的動畫中,各個骨骼沒有關(guān)聯(lián):
在此面板中右上角的 可以設(shè)置在預(yù)覽窗口里當(dāng)前選中骨骼的高亮顏色。
在列表里我們可以拖拽的方式,將子骨骼附著在父骨骼上。如下圖,我們將身體設(shè)置為主骨骼,而頭、尾巴、上肢和下肢都為其子骨骼。而上肢中又包含了上臂、下臂和手等。通過樹形結(jié)構(gòu)我們可以非常直觀的看到他們的從屬關(guān)系。
我們可以對每個骨骼的運(yùn)動參數(shù)進(jìn)行單獨(dú)設(shè)置。在Bone Tree面板中選中你需要設(shè)置的骨骼,調(diào)節(jié)下列參數(shù)。
Tween Time Scale: 設(shè)置當(dāng)前骨骼運(yùn)動時間相對動作總時間(總幀數(shù))的增加或減少。
Tween Time Delay: 設(shè)置當(dāng)前骨骼開始運(yùn)動時間相對所屬動作的延遲或提前。
別小看這2個參數(shù),各個骨骼通過這2個參數(shù)微調(diào)后,你會發(fā)現(xiàn)角色動作哪怕在時間軸上僅有2個關(guān)鍵幀,也會產(chǎn)生非常復(fù)雜的動作。
例如本例中,我們把龍的尾巴tail的Tween Delay設(shè)置為-10,尾巴尖tailTip的Tween Delay設(shè)置為-50,你可以明顯看到尾巴隨著身體的運(yùn)動甩動起來,非常的生動。;)
當(dāng)你調(diào)整完骨骼動畫,就可以點(diǎn)擊”Export”按鈕導(dǎo)出。
在導(dǎo)出格式選項(xiàng)中,包含多種數(shù)據(jù)格式供你實(shí)際項(xiàng)目需求。
- SWF (XML Merged): 包含骨骼XML數(shù)據(jù)的SWF格式,如果游戲需要矢量的骨骼動畫可以采用此格式導(dǎo)出,當(dāng)然前提是原始素材都是矢量的。
- PNG(XML Merged): 包含骨骼XML數(shù)據(jù)的PNG格式。
- Zip(XML and SWF): 分開保存的骨骼XML數(shù)據(jù)和SWF資源。
- Zip(XML and PNG): 分開保存的骨骼XML數(shù)據(jù)和PNG圖片。
- Zip(XML and PNGs): 分開保存的骨骼XML數(shù)據(jù)和按每個骨骼獨(dú)立的PNG圖片包。
例如在本例中,我們選擇PNG(XML Merged),點(diǎn)擊OK導(dǎo)出文件DragonWalk.png到指定的目錄。
你會發(fā)現(xiàn)導(dǎo)出的就一個PNG文件?是的,我們選擇了合并XML數(shù)據(jù)的PNG格式,所以此文件中包含了骨骼動畫需要的所有數(shù)據(jù)。
作為設(shè)計師,到此你的工作圓滿完成。
朱先忠注:
接下來,我們所需要了解的是,研究中的COCOS2D-X示例代碼,以便使用C++把上述FLASH數(shù)據(jù)呈現(xiàn)于你的COCOS2D-X游戲中。
因此,下面的內(nèi)容僅僅參考。
教程2:針對程序開發(fā) 在ActionSript項(xiàng)目中應(yīng)用骨骼動畫
在設(shè)計師用骨骼動畫編輯面板導(dǎo)出好相關(guān)格式數(shù)據(jù)之后,程序開發(fā)者就可以運(yùn)用DragonBones的開源動畫框架將數(shù)據(jù)資源導(dǎo)入到程序并讓動畫角色運(yùn)動起來。只需幾步操作,非常簡單!
接下來,你將了解如何在傳統(tǒng)DisplayList或支持GPU加速的Starling框架中調(diào)用骨骼動畫。
下載Skeleton Animation Framework,將這個包導(dǎo)入至你的開發(fā)項(xiàng)目中。
在開始代碼前,讓我們了解下骨骼動畫框架的基本概念。
Factory: 這是構(gòu)建骨骼動畫的基礎(chǔ)。它負(fù)責(zé)從前面骨骼面板導(dǎo)出的資源中解析數(shù)據(jù)格式和準(zhǔn)備圖像資源,并且通過它創(chuàng)建骨骼容器Armature。
Armature: 我們可以把它想像為一個容器,它對應(yīng)在Flash Pro中編輯并通過骨骼面板導(dǎo)出的一個MoiveClip。通過Armature來對各骨骼進(jìn)行管理,播放動畫等。
現(xiàn)在我們來看看在在傳統(tǒng)DisplayList顯示模式中添加骨骼的示例。打開此教程對應(yīng)的源文件DB_Tutorial_Walk_DisplayList.as。
首先,將骨骼面板導(dǎo)出的資源嵌入到項(xiàng)目。
?| [Embed(source = "../assets/Dragon1.swf", mimeType = "application/octet-stream")]? private static const ResourcesData:Class; |
此處嵌入的資源是由Flash Pro骨骼動畫編輯面板導(dǎo)出的合并了XML數(shù)據(jù)文件的PNG文件或SWF文件。當(dāng)然,你也可以通過動態(tài)加載的方式在項(xiàng)目運(yùn)行時候?qū)崟r載入資源。
創(chuàng)建factory,并通過fromRawData方法解析載入的資源格式,當(dāng)解析完畢后交給對應(yīng)事件textureCompleteHandler處理。
?| factory = new BaseFactory(); factory.addEventListener(Event.COMPLETE, textureCompleteHandler); factory.parseData(new ResourcesData()); |
事件函數(shù)textureCompleteHandler中,首先用buildArmature方法構(gòu)建骨骼動畫容器:
?| armature = factory.buildArmature("Dragon"); |
然后將容器的顯示內(nèi)容armature.display添加到場景:
?| addChild(armature.display as Sprite); |
指定要播放骨骼的某個動作:
?| armature.animation.play("walk"); |
最后,為ENTER_FRAME事件函數(shù)中添加armature.update()方法,讓SWF每幀渲染時候更新骨骼動畫。
OK,僅此幾行代碼,你就可以將骨骼動畫添加到已有項(xiàng)目。很簡單,不是么?:)
下面我們聊聊在Starling中添加骨骼動畫的方法。Starling是一個非常不錯的開源游戲框架,它可以幫助你快速創(chuàng)建基于Stage 3D技術(shù)GPU加速的2D游戲。如果你對它還不了解,請訪問Starling的官方網(wǎng)站:http://starlingframework.org。
使用Starling的用戶或許對用Sprite Sheet的位圖序列來構(gòu)建動畫非常熟悉,這種方式最大問題是對于復(fù)雜動畫會占用過多內(nèi)存。以下圖為例,一個簡單的行走動作,就會占用一大張位圖材質(zhì)。
而DragonBones解決了這個問題,不但僅需要少量骨骼素材,而且可以讓動畫更加豐富生動。
DragonBones可以完美的結(jié)合Starling,創(chuàng)建基于GPU加速的2D骨骼動畫。
打開本示例的項(xiàng)目DBStarlingWalk.as源碼你會發(fā)現(xiàn),我們創(chuàng)建了一個基于Starling的factory:
| factory = new StarlingFactory(); |
而余下的代碼,跟上個DisplayList的示例代碼完全一致。
關(guān)于Starling中嵌入的骨骼動畫素材資源,可以是合并骨骼XML數(shù)據(jù)的PNG格 式,也可以是合并XML數(shù)據(jù)的SWF格式。對于SWF格式的矢量資源,Skeleton Animation Framework會自動在程序運(yùn)行時轉(zhuǎn)換矢量為位圖材質(zhì),節(jié)省你項(xiàng)目尺寸。?
教程3:創(chuàng)建并控制多個動作的骨骼動畫
接下來你將了解到運(yùn)用DragonBones創(chuàng)建包含多個動作的骨骼動畫,并在程序中通過鍵盤交互控制動作。
打開文件 DragonBones_Tutorial_MultiBehavior.fla,雙擊庫里的動畫元件Dragon,你可以看到此動畫中有四個動 作:stand,walk,jump和fail。每個動作的起始幀上添加了對應(yīng)的幀標(biāo)簽,這也是DragonBones識別不同動作的標(biāo)識。
打開骨骼動畫編輯面板,你會看到在Behavior. List里面會有多個動作,選擇某個動作就可以為對應(yīng)動作設(shè)置動畫幀數(shù)、緩動,設(shè)置此動作的某個骨骼的細(xì)節(jié)參數(shù)等。
請留意Behavior編輯里的Tween Frame選項(xiàng)。
這個選項(xiàng)是表明的其他動作切換到當(dāng)前動作需要的過渡幀數(shù)。例如這里設(shè)置 的跳躍動作的Tween Frame為3,那么其他動作切換到跳躍需要3幀,DragonBones框架會自動為你添加其中的過渡幀,讓各種動作之間切換變得自然。當(dāng)然,你可以在 動畫預(yù)覽窗口中看到各種動畫的切換效果。
調(diào)整完畢各個動作的細(xì)節(jié)后,點(diǎn)擊“Export”按鈕導(dǎo)出骨骼動畫數(shù)據(jù)。
打開DBStarlingMultiBehavior.as文件,代碼如下。此示例是在Starling框架中通過鍵盤控制骨骼動畫運(yùn)動。
?| package { ????import dragonBones.Armature; ????import dragonBones.factorys.StarlingFactory; ????? ????import flash.ui.Keyboard; ????? ????import starling.display.Sprite; ????import starling.events.EnterFrameEvent; ????import starling.events.KeyboardEvent; ????import starling.text.TextField; ????? ????? ????public class DBStarlingMultiBehavior. extends Sprite ????{ ????????[Embed(source = "../assets/Dragon2.png", mimeType = "application/octet-stream")] ????????public static const ResourcesData:Class; ????????? ????????private var factory:StarlingFactory; ????????private var armature:Armature; ????????private var armatureClip:Sprite; ? ????????private var isLeft:Boolean; ????????private var isRight:Boolean; ????????private var isJumping:Boolean; ????????private var moveDir:int=0; ????????private var speedX:Number = 0; ????????private var speedY:Number = 0; ????????private var textField:TextField ????????? ????????public function DBStarlingMultiBehavior() ????????{ ????????????factory = new StarlingFactory(); ????????????factory.addEventListener(Event.COMPLETE, textureCompleteHandler); ????????????factory.parseData(new ResourcesData()); ? ????????} ????????? ????????private function textureCompleteHandler():void ????????{ ????????????armature = factory.buildArmature("Dragon"); ????????????armatureClip = armature.display as Sprite; ????????????armatureClip.x = 400; ????????????armatureClip.y = 550; ????????????addChild(armatureClip); ????????????updateBehavior() ????????????addEventListener(EnterFrameEvent.ENTER_FRAME, onEnterFrameHandler); ? ????????????stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyEventHandler); ????????????stage.addEventListener(KeyboardEvent.KEY_UP, onKeyEventHandler); ????????????? ????????????textField=new TextField(400,30,"A-move left,D-move right,W-jump","Verdana",16,0,true) ????????????textField.x=60; ????????????textField.y=2; ????????????addChild(textField); ????????} ????????? ????????private function onKeyEventHandler(e:KeyboardEvent):void ????????{ ????????????switch (e.keyCode) ????????????{ ????????????????case Keyboard.A : ????????????????case Keyboard.LEFT : ????????????????????isLeft=e.type == KeyboardEvent.KEY_DOWN; ????????????????????break; ????????????????case Keyboard.D : ????????????????case Keyboard.RIGHT : ????????????????????isRight=e.type == KeyboardEvent.KEY_DOWN; ????????????????????break; ????????????????case Keyboard.W : ????????????????case Keyboard.UP : ????????????????????jump(); ????????????????????break; ????????????} ????????????var dir:int; ????????????if (isLeft && isRight) ????????????{ ????????????????dir=moveDir; ????????????????return; ????????????} ????????????else if (isLeft) ????????????{ ????????????????dir=-1; ????????????} ????????????else if (isRight) ????????????{ ????????????????dir=1; ????????????} ????????????else ????????????{ ????????????????dir=0; ????????????} ????????????if(dir==moveDir) ????????????{ ????????????????return; ????????????} ????????????else ????????????{ ????????????????moveDir=dir; ????????????} ????????????updateBehavior() ????????} ????? ????????private function onEnterFrameHandler(_e:EnterFrameEvent):void ????????{ ????????????updateMove(); ????????????armature.update(); ????????} ? ????????private function updateBehavior():void ????????{ ????????????if (isJumping) ????????????{ ????????????????return; ????????????} ????????????if (moveDir == 0) ????????????{ ????????????????speedX = 0; ????????????????armature.animation.gotoAndPlay("stand"); ????????????} ????????????else ????????????{ ????????????????speedX=6*moveDir; ????????????????armatureClip.scaleX = -moveDir; ????????????????armature.animation.gotoAndPlay("walk"); ????????????} ????????} ????????private function updateMove():void ????????{ ????????????if (speedX != 0) ????????????{ ????????????????armatureClip.x += speedX; ????????????????if (armatureClip.x < 0) ????????????????{ ????????????????????armatureClip.x = 0; ????????????????} ????????????????else if (armatureClip.x > 800) ????????????????{ ????????????????????armatureClip.x = 800; ????????????????} ????????????} ????????????if (isJumping) ????????????{ ????????????????if (speedY <= 0 && speedY + 1 > 0 ) ????????????????{ ????????????????????armature.animation.gotoAndPlay("fall"); ????????????????} ????????????????speedY += 1; ????????????} ????????????if (speedY != 0) ????????????{ ????????????????armatureClip.y += speedY; ????????????????if (armatureClip.y > 540) ????????????????{ ????????????????????armatureClip.y = 550; ????????????????????isJumping = false; ????????????????????speedY = 0; ????????????????????updateBehavior(); ????????????????} ????????????} ????????} ????????private function jump():void ????????{ ????????????if (isJumping) ????????????{ ????????????????return; ????????????} ????????????speedY = -25; ????????????isJumping = true; ????????????armature.animation.gotoAndPlay("jump"); ????????} ????} } |
通過上面的代碼我們可以發(fā)現(xiàn),我們只需要在程序中需要播放相關(guān)骨骼動畫的時候調(diào)用函數(shù)armature.animation.gotoAndPlay()即可。
除了指定需要播放的動作名稱,你還可以通過此函數(shù)來動態(tài)指定動作的總幀數(shù)、是否循環(huán)等。
對于每個動畫,除了指定其播放之外,DragonBones框架提供了動畫播放相關(guān)的各種事件。
動作切換事件:
?| armature.addEventListener(dragonbones.events.Event.MOVEMENT_CHANGE, aramtureEventHandler); |
動作開始事件:
?| armature.addEventListener(dragonbones.events.Event.START, aramtureEventHandler); |
動作結(jié)束事件
?| armature.addEventListener(dragonbones.events.Event.COMPLETE, aramtureEventHandler); |
動作循環(huán)完畢事件:
?| armature.addEventListener(dragonbones.events.Event.LOOP_COMPLETE, aramtureEventHandler); |
通過各種事件與動作的配合,你可以輕松創(chuàng)建具有復(fù)雜運(yùn)動角色的游戲。?
控制骨骼框架中的每根骨頭
對于一個有趣的游戲,僅僅播放預(yù)先設(shè)置的骨骼動畫或許不夠,我們需要角色具有動態(tài)可控的各自動作。令人高興的是DragonBones提供了訪問并控制骨骼框架里每根骨頭的方法,讓你的角色在游戲中隨意運(yùn)動。
此示例通過鼠標(biāo)在場景中的移動來控制骨骼。我們創(chuàng)建了一個跟隨鼠標(biāo)運(yùn)動的小鳥,小龍人會與小鳥保持一定距離,同時小龍人的頭和胳膊會跟隨小鳥運(yùn)動而做出不同姿勢,非常有趣。
打開DBStarlingControlBone.as,代碼如下。
?| package { ????import dragonBones.Armature; ????import dragonBones.Bone; ????import dragonBones.factorys.StarlingFactory; ????? ????import flash.geom.Point; ????import flash.ui.Mouse; ????? ????import starling.display.Image; ????import starling.display.Sprite; ????import starling.events.EnterFrameEvent; ????import starling.events.TouchEvent; ????import starling.textures.Texture; ????? ????? ????public class DBStarlingControlBone extends Sprite ????{ ????????[Embed(source = "../assets/Dragon2.png", mimeType = "application/octet-stream")] ????????public static const ResourcesData:Class; ????????? ????????[Embed(source = "../assets/starling.png")] ????????private static const starlingImg:Class; ????????? ????????private var factory:StarlingFactory; ????????private var armature:Armature; ????????private var armatureClip:Sprite; ????????? ????????private var mouseX:Number = 0; ????????private var mouseY:Number = 0; ????????private var moveDir:int=0; ????????private var dist:Number; ????????private var speedX:Number = 0; ????????private var starlingBird:Image; ????????private var _r:Number; ????????? ????????private var _head:Bone; ????????private var _armR:Bone; ????????private var _armL:Bone; ????????? ????????public function DBStarlingControlBone() ????????{ ????????????factory = new StarlingFactory(); ????????????factory.addEventListener(Event.COMPLETE, textureCompleteHandler); ????????????factory.parseData(new ResourcesData()); ????????} ????????private function textureCompleteHandler():void ????????{ ????????????armature = factory.buildArmature("Dragon"); ????????????armatureClip = armature.display as Sprite; ????????????? ????????????armatureClip.x = 400; ????????????armatureClip.y = 550; ????????????addChild(armatureClip); ????????????updateBehavior(0) ????????????addEventListener(EnterFrameEvent.ENTER_FRAME, onEnterFrameHandler); ????????????stage.addEventListener(TouchEvent.TOUCH, onMouseMoveHandler); ????????????? ????????????starlingBird=new Image(Texture.fromBitmap(new starlingImg())) ????????????addChild(starlingBird); ????????????Mouse.hide(); ????????????//get the bones which you want to control ????????????_head = armature.getBone("head"); ????????????_armR = armature.getBone("armUpperR"); ????????????_armL = armature.getBone("armUpperL"); ????????????? ????????} ????????? ????????private function onEnterFrameHandler(_e:EnterFrameEvent):void ????????{ ????????????checkDist(); ????????????updateMove(); ????????????updateBones(); ????????????armature.update();????? ????????} ????????? ????????private function checkDist():void ????????{ ????????????dist = armatureClip.x-mouseX; ????????????if(dist<150) ????????????{ ????????????????updateBehavior(1) ????????????} ????????????else if(dist>190) ????????????{ ????????????????updateBehavior(-1) ????????????} ????????????else ????????????{ ????????????????updateBehavior(0) ????????????} ????????????? ????????} ????????? ????????private function onMouseMoveHandler(_e:TouchEvent):void ????????{ ????????????var _p:Point = _e.getTouch(stage).getLocation(stage); ????????????mouseX = _p.x; ????????????mouseY = _p.y; ????????????starlingBird.x=mouseX-73; ????????????starlingBird.y=mouseY-73; ????????} ????????private function updateBehavior(dir:int):void ????????{ ????????????if(moveDir==dir)return; ????????????moveDir=dir; ????????????if (moveDir == 0) ????????????{ ????????????????speedX = 0; ????????????????armature.animation.gotoAndPlay("stand"); ????????????} ????????????else ????????????{ ????????????????speedX=6*moveDir; ????????????????armature.animation.gotoAndPlay("walk"); ????????????} ????????} ????????private function updateMove():void ????????{ ????????????if (speedX != 0) ????????????{ ????????????????armatureClip.x += speedX; ????????????????if (armatureClip.x < 0) ????????????????{ ????????????????????armatureClip.x = 0; ????????????????} ????????????????else if (armatureClip.x > 800) ????????????????{ ????????????????????armatureClip.x = 800; ????????????????} ????????????} ????????} ????????private function updateBones():void ????????{ ????????????//update the bones' pos or rotation ????????????_r = Math.PI + Math.atan2(mouseY - armatureClip.y+armatureClip.height/2, ??????????????????????????????????????mouseX - armatureClip.x); ????????????if (_r > Math.PI) ????????????{ ????????????????_r -= Math.PI * 2; ????????????} ????????????_head.node.rotation = _r*0.3??????? ????????????_armR.node.rotation = _r *0.8; ????????????_armL.node.rotation = _r * 1.5; ????????????? ????????????starlingBird.rotation = _r*0.2; ????????} ????} } |
從上面代碼我們可以看到,通過方法dragonBones.Armature.getBone(_name:String):Bone來獲取某個骨骼。骨骼中的node對象包含了此骨骼的位置坐標(biāo),旋轉(zhuǎn)弧度,拉伸比例,傾斜數(shù)據(jù)等等。我們根據(jù)游戲邏輯的需要對骨骼的這些參數(shù)賦數(shù),即可實(shí)現(xiàn)動態(tài)控制此骨骼的效果。
在上面示例中,請留意updateBones()函數(shù)里,我們先獲取到當(dāng)前鼠標(biāo)位置與骨骼框架中心點(diǎn)的夾角,然后根據(jù)這個角度,來改變小龍人的頭部和胳膊的旋轉(zhuǎn)弧度,從而實(shí)現(xiàn)了這個有趣的效果。
實(shí)現(xiàn)骨骼動畫換裝
在游戲中我們往往有這樣的需求:角色更換服飾、裝備或武器等。對于DragonBones來說,所謂的換裝可以通過更換對應(yīng)骨骼的材質(zhì)來輕松實(shí)現(xiàn)。
因?yàn)槭歉鼡Q骨骼的材質(zhì),所以我們可以在程序中動態(tài)創(chuàng)建新材質(zhì)并賦予對應(yīng)骨骼,新的材質(zhì)可 以是來自其他方式創(chuàng)建或加載的圖片,也可以來自DragonBones骨骼動畫編輯面板導(dǎo)出的材質(zhì)圖集(Texture Atlas)。或許你會問,如何在Flash Pro中把沒有預(yù)先放在動畫時間軸的材質(zhì)一起打包在骨骼動畫編輯面板導(dǎo)出的材質(zhì)圖集中呢?
打開本教程的示例文件DragonBones_Tutorial_ChangeClothes.fla 。這個文件中,我們把動畫元件Dragon穿上了一件黃馬褂,將其放在時間軸上名為clothes的層上,并調(diào)整符合各種動作。
然后請注意庫中的clothTextureTemp動畫元件,雙擊打開 它,你會發(fā)現(xiàn)我們把打算換裝的4件衣服放在時間軸不同層上,并分別將層名稱與其對應(yīng)。這4件衣服因?yàn)榇笮⌒螤钜粯?#xff0c;所以在層中重合了。不過實(shí)際項(xiàng)目中,很 多時候更換的衣服、武器或道具大小不盡相同,所以需要相對于骨骼動畫中原始服飾的位置調(diào)整好各自坐標(biāo)位置。
留意在層label上我們給第一幀的幀標(biāo)簽取名為temp。因?yàn)闆]有幀標(biāo)簽的動畫元件,是不會被骨骼動畫編輯面板識別導(dǎo)入的。
選中庫中的Dragon和clothTextureTemp兩個元件, 打開骨骼動畫編輯面板,點(diǎn)擊“Import”按鈕導(dǎo)入所選的元件,你會發(fā)現(xiàn)在面板中Armature List里有了一個名為clothTextureTemp的骨架并且包含clothes1至clothes4的骨骼。不用管它,我們將它們導(dǎo)入面板的目的 不是為了編輯骨骼動畫,僅僅是為了最終導(dǎo)出這些服裝材質(zhì)與骨骼動畫材質(zhì)到一個文件中。
接下來你只需對Dragon這個骨架進(jìn)行相關(guān)的骨骼動畫調(diào)整,然后點(diǎn)擊”Export”按鈕導(dǎo)出素材資源。這里我們導(dǎo)出為合并XML數(shù)據(jù)的DragonWithClothes.png 。你會發(fā)現(xiàn)導(dǎo)出的材質(zhì)圖集中包含了我們需要的各自衣服。:)
現(xiàn)在我們看看在程序中如何實(shí)現(xiàn)換裝。打開教程3中創(chuàng)建的DBStarlingMultiBehavior.as文件,我們直接在這個文件中添加換裝代碼即可。首先將嵌入的素材更改為DragonWithClothes.png:
?| [Embed(source = "../assets/DragonWithClothes.png", mimeType = "application/octet-stream")] |
然后添加2個變量,數(shù)組textures保存了我們要更換服裝材質(zhì)的名稱,整數(shù)textureIndex用來做切換材質(zhì)時候的索引。
?| private var textures:Array = ["parts/clothes1", "parts/clothes2", "parts/clothes3", "parts/clothes4"]; private var textureIndex:int = 0; |
請注意這里寫的是“parts/clothes1”而不是 “clothes1”,原因是Flash Pro的庫中不同目錄的元件名稱可以相同,所以DragonBones在保存資源路徑的時候也包含了目錄結(jié)構(gòu)。打開 DragonBones_Tutorial_ChangeClothes.fla看看庫里的衣服動畫元件所在的目錄你就明白了。:)
在鍵盤響應(yīng)函數(shù)onKeyEventHandler中添加下面代碼,這樣按下鍵盤C鍵的時候調(diào)用換裝函數(shù)。
?| case Keyboard.C: ????if (e.type == KeyboardEvent.KEY_UP) { ????????changeClothes(); ????} ????break; |
創(chuàng)建換裝函數(shù)changeClothes()如下:
?| private function changeClothes():void { ????//循環(huán)更換貼圖 ????textureIndex++; ????if (textureIndex >= textures.length) { ????????textureIndex = textureIndex - textures.length; ????} ????//從骨骼面板導(dǎo)出的textureData中獲取Image實(shí)例,也可以單獨(dú)從其他圖片文件中構(gòu)造Image ????var _textureName:String = textures[textureIndex]; ????var _image:Image = StarlingFactory.getTextureDisplay(factory.textureData, _textureName); ????//用image替換bone.display完成換裝(注意bone.display的回收) ????var _bone:Bone = armature.getBone("clothes"); _bone.display.dispose(); ????_bone.display = _image; } |
這里我們用到了 dragonBones.factorys.StarlingFactory.getTextureDisplay(_textureData:TextureData, _fullName:String):Image來獲取由骨骼動畫編輯面板導(dǎo)出的材質(zhì)數(shù)據(jù),然后將對應(yīng)的材質(zhì)賦予給骨骼的display對象,實(shí)現(xiàn)了換 裝。當(dāng)然,正如前面所說,換裝的材質(zhì)可以隨意來自程序中載入的其他圖片資源。
W另外,當(dāng)你熟悉了DragonBones的開源框架,你會發(fā)現(xiàn)可以通過代碼實(shí)現(xiàn)更加靈活的變換,除了更換骨骼材質(zhì),你還可以在骨骼框架(Armature)中動態(tài)的刪除、添加骨骼,改變骨骼的從屬關(guān)系等。
OK,到此你掌握了如何在DragonBones中為你的游戲角色換裝,趕緊在你的游戲中試試吧。:)
總結(jié)
以上是生活随笔為你收集整理的使用DragonBones开发FLASH骨骼动画入门教程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 春节没事,看几部黑客电影吧!
- 下一篇: 有线数字电视机顶盒的基本原理