Cocos Creator封裝自己的幀動(dòng)畫(huà)組件播放動(dòng)畫(huà)
在Cocos Creator游戲開(kāi)發(fā)的過(guò)程中我們進(jìn)行需要使用動(dòng)畫(huà)效果,雖然可以通過(guò)動(dòng)畫(huà)編輯器編輯動(dòng)畫(huà)效果,但是有時(shí)候用戶想更靈活的控制幀動(dòng)畫(huà)的效果,就需要自己封裝幀動(dòng)畫(huà)組件。
一、幀動(dòng)畫(huà)播放組件
1: creator播放幀動(dòng)畫(huà)需要通過(guò)動(dòng)畫(huà)編輯器去制作;
2: 為了方便控制和使用加入幀動(dòng)畫(huà)代碼播放組件;
3: 屬性設(shè)置:
? ? sprite_frames: 幀動(dòng)畫(huà)所用到的所有的幀;
? ? duration: 每幀的時(shí)間間隔;
? ? loop: 是否循環(huán)播放;
? ? play_onload: 是否加載組件的時(shí)候播放;
4: 接口設(shè)置:
? ? play_once(end_func); // 播放結(jié)束后的回掉函數(shù);
? ? play_loop(); // 循環(huán)播放;
二、幀動(dòng)畫(huà)播放原理
1: 對(duì)的時(shí)間播放顯示對(duì)的圖片:
假設(shè)以三幀動(dòng)畫(huà)為例,時(shí)間間隔就是duration,

三、自己封裝幀動(dòng)畫(huà)組件
const {ccclass, property} = cc._decorator;
@ccclass
export default class FrameAnim extends cc.Component {
? ?@property({type: [cc.SpriteFrame], tooltip:"幀動(dòng)畫(huà)圖片數(shù)組"})
spriteFrames : Array<cc.SpriteFrame> = [];
? ?@property({tooltip:"每一幀的時(shí)長(zhǎng)"})
duration : number = 0.1;
? ?@property({tooltip:"是否循環(huán)播放"})
? ?loop : boolean = false;
? ?@property({tooltip:"是否在加載的時(shí)候就開(kāi)始播放"})
playOnload : boolean = false;
? ?// 播放完后的回調(diào)函數(shù)
? ?private endFunc : any = null;
? ?// 動(dòng)畫(huà)播放需要的精靈組件
? ?private sprite : cc.Sprite;
? ?// 動(dòng)畫(huà)播放的狀態(tài),正在播放還是停止
? ?private isPlaying : boolean = false;
? ?// 記錄已經(jīng)播放的時(shí)間
private playTime : number = 0;
? ?onLoad () {
? ? ? ?// 獲取當(dāng)前動(dòng)畫(huà)組件掛載的節(jié)點(diǎn)上的Sprite組件,如果沒(méi)有則添加
this.sprite = this.node.getComponent(cc.Sprite);
? ? ? ?if(!this.sprite){
this.sprite = this.node.addComponent(cc.Sprite);
? ? ? ?}
? ? ? ?// 判斷是否是預(yù)加載播放
? ? ? ?if(this.playOnload){
? ? ? ? ? ?if(this.loop){
this.playLoop(); ? ? ? ?// 循環(huán)播放
? ? ? ? ? ?}else{
this.playOnce(null); ? ?// 只播放一次
? ? ? ? ? ?}
? ? ? ?}
}
? ?public playLoop() : void {
this.initFrame(true, null);
} ?
? ?public playOnce(endf : any) : void {
this.initFrame(false, endf);
}
? ?private initFrame(loop:boolean, endf : any) : void{
? ? ? ?if(this.spriteFrames.length <= 0){
? ? ? ? ? ?return;
? ? ? ?}
this.isPlaying = true;
this.playTime = 0;
this.sprite.spriteFrame = this.spriteFrames[0];
this.loop = loop;
this.endFunc = endf;
}
start () {
}
? ?update (dt) {
? ? ? ?if(!this.isPlaying){
? ? ? ? ? ?return;
? ? ? ?}
? ? ? ?// 累計(jì)時(shí)間,通過(guò)時(shí)間計(jì)算應(yīng)該取哪一張圖片展示
this.playTime += dt;
? ? ? ?let index : number = Math.floor(this.playTime / this.duration);
? ? ? ?if(this.loop){ ?// 循環(huán)播放
? ? ? ? ? ?if(index >= this.spriteFrames.length){
? ? ? ? ? ? ? ?index -= this.spriteFrames.length;
this.playTime -= (this.duration * this.spriteFrames.length);
? ? ? ? ? ?}
this.sprite.spriteFrame = this.spriteFrames[index];
? ? ? ?}else{ ? ? ? ? ?// 播放一次
? ? ? ? ? ?if(index >= this.spriteFrames.length){
this.isPlaying = false;
? ? ? ? ? ? ? ?// 如果有回調(diào)函數(shù)的處理,則調(diào)用回調(diào)函數(shù)
? ? ? ? ? ? ? ?if(this.endFunc){
this.endFunc();
? ? ? ? ? ? ? ?}
? ? ? ? ? ?}else{
this.sprite.spriteFrame = this.spriteFrames[index];
? ? ? ? ? ?}
? ? ? ?}
? ?}
}
四、測(cè)試封裝的幀動(dòng)畫(huà)組件

勾選PlayOnLoad和去掉的區(qū)別,勾選Loop和去掉的區(qū)別,可以發(fā)現(xiàn)預(yù)加載和循環(huán)播放。
如何在代碼中控制?
新建GameMgr.ts掛載到Canvas節(jié)點(diǎn)上。
import FrameAnim from "./FrameAnim";
const {ccclass, property} = cc._decorator;
@ccclass
export default class GameMgr extends cc.Component {
? ?@property({type: [FrameAnim], tooltip:"幀動(dòng)畫(huà)數(shù)組"})
? ?anim : Array<FrameAnim> = [];
// onLoad () {}
? ?endPlay(){
console.log("動(dòng)畫(huà)播放完畢?。?#34;);
? ?}
? ?start () {
? ? ? ?//this.anim[0].playOnce(this.endPlay);
? ? ? ?//this.anim[1].playOnce(this.endPlay);
? ? ? ?//this.anim[0].playOnce(null);
? ? ? ?//this.anim[1].playOnce(null);
? ? ? ?//this.anim[0].playLoop();
? ? ? ?//this.anim[1].playLoop();
? ? ? ?if(this.anim.length > 1){
this.anim[1].duration = 0.5;
this.anim[1].playOnce(this.endPlay);
? ? ? ?}
? ? ? ?if(this.anim.length > 0){
this.anim[0].playLoop();
? ? ? ?}
? ?}
}


更多教學(xué)視頻以及素材源碼:
https://bycwedu.vipwan.cn/promotion_channels/630597732