這篇開始來講Starling裡的Animation。Juggle是個簡單的Class,用來控制動畫的進行。他負責管理經由add()加進來的實現IAnimatable介面的物件,然後當Juggler的advanceTime()被呼叫時,它會負責去呼叫這些IAnimatable的advanceTime(),讓動畫進行下去;而當某個IAnimatable到達complete狀態時,則會被Juggler踢出去。我們就只要負責每個frame去呼叫Juggler的advanceTime()就好。而Starling class裡有個預設的juggler,當Starling.current正在運行時,Starling.juggler在每個frame時會自動被呼叫advanceTime()。通常我們把遊戲裡的動畫加到Starling.juggler裡,而一些特殊的動畫,例如遊戲暫停時要撥放的動畫,再加到另一個我們新增的Juggler,然後每個frame去呼叫它的advanceTime()。這裡講的每個frame,我們是使用EnterFrameEvent.ENTER_FRAME,而不是Event.ENTER_FRAME,因為EnterFrameEvent可以取得passedTime,這個passTime是指跟上一次事件發生經過的時間,可以傳給Juggle的advanceTime()的第一個參數。用經過時間來播放動畫,這樣就不會受frame數不穩定而影響動畫撥放的時間。
而要實現IAnimatable介面,只要實作advanceTime()這個方法,並且要設定一個complete條件,當達到這個條件時將自己的isComplete設為true,這樣就可以自動被Juggle移除。在Starling裡面,實現IAnimatable介面的除了Juggle以外,目前還有三種:Tween、DelayedCall以及MovieClip。接下來我們先來談前兩個。Tween的概念跟native的Tween或其他Tween API類似。Tween建構式可傳入三個參數,第一個是要產生動畫的目標,第二個是時間,第三個是transition,也就是ease function。transition可以查一下Transition Class,目前支援的function比起TweenMax這類的API要少得多,看看之後會不會新增,或者有沒有Extension可以用。新增了一個Tween之後,接著要設定要被改變的屬性。一般的數值型屬性可以使用animate()來設定,第一個參數是屬性名稱,使用字串來輸入,例如"x","rotation"等;第二個是目標值,例如0.5,20等等。常用的位移,改變大小,改變alpha值分別有對應的方法可以使用。也有onStart,onUpdate,onComplete等function可以設定。設定完Tween就使用Juggler的add將tween加進動畫執行。
DelayCall,顧名思義就是過一定時間之後再去呼叫某function。DelayedCall的建構式,第一個指定要call的function,第二個是delay時間,第三個是function需要的參數,用一個Array依序填入。設定好一樣要加到Juggler才會跑。
我們來寫個範例,在場景上放一個Button跟一個Image,當這個Button triggered,產生一個Tween去讓Image做些動畫,這個Tween我們交給Starling.juggler自動執行。當這個Tween執行完,我們新增一個DelayedCall,讓它停一小段時間之後,呼叫一個function,讓Image與Button回到原來的狀態。而這個DelayCall我們故意加到一個我們新增的Juggler,然後監聽EnterFrameEvent.ENTER_FRAME去呼叫這個Juggler的advanceTime()。程式碼如下:
publicclassGame6extendsSprite
{
privatevar _container:Sprite;
privatevar _image:Image;
privatevar _button:Button;
[Embed(source ="/assets/btnBg.png")]
privatestaticconstBtnBitmap:Class;
[Embed(source ="/assets/btnDownBg.png")]
privatestaticconstBtnDownBitmap:Class;
[Embed(source ="/assets/head.png")]
privatestaticconstHeadBitmap:Class;
privatevar _juggler:Juggler;
publicfunctionGame6()
{
super();
addEventListener(Event.ADDED_TO_STAGE, init);
}
privatefunction init(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
_container =newSprite();
addChild(_container);
addChild(newStats());
//新增一個Juggler
_juggler =newJuggler();
//新增一個Image
_image =newImage(Texture.fromBitmap(newHeadBitmap()));
_image.x =300;
_image.y =200;
_image.pivotX = _image.width >>1;
_image.pivotY = _image.height >>1;
_container.addChild(_image);
//新增一個Button
var btnTexture:Texture=Texture.fromBitmap(newBtnBitmap());
var btnDownTexture:Texture=Texture.fromBitmap(newBtnDownBitmap());
_button =newButton(btnTexture,"Tween", btnDownTexture);
_button.x =200;
_button.y =30;
_container.addChild(_button);
_button.addEventListener(Event.TRIGGERED, buttonTriggered);//監聽_button triggered事件
}
privatefunction buttonTriggered(e:Event):void
{
_button.enabled =false;//_button disable
var tween:Tween=newTween(_image,2,Transitions.EASE_OUT_BOUNCE);//新增一個Tween,控制_image
tween.animate("rotation",Math.PI /2);//增加旋轉動畫
tween.moveTo(300,400);//增加位移動畫
tween.fadeTo(0.5);//改變alpha
tween.scaleTo(0.5);//改變大小
tween.onComplete = tweenComplete;//結束時呼叫tweenComplete
Starling.juggler.add(tween);//將tween加到Starling.juggler自動執行
}
privatefunction tweenComplete():void
{
var delayedCall:DelayedCall=newDelayedCall(imageBack,0.5);//新增一個DelayedCall,過0.5秒呼叫imageBack()
//Starling.juggler.add(delayedCall);//可以直接加到Starling.juggler自動執行,但我們故意加到新增的_juggler
_juggler.add(delayedCall);//將delayedCall加到_juggler
addEventListener(EnterFrameEvent.ENTER_FRAME, onEnterFrame);//要手動監聽EnterFrameEvent.ENTER_FRAME,去呼叫_juggle.advanceTime()
}
privatefunction onEnterFrame(e:EnterFrameEvent):void
{
_juggler.advanceTime(e.passedTime);//手動執行_juggler.advanceTime(),將e.passedTime傳入
}
privatefunction imageBack():void
{
removeEventListener(EnterFrameEvent.ENTER_FRAME, onEnterFrame);//移除監聽
//讓image回到原來狀態,_button enable
_image.x =300;
_image.y =200;
_image.alpha =1;
_image.rotation =0;
_image.scaleX = _image.scaleY =1;
_button.enabled =true;
}
}
Demo如下:
http://dl.dropbox.com/u/9231233/blog/111116_starling_ianimatable/index.html