cocos creator实现读取白鹭movieClip组件(尝试)
背景:原本是做白鷺項目的,后續考慮換成creator,但是由于creator的動畫編輯器比較難受,而在白鷺那邊已經有了一些腳本工具,因此希望在creator上實現一個組件,直接能夠播放白鷺的movieClip。
? ? ? ? 在cocos社區找了一圈,沒有找到可以直接伸手的組件,故想著自己也試著來造造輪子。
期待的樣子:
1.實現movieClip控件(繼承Node節點),直接new出來,添加到對應節點下,然后可以調用load(fileName)接口直接加載資源。playMovie/loadAndPlay等直接播放或者加載播放對應的動畫/動作;一些額外回調操作;
2.實現movieClipComponent組件,可以掛載到節點上。具體是實現上述的需求。
首先做的一些準備:
? ? ? ? 1.封裝了讀取mc資源的接口,主要是來讀取json跟texture2d;
?加載json,加載texture,保證兩步都加載完成了,才進行下一步操作。
解析配置主要做的是把json里的資源resData跟? 動畫mcData保存下來。
實現思路:
? ? ? ? 1.當前幀包括當前動畫/當前動作/當前幀索引等。將這些作為一個私有變量保存起來,這樣可以隨時getter/setter。在數據發生變化的時候才重新去計算當前值。
? ? ? ? 2.基于update幀驅動或者計時器驅動,獲取當前幀的配置數據,將紋理渲染出來,然后索引+1,等待下一次刷新。
只是拿到了當前幀的配置數據,怎樣才能在雪碧圖里裁切出想要的子圖呢?
在這里我采取的辦法是spriteFrame中的設置rect,來實現子圖的效果。
在實現的路上,暫時忽略new過程中的性能損耗。。。。
3.后續又加入了循環以及播放次數的判斷。播放結束/完成等的判斷。
?最后終于能夠把動畫播放起來了。?
延時切換到該文件下的其他動畫,結果也是可行。?
最后是完整的代碼。。。。。
import { Node } from "cc"; import { MovieClipComponent } from "./MovieClipComponent";export class MovieClip extends Node{private _mcc:MovieClipComponent;private get mcc(){if(!this._mcc)this._mcc = this.addComponent(MovieClipComponent);return this._mcc;}private _fileName:string;constructor(){super();}onLoad(){};/*** 加載mc資源文件*/public loadFile(fileName:string){if(fileName === this._fileName){return;}this._fileName = fileName;this.mcc.loadFile(fileName);}/**加載并播放 指定文件名 動畫名 動作名 次數 加載完成回調*/public loadAndPlay(fileName:string,mcName:string,actName?:string,times?:number,compeletCall?:Function,target?:any){this._fileName = fileName;this.mcc.loadAndPlay(fileName,mcName,actName,times,compeletCall,target);}/**播放指定動畫 動作 */public playMovie(mcName: string, actName?: string, times?: number){if(!this._fileName)return;this.mcc.playMovie(mcName,actName,times);}/**跳到指定動作的第幾幀 播放次數 播放一輪回調 播放完成回調 ------- 當前動畫*/public gotoAndPlay(actName: string, frame: number = 0, times: number = -1, roundCall?: Function,finishCall?: Function, target?: any) {if(target){roundCall = roundCall && roundCall.bind(target);finishCall = finishCall && finishCall.bind(target);}this.mcc.gotoAndPlay(actName, frame, times, roundCall, finishCall);} } import { Component, JsonAsset, Layers, math, Node, Rect, Sprite, SpriteFrame, Texture2D, UITransform, Vec2, _decorator } from "cc"; import { ResourceManage } from "../ResourceManage";const { ccclass, property } = _decorator;/*** 幀動畫組件* * 讀取白鷺.json + .png資源格式* 利用幀刷新/計時器來刷新紋理* */ @ccclass('MovieClipComponent') export class MovieClipComponent extends Component {/**資源文件名 */private _fileName: string;/**幀圖數據 */private _resData: any;/**動畫數據 */private _mcData: any;/**紋理數據 */private _texture2d: Texture2D;/**渲染節點 */private _sprite: Sprite;private _spriteUI: UITransform;/**播放次數 -1為循環播放 */private _times: number;/**加載完成回調 */private _compeletCall: Function;/**播放一輪回調 */private _playRoundCall:Function;/**播放結束回調 */private _playFinishCall:Function;/**是否播放中 */public isPlay: boolean;private _interval;/**幀率 */private _frameRate: number;/**設置幀率 */public set frameRate(rate: number) {if (!rate || this._frameRate == rate) {return;}this._frameRate = rate;this.play();}/**幀率 */public get frameRate() {return this._frameRate || this._mcData[this.mcName].frameRate || 24;}/**首圖基準 */private _initPos: any;/**首圖基準 */private get initPos() {if (!this._initPos)this._initPos = this._mcData[this.mcName].frames[0];return this._initPos}/**當前動畫名 */private _mcName: string;/**當前動畫名 */public get mcName(): string {if (!this._mcName)this._mcName = this._mcData && Object.keys(this._mcData)[0];return this._mcName;}/**當前動畫名 */public set mcName(name: string) {let mcs = this._mcData && Object.keys(this._mcData);if (mcs.indexOf(name) == -1) {name = mcs[0];}this._mcName = name;}/**當前動作名 */private _actName: string;/**當前動作名 */public get actName() {if (this._actName == void 0) {let labels = this.actNames;this._actName = labels[0].name;}return this._actName;}/**設置當前動作名 */public set actName(name) {if (this._actName == name)return;let actNames = this.actNames;for (let data of actNames) {if (data.name == name) {this._actName = name;break;}}}/**當前動畫所有動作 */private _actNames: any[];/**當前動畫所有動作 */public get actNames() {if (!this._actNames)this._actNames = this._mcData[this.mcName].labels || [{ name: "", frame: 1, end: this._mcData[this.mcName].frames.length }];return this._actNames;}onLoad() {let node = new Node('mc');node.layer = Layers.Enum.UI_2D;node.parent = this.node;this._sprite = node.addComponent(Sprite);// this._sprite = this.node.getChildByName("Sprite").getComponent(Sprite);this._spriteUI = this._sprite.getComponent(UITransform);}/**加載資源 */public loadFile(fileName: string,compeletCall?:Function) {if (fileName == this._fileName)return;this._fileName = fileName;this._compeletCall = compeletCall;let thiz = this;ResourceManage.loadMcRes(`${fileName}`, JsonAsset, (res: JsonAsset) => {thiz.parseJson(res.json);thiz.checkCompelet();});ResourceManage.loadMcRes(`${fileName}/texture`, Texture2D, (res: Texture2D) => {if (res) {thiz._texture2d = res;thiz.checkCompelet();}});}/**解析配置 */private parseJson(data: any) {this._resData = data.res;this._mcData = data.mc;}/**檢查加載狀態 */private checkCompelet(): boolean {if (this._resData && this._mcData) {this.doLoadCompelet();return true;}return false;}/**加載完成 */private doLoadCompelet() {this._compeletCall && this._compeletCall()}/**加載并播放* @property fileName 文件名* @property mcName 動畫名* @property actName 動作名* @property times 播放次數 -1為循環* @property compeletCall 加載完成回調*/public loadAndPlay(fileName: string, mcName: string, actName: string, times: number = -1, compeletCall?: Function, target?: any) {let thiz = this;this.loadFile(fileName,() => {thiz.playMovie(mcName, actName, times);compeletCall && compeletCall.call(target);});}/**播放動畫 */public playMovie(mcName: string, actName?: string, times: number = -1) {this.mcName = mcName;this.gotoAndPlay(actName, 0, times);}/**跳到指定動作 指定幀 */public gotoAndPlay(actName: string, frame: number = 0, times: number = -1, roundCall?: Function, finishCall?:Function,) {this.curIndex = void 0;this.actName = actName;this._actData = void 0;this._times = times;this.curIndex = frame;this._times = times;this._playRoundCall = roundCall;this._playFinishCall = finishCall;this.play();}public play() {if (this.isPlay)return;let thiz = this;clearInterval(this._interval);this.isPlay = true;this._interval = setInterval(() => {thiz.doTimeUpdate();}, 1000.0 / this.frameRate);}/**停止播放 */public stop() {if (!this.isPlay)return;this.isPlay = false;this.curIndex = 0;clearInterval(this._interval);}public pause() {if (!this.isPlay)return;this.isPlay = false;clearInterval(this._interval);}/**重新播放 */public replay() {this.isPlay = false;this.curIndex = 0;this.play();}/**當前幀索引*/private _curIndex: number;private get curIndex() {if (!this._curIndex == void 0 || this._curIndex < this.actData.frame || this._curIndex > this.actData.end) {this._curIndex = this.actData.frame - 1;}return this._curIndex}private set curIndex(index) {if (index == void 0 || index < this.actData.frame - 1 || index > this.actData.end) {return;}this._curIndex = index;}/**當前幀數據 */private _actData: any;private get actData() {if (!this._actData) {let labels = this.actNames;for (let data of labels) {if (data.name == this.actName) {this._actData = data;break;}}}return this._actData;}/**當前幀數據 */private get curFrameData() {return this._mcData[this.mcName].frames[this.curIndex];}/**當前紋理數據 */private getCurResData(res: string) {return this._resData[res];}private doTimeUpdate() {if (!this.isPlay) {return;}let curFrame = this.curFrameData;if (!curFrame) {return;}let res = this.getCurResData(curFrame.res);let spriteFrame = new SpriteFrame();spriteFrame.texture = this._texture2d;this._sprite.spriteFrame = spriteFrame;this._sprite.spriteFrame.rect = new Rect(res.x, res.y, res.w, res.h);this._sprite.spriteFrame.offset = new Vec2(res.x, res.y);this._sprite.node.setPosition(curFrame.x - this.initPos.x, curFrame.y - this.initPos.y);this._spriteUI.width = res.w;this._spriteUI.height = res.h;this.curIndex++;if (this.curIndex >= this.actData.end) {if (this._times > 0) {this._times--;}this.curIndex = 0;this.doPlayRound();if (this._times == 0) {this.isPlay = false;this.doPlayFinished();}}}/**播放結束 */private doPlayFinished() {console.log('endddddddddddddddd');this._playFinishCall && this._playFinishCall();}/**播放一輪 */private doPlayRound() {console.log('rooooooooooound');this._playRoundCall && this._playRoundCall();}}總結
以上是生活随笔為你收集整理的cocos creator实现读取白鹭movieClip组件(尝试)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《平潭史话》之平潭轮渡
- 下一篇: 许晓斌_Maven实战(六)——Grad