
這篇要來把動畫跟AS3串接起來。用SpriterAS+Starling來做。
SpriterAS是一款基於Starling架構,專門播放Spriter動畫的AS3 Library。由加拿大的TreeFortress小組所開發。(TreeFortress專注於Mobile Game開發,成員包括了知名的gskinner大神)
.先看一下範例:

(click to open)
.Download Source
上述範例我在Spriter裏做了三則animation,分別是idle(平常狀況)、fight_0(輕拳)、fight_1(重拳)。其他如眨眼、拳頭上的特效、頭掉下來,都是由程式控制的,而SpriterAS也支援Playback Speed的控制,這也是突顯了元件動畫優於連續圖檔的一大強項。
TreeFortress有寫了一篇Introducting SpriterAS - Play Spriter Animations with Starling。算是SpriterAS的入門介紹文,本篇範例也是看完他們的介紹文後的產物。建議有空可以先去看看,以下我只挑幾個重點介紹。
.github載點 https://github.com/treefortress/SpriterAS
.載入scml並叫出動畫
//**注意:SpriterAS是建立在Starling之上的,必需在Starling內 //**使用下列程式才能有作用。 protected var spLoader:SpriterLoader; protected function init():void{ spLoader = new SpriterLoader(); spLoader.completed.add(onSpriterLoadComplete); //SpriterLoader可一次載入多個scml檔,所以參數是填一個array,可代入多個scml位置 spLoader.load(['assets/hero/hero.scml'],1) } protected function onSpriterLoadComplete(spLoader:SpriterLoader):void { //從loader中取得動畫,以scml名稱為索引 hero = spLoader.getSpriterClip('hero') //idle是hero.scml裏其中一段animation的名稱 hero.play("idle") hero.x = 100 hero.y =300 addChild(hero) Starling.juggler.add(hero) }這裏需要注意一點是,spLoader必需是class內的固定成員,不可以是function中的區域變數,例如我試過以下這樣寫的話,onSpriterLoadComplete將無法被觸發:
protected function init():void{ var spLoader:SpriterLoader = new SpriterLoader();//不能用區域宣告 spLoader.completed.add(onSpriterLoadComplete); spLoader.load(['assets/hero/hero.scml'],1) }
.按下button切換animation至"fight_0"(輕拳),並在播放完畢時,切回"idle"
private function onClickFight0(e:MouseEvent):void { hero.play("fight_0") hero.addCallback(onOverFight,400)//400ms後呼叫onOverFight } protected function onOverFight():void{ if(hero.animation.name != 'idle')hero.play("idle") }直接使用 play("animation名稱"),即可切換動畫。
而 addCallback則是一個相當實用的method,可設定動畫播到多少ms時回call某個function,而此ms數會依照當初在Spriter裏設定的timeline來執行,因此不會受playback speed而受影響。
完整使用方式是:
addCallback(回call的function, 回call時間, 是否只執行一次)
.眨眼功能(動態切換元件)
private function onClickBlink(e:MouseEvent):void { hero.swapPiece("head_0", "head_1"); TweenLite.delayedCall(.1,hero.unswapPiece,['head_0']) }swapPiece("A", "B")可將動畫中的A圖換成B圖。
unswapPiece("A")則是取消加諸在"A"身上的任何swapPiece效果。
.附著在拳頭上的粒子效果:
private function getHandPos():Point{ var handImg:Image //Starling中的Image handImg = hero.getImage("leftHand_0"); return new Point(handImg.x,handImg.y) }粒子效果非本篇重點,所以特效的部份就不多寫,上述程式只針對取得拳頭位置做示範,不過這邊要注意,取得的handImg.x及y後,記得還要加上hero.x及y,才是拳頭在畫面上看到的位置。
.頭掉下來(動態將元件拆離scml設定,或再組合回去)
private function onClickDropHead(e:MouseEvent):void { var headImg:Image = hero.getImage("head_0") if(headImg.y>-100){//弱弱的用y的位置來判斷目前頭的狀況 hero.includePiece(headImg);//組回 return; } hero.excludePiece(headImg,true)//脫離 TweenLite.to(headImg,.6,{y:25,ease:Bounce.easeOut}) }
.playback speed 控制
private function onSlideFPS(e:Event):void { _stage.frameRate = _fpsSlider.value } private function onSlideSpeed(e:Event):void { hero.playbackSpeed = _speedSlider.value }這邊就沒什麼好解說的了,playbackSpeed代1的話表示正常進度,2為兩倍,0.5為半速,以此類推。
.動態才用到的元件
這邊算是個人使用心得。當我在製作範例中的眨眼功能,遇到了點小問題。原本我在Spriter裏編輯時只有三段animations,分別是idle, fight_0, fight_1,而這三段動畫完全沒用到眨眼的那張圖(head_1.png),使得當我在用hero.swapPiece("head_0", "head_1")時,會完全沒有做用。原因是當我查看scml檔的內容,發現scml在最前頭會先將所有圖檔列一份清單,之後的keyframe資訊就只會記下清單中的id,而這時又發現scml內只會記錄所有animation有用到過的圖檔,而不是所有放在project folder中的圖檔,所以它並沒有將我的head_1.png存進去,導致讓swapPiece("head_0", "head_1")無效。
變通的辨法是,再開一個新的animation,把所有程式會用到的圖都放進去,再輸出成scml即可。

例如上圖我就是把程式才會用到的圖,都放在"assets"這段animation裏。
.心得與注意事項:
SpriterAS使用下來,我個人覺得功能算是很完整了,已能符合大多數需求,唯一缺點是Spriter中的Bones功能尚未支援(如果有帶bone的scml,在spriterAS裏會爛掉),SpriterAS在官方blog是說未來會支援。不過我個人心得是,這部份還好,在我們真的在調比較細緻的動畫時,bones及IK其實沒什麼太大的幫助。另外作者群還有提到未來可能會推出JS版,有用JS的人可以期待一下。
*另一個library: SpriterMC有支援bones及IK,我在下一篇會簡單介紹一下SpriterMC
Index:
.Spriter好好玩系列 (一) ---- 什麼是Spriter ?
.Spriter好好玩系列 (二) ---- Spriter 基本操作
.Spriter好好玩系列 (三) ---- 使用SpriterAS
.Spriter好好玩系列 (四) ---- 使用SpriterMC
沒有留言:
張貼留言