說在前頭:
如果你看到上一篇的SpriterAS已經覺得很夠用的話,那這篇SpriterMC其實可以直接跳過。原因是我個人認為SpriterAS目前的實用性大過於SpriterMC,而寫這篇只是因為都花時間研究了,就留下點筆記而已。另外SpriterMC唯一較強的是目前有支援Spriter的Bones及IK,所以除非有此特別需求或是好奇想看看的話,個人建議可直接跳過。
(以上心得基於SpriterMC v1.3版的狀況)
.官網:http://www.sammyjoeosborne.com/SpriterMC/
.github載點:https://github.com/sammyjoeosborne/spritermc
.基本用法:http://wiki.starling-framework.org/extensions/spritermc#usage
.先看一下範例:
(click to open)
.Download Source
.載入SCML:
在官網中是這樣寫的:
var monster1:SpriterMC = SpriterMCFactory.createSpriterMC("monster", "xml/monster.scml"); monster1.play(); //Note: SpriterMC's will not actually start playing or show up on stage until SpriterMC.SPRITER_MC_READY is broadcast //Add each SpriterMC to a Juggler, just like a regular Starling MovieClip myJuggler.add(monster1);但他們另外提供了事先做好TextureAtlas的做法,並且推薦用這種:
var monster1:SpriterMC = SpriterMCFactory.createSpriterMC("monster", "xml/monster.scml", _textureAtlas); monster1.playbackSpeed = 1.5; //Demonstrating playbackSpeed, which is like Scale, 1 == 100%. You can also set negative values to play backward monster1.play(); //Note: SpriterMC's will not actually start playing or show up on stage until SpriterMC.SPRITER_MC_READY is broadcast //Add each SpriterMC to a Juggler, just like a regular Starling MovieClip myJuggler.add(monster1);但我個人測試結果是,你必需使用TextureAtlas的寫法,否則使用第一種的話,執行時會出現error。
.如何使用TextureAtlas:
照SpriterMC官網的說明,在他解析並產生這些SCML動畫時,會動態將所有的元件圖檔拼成一張大張的TextrueAtlas,這樣更能符合Starling的圖形加速處理,所以他建議使用者不如一開始自己就先手動做好拼圖這個動作。這件事我們可以利用TexturePacker來做(格式選AS3/Starling)。做完會像這樣:
一張大拼圖及一個xml描述檔。而AS3寫法可參考以下:
protected function init():void{ loadTexture('assets/heroTA.png') } private function loadTexture(_url:String):void { var _loader:Loader = new Loader(); _loader.contentLoaderInfo.addEventListener(starling.events.Event.COMPLETE, textureLoadedHandler); _loader.load(new URLRequest(_url)); } private function textureLoadedHandler(e:*):void { _heroTexture = Texture.fromBitmap(Bitmap(e.target.loader.content)); loadTextureAtlasXML("assets/heroTA.xml"); } private function loadTextureAtlasXML(_url:String):void { var _urlLoader:URLLoader = new URLLoader(new URLRequest(_url)); _urlLoader.addEventListener(starling.events.Event.COMPLETE, atlasXMLLoadedHandler); } private function atlasXMLLoadedHandler(e:*):void { var _xml:XML = XML(e.target.data); _textureAtlas = new TextureAtlas(_heroTexture, _xml); createCharacters(); } private function createCharacters():void { _hero = SpriterMCFactory.createSpriterMC("heroIK", "assets/heroIK/heroIK.scml",_textureAtlas,spriterReadyHandler,true); } private function spriterReadyHandler(e:starling.events.Event):void { _hero.x= 100 _hero.y=380 _hero.setAnimationByName('idle') _hero.play(); addChild(_hero); Starling.juggler.add(_hero) }
.頭尾相連的動畫
成功讀入scml後,首先會發現動畫有點問題,就是原本來Spriter裏,最後一個keyframe都會自動做tween連回第一個keyframe,除非你自己取消這個功能。但是從SpriterMC讀進來的動畫卻完全都沒有這個效果。
正常來說,我們在Spriter裏可以透過上圖a點來切換是否要開啟"頭尾相連"的功能,但在SpriterMC裏目前完全無效,所以變通的方法就是自行將0ms的keyframe複製到動畫最尾處,如上圖b點。
.動畫播完的callBack
這個功能對遊戲開發十分重要,例如我們做完一個攻擊、做完一個跳躍動畫,都會需要馬上切換至一般狀態的動畫,所以動畫播完呼叫一個callback會是十分常做的事情。在SpriterAS裏有提供了addCallBack這樣的method,但SpriterMC目前尚未提供這樣的api,我只能先用變通的方式來處理。
private function onClickJump(e:MouseEvent):void{ if(_hero.currentAnimation.name == 'jump')return; _hero.setAnimationByName('jump') _hero.loop=false; _hero.play() _hero.addEventListener(starling.events.Event.ENTER_FRAME,onEnterCheck); } protected function onEnterCheck(e:starling.events.Event):void{ if(_hero.isComplete){ _hero.removeEventListener(starling.events.Event.ENTER_FRAME,onEnterCheck); _hero.setAnimationByName('idle') _hero.loop=true; } }這邊我使用ENTER_FRAME不斷去check他的isComplete是否為true,如此才能知道他是不是播完了。而在使用isComplete時,有兩個注意事項:
1.需把loop設為false,如此isComplete才有機會變成true,否則會永遠得不到true。
2.我個人懷疑這是bug。當我設_hero.setAnimationByName('jump')並成功播完一次後,下次再執行_hero.play()時,isComplete會在一開始就是true了,也就是它並沒有因為重新play,而重設為false。為了解決這問題,我直接修改了SpriterMC裏Animation.as這支檔案的play函式:
internal function play():void { //if we aren't looping and play was called while the animation was on its last frame, restart it if (!_loop && _currentKeyIndex == _lastFrameIndex) { _currentTime = mainKeys[_firstFrameIndex].time; //this is gonna make currentTime 0 or the length of the animation, depending on which way the animation is playing _currentKeyIndex = _firstFrameIndex; } _animationEnded = false;//maso add _isPlaying = true; }修改過後就能正常執行了。
.其他心得
SpriterMC目前能做的應用很少,所以試到這裏就沒什麼好繼續了,所以其他請自行參閱官網。倒是有一點較特別的是,Spriter的timeline是以ms為單位,但SpriterMC裏卻提到了一個叫currentFrame屬性,這裏試了一下,所謂的frame其實是Spriter中的Keyframe,第一個Keyframe得到是0,第二個是1,以此類推。不過在沒有call back的應用下,這個currentFrame其實也沒太大的用處。
Index:
.Spriter好好玩系列 (一) ---- 什麼是Spriter ?
.Spriter好好玩系列 (二) ---- Spriter 基本操作
.Spriter好好玩系列 (三) ---- 使用SpriterAS
.Spriter好好玩系列 (四) ---- 使用SpriterMC
沒有留言:
張貼留言