|
|
@@ -0,0 +1,245 @@
|
|
|
+const { ccclass, property, executeInEditMode, playOnFocus } = cc._decorator;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 帧动画播放组件
|
|
|
+ * ### 开放的接口;
|
|
|
+ * #### play 播放
|
|
|
+ * #### stop 停止播放
|
|
|
+ * #### gotoAndPlay 跳转到某帧并播放
|
|
|
+ * #### gotoAndStop 跳转到某帧并停止播放
|
|
|
+ * #### isPlayEnd 是否播放结束
|
|
|
+ * @author 薛鸿潇
|
|
|
+ */
|
|
|
+@ccclass
|
|
|
+@executeInEditMode()
|
|
|
+@playOnFocus()
|
|
|
+export default class FrameAnimation extends cc.Component {
|
|
|
+
|
|
|
+ @property({ displayName: '精灵纹理', type: cc.SpriteFrame }) private images: cc.SpriteFrame[] = [];
|
|
|
+ @property({ displayName: '每帧间隔' }) private frameTime: number = 0.1;
|
|
|
+ @property({ displayName: '播放次数' }) private playTimes: number = 0;
|
|
|
+ @property({ displayName: "是否倒播", tooltip: "勾选,倒着播放,不钩,顺序播放" }) private reverse: boolean = false;
|
|
|
+ @property({ displayName: '自动播放' }) private autoPlayOnLoad: boolean = true;
|
|
|
+ @property({ displayName: "自动销毁", tooltip: '播完自动销毁' }) private autoDestroy: boolean = false;
|
|
|
+ @property({ displayName: "每帧回调", type: cc.Component.EventHandler }) onFrameCall: cc.Component.EventHandler = new cc.Component.EventHandler();
|
|
|
+ @property({ displayName: "结束回调", type: cc.Component.EventHandler }) onCompleteCall: cc.Component.EventHandler = new cc.Component.EventHandler();
|
|
|
+ /** 编辑器预览 bug待修复*/
|
|
|
+ // private _edit_play: boolean = false;
|
|
|
+ // @property({ displayName: '编辑器预览' })
|
|
|
+ // get edit_play(): boolean {
|
|
|
+ // if (this._edit_play && this.frameNum) {
|
|
|
+ // this.play();
|
|
|
+ // this._edit_play = false;
|
|
|
+ // cc.log(this._edit_play)
|
|
|
+ // }
|
|
|
+ // this.running = this._edit_play;
|
|
|
+ // return this._edit_play;
|
|
|
+ // }
|
|
|
+ // set edit_play(v: boolean) {
|
|
|
+ // this._edit_play = v;
|
|
|
+ // }
|
|
|
+
|
|
|
+ /** 动画帧数量 */
|
|
|
+ public frameNum: number = 0;
|
|
|
+ /** 当前帧下标 */
|
|
|
+ public frameIndex: number = 0;
|
|
|
+ /** 下一帧下标 */
|
|
|
+ public nextFrameIndex: number = 0;
|
|
|
+
|
|
|
+ public running: boolean = true;
|
|
|
+
|
|
|
+ private m_render: cc.Sprite;
|
|
|
+
|
|
|
+ private time: number = 0;
|
|
|
+
|
|
|
+ public completeTimesCallback: Function;
|
|
|
+
|
|
|
+ public completeCallback: Function;
|
|
|
+
|
|
|
+ public frameCallback: Function;
|
|
|
+
|
|
|
+ private currentTimes: number = 0;
|
|
|
+
|
|
|
+ onLoad() {
|
|
|
+ this.m_render = this.getComponent(cc.Sprite);
|
|
|
+ }
|
|
|
+
|
|
|
+ start() {
|
|
|
+ if (this.images.length != 0) {
|
|
|
+ this.frameNum = this.images.length;
|
|
|
+ }
|
|
|
+ this.running = this.autoPlayOnLoad;
|
|
|
+
|
|
|
+ if (this.reverse) {
|
|
|
+ this.frameIndex = this.frameNum - 1;
|
|
|
+ this.nextFrameIndex = this.frameNum - 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 更新动画帧
|
|
|
+ * @param dt
|
|
|
+ */
|
|
|
+ update(dt) {
|
|
|
+
|
|
|
+ if (!this.running) return;
|
|
|
+ if (this.images.length == 0) return;
|
|
|
+ if (this.playTimes != 0 && this.currentTimes > this.playTimes) {
|
|
|
+ this.running = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.time -= dt;
|
|
|
+ if (this.time <= 0) {
|
|
|
+ this.time = this.frameTime;
|
|
|
+ if (!this.reverse) {
|
|
|
+ this.frameIndex = this.nextFrameIndex % this.frameNum;
|
|
|
+ this.nextFrameIndex = this.frameIndex + 1;
|
|
|
+ } else {
|
|
|
+ this.frameIndex = (this.nextFrameIndex + this.frameNum) % this.frameNum;
|
|
|
+ this.nextFrameIndex = this.frameIndex - 1;
|
|
|
+ }
|
|
|
+ this.playing();
|
|
|
+ if (this.frameIndex == 0) {
|
|
|
+ this.playEnd();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /** 播放中 */
|
|
|
+ private playing() {
|
|
|
+ this.m_render.spriteFrame = this.images[this.frameIndex];
|
|
|
+
|
|
|
+ if (this.m_render.spriteFrame) {
|
|
|
+ var rect: cc.Rect = this.m_render.spriteFrame.getRect();
|
|
|
+ this.node.width = rect.width;
|
|
|
+ this.node.height = rect.height;
|
|
|
+ }
|
|
|
+ // 事件回调
|
|
|
+ this.onFrameCall.emit([]);
|
|
|
+ if (this.frameCallback != null) {
|
|
|
+ this.frameCallback(this.frameIndex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /** 播放结束 */
|
|
|
+ private playEnd() {
|
|
|
+ this.currentTimes++;
|
|
|
+
|
|
|
+ // 完成一次
|
|
|
+ this.node.emit("completeTimes", this.currentTimes);
|
|
|
+ if (this.completeTimesCallback != null) {
|
|
|
+ this.completeTimesCallback(this.currentTimes);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 全部完成
|
|
|
+ if (this.playTimes != 0 && this.currentTimes > this.playTimes) {
|
|
|
+ // 事件回调
|
|
|
+ this.node.emit("complete");
|
|
|
+ this.onCompleteCall.emit([]);
|
|
|
+ if (this.completeCallback != null) {
|
|
|
+ this.completeCallback();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.autoDestroy && !CC_EDITOR) {
|
|
|
+ this.node.destroy();
|
|
|
+ }
|
|
|
+ // this._edit_play = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 开始播放
|
|
|
+ * @param frameCallback
|
|
|
+ * @param completeCallback
|
|
|
+ */
|
|
|
+ public play(frameCallback: Function = null, completeCallback: Function = null) {
|
|
|
+
|
|
|
+ this.frameCallback = frameCallback;
|
|
|
+ this.completeCallback = completeCallback;
|
|
|
+
|
|
|
+ this.running = true;
|
|
|
+ this.frameIndex = 0;
|
|
|
+ this.currentTimes = 0;
|
|
|
+
|
|
|
+ this.time = this.frameTime;
|
|
|
+
|
|
|
+ if (this.images.length != 0) {
|
|
|
+ this.frameNum = this.images.length;
|
|
|
+
|
|
|
+ if (this.reverse) {
|
|
|
+ this.frameIndex = this.frameNum - 1;
|
|
|
+ this.nextFrameIndex = this.frameNum - 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this.m_render) {
|
|
|
+ this.m_render = this.getComponent(cc.Sprite);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.m_render)
|
|
|
+ this.m_render.spriteFrame = this.images[0];
|
|
|
+
|
|
|
+
|
|
|
+ if (this.m_render.spriteFrame) {
|
|
|
+ var rect: cc.Rect = this.m_render.spriteFrame.getRect();
|
|
|
+ this.node.width = rect.width;
|
|
|
+ this.node.height = rect.height;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 跳转到某帧并开始播放
|
|
|
+ * @param frameIndex 帧下标
|
|
|
+ */
|
|
|
+ public gotoAndPlay(frameIndex: number) {
|
|
|
+ if (!this.m_render) {
|
|
|
+ this.m_render = this.getComponent(cc.Sprite);
|
|
|
+ }
|
|
|
+
|
|
|
+ this.running = true;
|
|
|
+ this.frameIndex = frameIndex;
|
|
|
+ this.nextFrameIndex = frameIndex;
|
|
|
+ this.currentTimes = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 停止 */
|
|
|
+ public stop() {
|
|
|
+ this.running = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 跳转到某帧并停止播放
|
|
|
+ * @param frameIndex 帧下标
|
|
|
+ */
|
|
|
+ public gotoAndStop(frameIndex: number) {
|
|
|
+ this.frameIndex = frameIndex;
|
|
|
+
|
|
|
+ if (this.frameIndex < 0)
|
|
|
+ this.frameIndex = 0;
|
|
|
+
|
|
|
+ if (this.frameIndex > this.images.length - 1)
|
|
|
+ this.frameIndex = this.images.length - 1;
|
|
|
+
|
|
|
+ if (!this.m_render) {
|
|
|
+ this.m_render = this.getComponent(cc.Sprite);
|
|
|
+ }
|
|
|
+
|
|
|
+ this.m_render.spriteFrame = this.images[this.frameIndex];
|
|
|
+
|
|
|
+ if (this.m_render.spriteFrame) {
|
|
|
+ var rect: cc.Rect = this.m_render.spriteFrame.getRect();
|
|
|
+ this.node.width = rect.width;
|
|
|
+ this.node.height = rect.height;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.running = false;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 是否播放结束
|
|
|
+ * @returns
|
|
|
+ */
|
|
|
+ public isPlayEnd(): boolean {
|
|
|
+ return this.frameIndex == this.frameNum;
|
|
|
+ }
|
|
|
+}
|