FrameAnimation.ts 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. const { ccclass, property, executeInEditMode, playOnFocus } = cc._decorator;
  2. /**
  3. * 帧动画播放组件
  4. * ### 开放的接口;
  5. * #### play 播放
  6. * #### stop 停止播放
  7. * #### gotoAndPlay 跳转到某帧并播放
  8. * #### gotoAndStop 跳转到某帧并停止播放
  9. * #### isPlayEnd 是否播放结束
  10. * ### 开放的事件
  11. * #### completeTimes 单次播完完成事件
  12. * #### complete 全部次数完成事件
  13. * @author 薛鸿潇
  14. */
  15. @ccclass
  16. @executeInEditMode()
  17. @playOnFocus()
  18. export default class FrameAnimation extends cc.Component {
  19. @property({ displayName: '精灵纹理', type: cc.SpriteFrame })
  20. private images: cc.SpriteFrame[] = [];
  21. @property({ displayName: '每帧间隔' })
  22. private frameTime: number = 0.1;
  23. @property({ displayName: '播放次数' })
  24. private playTimes: number = 0;
  25. @property({ displayName: "是否倒播", tooltip: "勾选,倒着播放,不钩,顺序播放" })
  26. private reverse: boolean = false;
  27. @property({ displayName: '自动播放' })
  28. private autoPlayOnLoad: boolean = true;
  29. @property({ displayName: "自动销毁", tooltip: '播完自动销毁' })
  30. private autoDestroy: boolean = false;
  31. @property({ displayName: "每帧回调", type: cc.Component.EventHandler })
  32. onFrameCall: cc.Component.EventHandler = new cc.Component.EventHandler();
  33. @property({ displayName: "结束回调", type: cc.Component.EventHandler })
  34. onCompleteCall: cc.Component.EventHandler = new cc.Component.EventHandler();
  35. /** 编辑器预览 */
  36. private _edit_play: boolean = false;
  37. @property({ displayName: '编辑器预览' })
  38. get edit_play(): boolean {
  39. if (this._edit_play && !this.edit_playing) {
  40. this.edit_playing = true;
  41. this.play();
  42. }
  43. this.running = this._edit_play;
  44. return this._edit_play;
  45. }
  46. set edit_play(v: boolean) {
  47. this._edit_play = v;
  48. }
  49. /** 编辑器是否正在播放 */
  50. private edit_playing = false;
  51. /** 动画帧数量 */
  52. public frameNum: number = 0;
  53. /** 当前帧下标 */
  54. public frameIndex: number = 0;
  55. /** 下一帧下标 */
  56. public nextFrameIndex: number = 0;
  57. /** 是否允许播放 */
  58. public running: boolean = true;
  59. /** 精灵组件 */
  60. private comp_spr: cc.Sprite;
  61. /** 播放下一帧的倒计时 */
  62. private time: number = 0;
  63. /** 每完成一轮的回调 */
  64. public completeTimesCallback: Function;
  65. /** 全部播完回调 */
  66. public completeCallback: Function;
  67. /** 每帧回调 */
  68. public frameCallback: Function;
  69. /** 当前轮播次数 */
  70. private currentTimes: number = 0;
  71. onLoad() {
  72. this.comp_spr = this.getComponent(cc.Sprite);
  73. }
  74. start() {
  75. if (this.images.length != 0) {
  76. this.frameNum = this.images.length;
  77. }
  78. if (this.reverse) {
  79. this.frameIndex = this.frameNum - 1;
  80. this.nextFrameIndex = this.frameNum - 1;
  81. }
  82. if (CC_EDITOR) {
  83. this.running = this.edit_playing;
  84. } else {
  85. this.running = this.autoPlayOnLoad;
  86. }
  87. }
  88. update(dt) {
  89. if (!this.running) return;
  90. if (this.images.length == 0) return;
  91. if (this.playTimes != 0 && this.currentTimes > this.playTimes) {
  92. this.running = false;
  93. return;
  94. }
  95. this.time -= dt;
  96. if (this.time <= 0) {
  97. this.time = this.frameTime;
  98. if (!this.reverse) {
  99. this.frameIndex = this.nextFrameIndex % this.frameNum;
  100. this.nextFrameIndex = this.frameIndex + 1;
  101. } else {
  102. this.frameIndex = (this.nextFrameIndex + this.frameNum) % this.frameNum;
  103. this.nextFrameIndex = this.frameIndex - 1;
  104. }
  105. this.playing();
  106. if (this.frameIndex == 0) {
  107. this.playEnd();
  108. }
  109. }
  110. }
  111. /** 播放中 */
  112. private playing() {
  113. this.comp_spr.spriteFrame = this.images[this.frameIndex];
  114. if (this.comp_spr.spriteFrame) {
  115. var rect: cc.Rect = this.comp_spr.spriteFrame.getRect();
  116. this.node.width = rect.width;
  117. this.node.height = rect.height;
  118. }
  119. // 事件回调
  120. this.onFrameCall.emit([]);
  121. if (this.frameCallback != null) {
  122. this.frameCallback(this.frameIndex);
  123. }
  124. }
  125. /** 播放结束 */
  126. private playEnd() {
  127. this.currentTimes++;
  128. // 完成一次
  129. this.node.emit("completeTimes", this.currentTimes);
  130. if (this.completeTimesCallback != null) {
  131. this.completeTimesCallback(this.currentTimes);
  132. }
  133. // 全部完成
  134. if (this.playTimes != 0 && this.currentTimes > this.playTimes) {
  135. // 事件回调
  136. this.node.emit("complete");
  137. this.onCompleteCall.emit([]);
  138. if (this.completeCallback != null) {
  139. this.completeCallback();
  140. }
  141. if (this.autoDestroy && !CC_EDITOR) {
  142. this.node.destroy();
  143. }
  144. // this.edit_play = false;
  145. this._edit_play = false;
  146. this.edit_playing = false;
  147. }
  148. }
  149. /**
  150. * 开始播放
  151. * @param frameCallback
  152. * @param completeCallback
  153. */
  154. public play(frameCallback: Function = null, completeCallback: Function = null) {
  155. this.frameCallback = frameCallback;
  156. this.completeCallback = completeCallback;
  157. this.running = true;
  158. this.frameIndex = 0;
  159. this.currentTimes = 0;
  160. this.time = this.frameTime;
  161. if (this.images.length != 0) {
  162. this.frameNum = this.images.length;
  163. if (this.reverse) {
  164. this.frameIndex = this.frameNum - 1;
  165. this.nextFrameIndex = this.frameNum - 1;
  166. }
  167. }
  168. if (!this.comp_spr) {
  169. this.comp_spr = this.getComponent(cc.Sprite);
  170. }
  171. if (this.comp_spr)
  172. this.comp_spr.spriteFrame = this.images[0];
  173. if (this.comp_spr.spriteFrame) {
  174. var rect: cc.Rect = this.comp_spr.spriteFrame.getRect();
  175. this.node.width = rect.width;
  176. this.node.height = rect.height;
  177. }
  178. }
  179. /**
  180. * 跳转到某帧并开始播放
  181. * @param frameIndex 帧下标
  182. */
  183. public gotoAndPlay(frameIndex: number) {
  184. if (!this.comp_spr) {
  185. this.comp_spr = this.getComponent(cc.Sprite);
  186. }
  187. this.running = true;
  188. this.frameIndex = frameIndex;
  189. this.nextFrameIndex = frameIndex;
  190. this.currentTimes = 0;
  191. }
  192. /** 停止 */
  193. public stop() {
  194. this.running = false;
  195. }
  196. /**
  197. * 跳转到某帧并停止播放
  198. * @param frameIndex 帧下标
  199. */
  200. public gotoAndStop(frameIndex: number) {
  201. this.frameIndex = frameIndex;
  202. if (this.frameIndex < 0)
  203. this.frameIndex = 0;
  204. if (this.frameIndex > this.images.length - 1)
  205. this.frameIndex = this.images.length - 1;
  206. if (!this.comp_spr) {
  207. this.comp_spr = this.getComponent(cc.Sprite);
  208. }
  209. this.comp_spr.spriteFrame = this.images[this.frameIndex];
  210. if (this.comp_spr.spriteFrame) {
  211. var rect: cc.Rect = this.comp_spr.spriteFrame.getRect();
  212. this.node.width = rect.width;
  213. this.node.height = rect.height;
  214. }
  215. this.running = false;
  216. }
  217. /**
  218. * 是否播放结束
  219. * @returns
  220. */
  221. public isPlayEnd(): boolean {
  222. return this.frameIndex == this.frameNum;
  223. }
  224. }