在一般的2D遊戲中,動畫可以用2D骨骼動畫製作(如:Spine)、粒子系統(如:Particles)、或者使用Tween(如:gsap)以及逐格動畫來製作。
下面為這四種動畫的介紹:
骨骼動畫:針對角色動畫的骨架做設定,並且經由改變骨骼元件方向及變形來讓角色做出如行走、跳躍等動態動作。使用骨骼動畫可以大大降低角色所占的圖像空間,尤其是在2D的遊戲裡,這是不可或缺的技術。
粒子系統:有許多編輯器可以編輯出粒子效果的設定檔,並藉由粒子系統的程式來做出特效。
Tween:針對一個物件的某個屬性去設定一段時間將該屬性從a數值變成b數值。可以用在物件位移(更動x、y屬性)、放大縮小(更動scale)、旋轉(更動rotate)等效果上。也可以更改自定義屬性,如跑分效果(將分數慢慢加上去)。
下面是官網上的一個效果範例:
逐格動畫:逐格動畫是最簡單原始的動畫類型,由許多張的動態圖組合成為一幅動畫。逐格動畫的動畫製作能夠最精緻、最多樣化,但是也需要花最多力氣在繪製圖像,並且會有很大的檔案大小。其原理與一般電影、gif檔相同。
PIXI.extras.AnimatedSprite是在Pixi.JS裡處理動畫的類別,官網對此類別的說明如下:
An AnimatedSprite is a simple way to display an animation depicted by a list of textures.
也就是可以用來播放由多張連續的圖檔組成的逐格動畫,在前面的[13- 遊戲製作] 素材處理的部份,已經有分享過該如何將連續圖檔打包成所需的格式,在這一章裡,則會在遊戲裡來實際使用這些連續圖檔。
在遊戲中,我們希望角色動畫可以在不同的時間播放不同的動畫,讓角色與遊戲能夠更有互動感,播放時機與動畫的設計如下:
待機動畫:播放Character_Idle.json
消除成功時:播放Character_Laugh.json
按下提示時:播放Character_Jump.json
createAnim(id:string, onComplete:any){
let anim = Loader.resources[id].textures;
let textures = [];
for(var index in anim) {
textures.push(anim[index]);
}
var character = new PIXI.extras.AnimatedSprite(textures);
character.play();
character.animationSpeed = 0.25;
character.loop = false;
character.onComplete = onComplete;
this.addChild(character);
return character;
}
private shouldPlayTarget:string = 'idle';
constructor(){
super();
//每次動畫完成之後,都要判斷下一個要播放的動畫為何
this.idle = this.createAnim('Character_Idle', this.playAnim.bind(this));
this.jump = this.createAnim('Character_Jump', this.playAnim.bind(this));
this.laugh = this.createAnim('Character_Laugh', this.playAnim.bind(this));
eventEmitter.on(GameFlowEvent.LinkedLineSuccess, ()=>{
this.shouldPlayTarget = 'laugh';//設定下一個要播的動畫
});
eventEmitter.on(GameFlowEvent.TipsRequest, ()=>{
this.shouldPlayTarget = 'jump';
});
}
//依據shouldPlayTarget的值來判斷現在要播的動畫
//如果沒有特殊要播的動畫的話,則一律播放待機動畫
playAnim(){
this.idle.visible = false;
this.laugh.visible = false;
this.jump.visible = false;
this[this.shouldPlayTarget].visible = true;
this[this.shouldPlayTarget].gotoAndPlay(0);
this.shouldPlayTarget = 'idle';
}
在上面,我們是直接產生三個動畫物件,在需要使用時才會把visible設為true並且播放,因此要小心是否會造成效能問題,在研究了一下Container.js的原始碼,可以發現如果當元件的visible為false時,是不會去render這個物件的,也不會去處理其相關子元件的畫面變更。
Source:Container.js
在經過實測後,的確將畫面上不會被看到的元件的visible設為false後,能夠提升畫面的fps,因此這也是開發上一個可以多加利用的小技巧。
另外,filter的使用,會花費較多的效能,需要謹慎使用。而mask下的物件,即便因為mask而無法看到,仍舊會一直被render,因此即便是已經在mask下因此畫面上無法看見的元件,依然建議要把可試範圍外的物件的visible設為false,以提升遊戲效能。
線上demo:http://claire-chang.com/ironman2018/1104/
今日成果下載:ironman1104