【咸鱼教程】自定义序列图工具类(制作序列图动画)

教程目录  
一 前言
二 实际效果
三 实现原理
四 自定义位图影片剪辑类
五 切图工具类
六 使用示例
七 Demo源码下载


一 前言

一般我们做动画用TextureMerger,用gif或swf,导出一个json和png纹理合集,用MovieClip类来实现。
现在我们使用自定义的BitmapMovie类来制作序列图动画,直接用代码制作,节省TextureMerger工具的操作步骤。

参考:史上最高效、易用的位图动画类开源了,还不快进来!?
         《ActionScript3.0 基础动画教程》第一章 基本动画概念

使用封装好的工具类,只需要简单几句就能使用。

[C#]  纯文本查看 复制代码
?
1
2
3
4
var mc:BitmapMovie = new BitmapMovie();
mc.initByTile( "dragon" , "jpg" ,18);
this .addChild(mc);
mc.play();



二 实际效果


多张序列图
 

             


一整张序列图

      

 


三 实现原理
1 自定义BtimapMovie类继承自eui.Image。(不继承egret.Bitmap,因为没有eui的特性,比如约束适配...)
2 整张的序列图,使用RenderTexture类的drawToTexture进行切图,并将切下的texture保存到数组中。
3 零碎的序列图,使用RES.getRes(),将texture保存到数组中。
3 每一帧切换纹理 BitmapMovie.texture =  下一张texture,这样就连成了一个动画。
 

四 自定义位图影片剪辑类
1 整张序列图,使用initByBitmap进行初始化,对整张Bitmap进行裁剪,变成单张的texture,并保存到数组中。
2 多张序列图,使用initByTile进行初始化,将单张的texture保存到数组中
3 使用egret.Timer进行计时,轮流切换BitmapMovie.texture,达到动画的效果。 (这样每一个剪辑就有一个timer,各位可自行优化)
4 提供了egret.MoveClip的play, stop, gotoAndPlay, gotoAndStop等,其他可自行扩展....

[C#]  纯文本查看 复制代码
?
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/**
  * 自定义位图影片剪辑
  * @author chenkai
  * [url=home.php?mod=space&uid=81950]@since[/url] 2017/4/17
  */
class BitmapMovie extends eui.Image{
         /**纹理列表 */
         private textureList:Array<egret.Texture> = [];
         /**总帧数 */
         public totalFrame:number;
         /**当前播放帧数 第一帧从1开始 */
         public curFrame:number = 0;
         /**计时器 */
         private timer:egret.Timer;
         /**播放延迟 */
         private _delay:number = 1000/60;
         /**循环次数 */
         private loop:number = 0;
 
         public constructor() {
                 super();
         }
 
         /**
          * 使用整张序列图初始化
          * @srcBm 源图
          * @maxRow 有几行
          * @maxCol 有几列
          * @startPos 从第几张位置开始切(包含该位置)
          * @pieceNum 切多少张
          * @width tile宽度
          * @height tile高度
          */
         public initByBitmap(srcBm:egret.Bitmap, maxRow:number, maxCol:number, startPos:number, pieceNum:number, width:number, height:number){
                 this .textureList = CutImgTool.cutTile(srcBm, maxRow, maxCol, startPos, pieceNum, width, height);
                 if ( this .textureList && this .textureList.length > 0){
                         this .texture = this .textureList[0];
                         this .curFrame = 0;
                         this .totalFrame = this .textureList.length;
                 }
         }
 
         /**
          * 使用零散的序列图初始化
          * @imgName 图片名称  命名格式: "boom0_png","boom1_png",...
          * @imgType 图片后缀 "png"或者"jpg"
          * @pieceNum 有多少张
          */
         public initByTile(imgName: string , imgType: string , pieceNum:number){
                 this .textureList.length = 0;
                 for (var i=0;i<pieceNum;i++){
                         this .textureList = RES.getRes(imgName + i + "_" + imgType);
                 }
                 if ( this .textureList.length > 0){
                         this .texture = this .textureList[0];
                         this .curFrame = 0;
                         this .totalFrame = this .textureList.length;
                 }
         }
 
         /**
          * 播放
          * @loop 循环次数
          */
         public play(loop:number = 0){
                 this .loop = loop;
                 this .startTimer();
         }
 
         /**
          * 停止播放
          */
         public stop(){
                 this .stopTimer();
         }
 
         /**
          * 跳转播放
          * @frame 播放的起始帧
          * @loop 循环次数
          */
         public gotoAndPlay(frame:number, loop:number = 0){
                 if (frame <= this .totalFrame){
                         this .loop = loop;
                         this .curFrame = frame;
                         this .texture = this .textureList[frame-1];
                         this .startTimer();
                 } else {
                         console.error( "BitmapMovie >> frame超出范围" );
                 }
         }
         
         /**
          * 跳转停止
          * @frame 停止的帧
          */
         public gotoAndStop(frame:number){
                 if (frame <= this .totalFrame){
                         this .stopTimer();
                         this .curFrame = frame;
                         this .texture = this .textureList[frame-1];
                 } else {
                         console.error( "BitmapMovie >> frame超出范围" );
                 }
         }
 
         //启动计时器
         private startTimer(){
                 this .timer || ( this .timer = new egret.Timer( this .delay));
                 this .timer.addEventListener(egret.TimerEvent.TIMER, this .onTimerHandler, this );
                 this .timer.reset();
                 this .timer.start();
         }
 
         //计时处理
         private onTimerHandler(){
                 this .curFrame ++;
                 if ( this .curFrame <= this .totalFrame){
                         this .texture = this .textureList[ this .curFrame-1];
                 } else {
                         this .loop --;
                         this .dispatchEvent( new egret.Event(egret.Event.LOOP_COMPLETE));
                         if ( this .loop > 0){
                                 this .curFrame = 1;
                                 this .texture = this .textureList[ this .curFrame-1];
                         } else {
                                 this .stopTimer();
                                 this .dispatchEvent( new egret.Event(egret.Event.COMPLETE));
                         }
                 }
         }
 
         //停止计时
         private stopTimer(){
                 if ( this .timer){
                         this .timer.removeEventListener(egret.TimerEvent.TIMER, this .onTimerHandler, this );
                         this .timer.stop();
                 }
         }
 
         //延迟
         public set delay(value:number){
                 this ._delay = value;
                 if ( this .timer){
                         this .timer.delay = value;
                 }
         }
 
         //延迟
         public get delay(){
                 return this ._delay;
         }
}




五 切图工具类
1 主要利用RenderTexture的drawToTexture进行切图。


[C#]  纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
  * 切图工具类
  * @author chenkai
  * @since 2017/4/17
  */
class CutImgTool {
         
         /**
          * 切图
          * @srcBm 源图
          * @maxRow 有几行
          * @maxCol 有几列
          * @startPos 从第几张位置开始切(包含该位置)
          * @pieceNum 切多少张
          * @width tile宽度
          * @height tile高度
          * @returns 返回切割的纹理列表
          */
         public static cutTile(srcBm:egret.Bitmap,maxRow:number,maxCol:number,startPos:number, pieceNum:number,width:number,height:number){
                 var rect:egret.Rectangle = new egret.Rectangle();  //切割矩形区域
                 var cutCount:number = 0;                           //当前已切割多少块
                 var textureList = [];                              //保存切割的纹理
                 for (var i=0;i<maxRow;i++){
                         for (var j=0;j<maxCol;j++){
                                 //>=起始位置,并且<=切割数量
                                 if ((i*maxCol + j >= startPos) && cutCount <= pieceNum){
                                         var renderTexture:egret.RenderTexture = new egret.RenderTexture();
                                         rect.x = j*width;
                                         rect.y = i*height;
                                         rect.width = width;
                                         rect.height = height;
                                         if (renderTexture.drawToTexture(srcBm, rect) == false ){
                                                 console.error( "CutImgTool >> cut error" );
                                                 return null ;
                                         } else {
                                                 textureList.push(renderTexture);
                                                 cutCount ++;
                                         }
                                 } else {
                                         return textureList;
                                 }
                         }
                 }
                 return textureList;
         }
 
}




六 使用示例

[C#]  纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
  * 主页场景
  * @author chenkai
  * @since 2017/4/17
  */
class HomeScene extends eui.Component{
         public constructor() {
                 super();
                 this .skinName = "HomeSceneSkin" ;
         }
 
         public childrenCreated(){
                 //创建自定义影片剪辑
                 var boom:BitmapMovie = new BitmapMovie();
 
                 //使用整张序列图初始化
                 var bm:egret.Bitmap = new egret.Bitmap(RES.getRes( "boom_png" ));
                 boom.initByBitmap(bm,4,5,0,18,192,192);
 
                 //使用零散的多张序列图初始化
                 //boom.initByTile("dragon", "jpg",18);
 
                 //设置位置
                 boom.x = ( this .stage.stageWidth - boom.width)/2;
                 boom.y = ( this .stage.stageHeight - boom.height)/2;
                 boom.delay = 1000/20;
                 this .addChild(boom);
 
                 //监听播放完成
                 boom.addEventListener(egret.Event.COMPLETE, this .onComplete, this );
                 boom.addEventListener(egret.Event.LOOP_COMPLETE, this .onLoopComplete, this );
 
                 //开始播放
                 boom.play(999);
         }
 
         //所有播放完成
         private onComplete(){
                 console.log( "HomeScene >> Boom 播放完成" );
         }
 
         //播放完一次
         private onLoopComplete(){
                 console.log( "HomeScene >> Boom 播放一次完成" );
         }
}



Demo源码下载

猜你喜欢

转载自www.cnblogs.com/gamedaybyday/p/9219954.html