Cocos Creator封装自己的帧动画组件播放动画
前言
在Cocos Creator游戏开发的过程中我们进行需要使用动画效果,虽然可以通过动画编辑器编辑动画效果,但是有时候用户想更灵活的控制帧动画的效果,就需要自己封装帧动画组件。
一、帧动画播放组件
1: creator播放帧动画需要通过动画编辑器去制作;
2: 为了方便控制和使用加入帧动画代码播放组件;
3: 属性设置:
sprite_frames: 帧动画所用到的所有的帧;
duration: 每帧的时间间隔;
loop: 是否循环播放;
play_onload: 是否加载组件的时候播放;
4: 接口设置:
play_once(end_func); // 播放结束后的回掉函数;
play_loop(); // 循环播放;
二、帧动画播放原理
1: 对的时间播放显示对的图片:
假设以三帧动画为例,时间间隔就是duration,

三、自己封装帧动画组件
1. `const {ccclass, property} = cc._decorator;` 3. `@ccclass` 4. `export default class FrameAnim extends cc.Component {` 5. ` @property({type: [cc.SpriteFrame], tooltip:"帧动画图片数组"})` 6. `spriteFrames : Array<cc.SpriteFrame> = [];` 8. ` @property({tooltip:"每一帧的时长"})` 9. `duration : number = 0.1;` 11. ` @property({tooltip:"是否循环播放"})` 12. ` loop : boolean = false;` 14. ` @property({tooltip:"是否在加载的时候就开始播放"})` 15. `playOnload : boolean = false;` 17. ` // 播放完后的回调函数`18. ` private endFunc : any = null;` 19. ` // 动画播放需要的精灵组件`20. ` private sprite : cc.Sprite;` 21. ` // 动画播放的状态,正在播放还是停止`22. ` private isPlaying : boolean = false;` 23. ` // 记录已经播放的时间`24. `private playTime : number = 0;` 26. ` onLoad () {` 27. ` // 获取当前动画组件挂载的节点上的Sprite组件,如果没有则添加`28. ` this.sprite = this.node.getComponent(cc.Sprite);` 29. ` if(!this.sprite){` 30. ` this.sprite = this.node.addComponent(cc.Sprite);` 31. ` }` 33. ` // 判断是否是预加载播放`34. ` if(this.playOnload){` 35. ` if(this.loop){` 36. ` this.playLoop(); // 循环播放`37. ` }else{` 38. ` this.playOnce(null); // 只播放一次`39. ` }` 40. ` }` 41. `}` 43. ` public playLoop() : void {` 44. ` this.initFrame(true, null);` 45. `} ` 47. ` public playOnce(endf : any) : void {` 48. ` this.initFrame(false, endf);` 49. `}` 51. ` private initFrame(loop:boolean, endf : any) : void{` 52. ` if(this.spriteFrames.length <= 0){` 53. ` return;` 54. ` }` 55. ` this.isPlaying = true;` 56. ` this.playTime = 0;` 57. ` this.sprite.spriteFrame = this.spriteFrames[0];` 58. ` this.loop = loop;` 59. ` this.endFunc = endf;` 60. `}` 62. `start () {` 64. `}` 66. ` update (dt) {` 67. ` if(!this.isPlaying){` 68. ` return;` 69. ` }` 71. ` // 累计时间,通过时间计算应该取哪一张图片展示`72. ` this.playTime += dt;` 73. ` let index : number = Math.floor(this.playTime / this.duration);` 75. ` if(this.loop){ // 循环播放`76. ` if(index >= this.spriteFrames.length){` 77. ` index -= this.spriteFrames.length;` 78. ` this.playTime -= (this.duration * this.spriteFrames.length);` 79. ` }` 80. ` this.sprite.spriteFrame = this.spriteFrames[index];` 81. ` }else{ // 播放一次`82. ` if(index >= this.spriteFrames.length){` 83. ` this.isPlaying = false;` 84. ` // 如果有回调函数的处理,则调用回调函数`85. ` if(this.endFunc){` 86. ` this.endFunc();` 87. ` }` 88. ` }else{` 89. ` this.sprite.spriteFrame = this.spriteFrames[index];` 90. ` }` 91. ` }` 92. ` }` 93. `}`
四、测试封装的帧动画组件

勾选PlayOnLoad和去掉的区别,勾选Loop和去掉的区别,可以发现预加载和循环播放。如何在代码中控制?
新建GameMgr.ts挂载到Canvas节点上****。
1. `import FrameAnim from "./FrameAnim";` 3. `const {ccclass, property} = cc._decorator;` 4. `@ccclass` 5. `export default class GameMgr extends cc.Component {` 7. ` @property({type: [FrameAnim], tooltip:"帧动画数组"})` 8. ` anim : Array<FrameAnim> = [];` 9. `// onLoad () {}`11. ` endPlay(){` 12. ` console.log("动画播放完毕!!");` 13. ` }` 14. ` start () {` 15. ` //this.anim[0].playOnce(this.endPlay);`16. ` //this.anim[1].playOnce(this.endPlay);`17. ` //this.anim[0].playOnce(null);`18. ` //this.anim[1].playOnce(null);`19. ` //this.anim[0].playLoop();`20. ` //this.anim[1].playLoop();`21. ` if(this.anim.length > 1){` 22. ` this.anim[1].duration = 0.5;` 23. ` this.anim[1].playOnce(this.endPlay);` 24. ` }` 25. ` if(this.anim.length > 0){` 26. ` this.anim[0].playLoop();` 27. ` }` 28. ` }` 29. `}`

