教程目录  
一 前言
二 实际效果
三 实现原理
四 自定义位图影片剪辑类
五 切图工具类
六 使用示例
七 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 整张的序列图,使用egret.Texture的initData进行切图,并将切下的texture保存到数组中。
3 零碎的序列图,使用RES.getRes(),将texture保存到数组中。
3 每一帧切换纹理 BitmapMovie.texture =  下一张texture,这样就连成了一个动画。
 

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

 
class BitmapMovie extends eui.Image{
    /**纹理缓存列表 */
    private textureCaches:Array<egret.Texture> = [];
    /**总帧数 */
    public totalFrame:number;
    /**当前播放帧数 索引从1开始 */
    public curFrame:number = 0;
    /**计时器 */
    private timer:egret.Timer;
    /**播放延迟 默认30帧*/
    private _delay:number = 1000/30;
    /**循环次数 */
    private loop:number = 0;

    public constructor() {
        super();
    }
    /**
     * 使用整张序列图创建动画
     * @param srcTexture 源纹理
     * @param maxRow 有几行
     * @param maxCol 有几列
     * @param startPos 从第几张位置开始切(包含该位置 索引从0开始)
     * @param pieceNum 切多少张
     * @param width tile宽度
     * @param height tile高度
     */
    public initByOnePic(srcTexture:egret.Texture, maxRow:number, maxCol:number, startPos:number, pieceNum:number, width:number, height:number){
        this.textureCaches = CutImgTool.cutTile(srcTexture, maxRow, maxCol, startPos, pieceNum, width, height);
        if(this.textureCaches && this.textureCaches.length > 0){
            this.texture = this.textureCaches[0];
            this.curFrame = 0;
            this.totalFrame = this.textureCaches.length;
        }
    }
    /**
     * 使用多张序列图创建动画  命名格式: "boom0_png"
     * @param imgName 图片名称  "boom"
     * @param imgType 图片后缀 "png" ("jpg")
     * @param pieceNum 有多少张
     */
    public initByTile(imgName:string, imgType:string, pieceNum:number){
        this.textureCaches.length = 0;
        for(var i=0;i<pieceNum;i++){
            if(RES.hasRes(imgName + i + "_" + imgType)){
                this.textureCaches[i] = RES.getRes(imgName + i + "_" + imgType);
            }else{
                this.textureCaches[i] = null;
                Log.error("BitmapMovie >> 序列图不存在:", imgName + i + "_" + imgType);
            }
        }
        this.texture = this.textureCaches[0];
        this.curFrame = 0;
        this.totalFrame = this.textureCaches.length;
    }
    /**
     * 播放
     * @param loop 循环次数  负整数无限循环
     */
    public play(loop:number = 0){
        this.loop = loop;
        this.startTimer();
    }
    /**
     * 停止播放
     */
    public stop(){
        this.stopTimer();
    }
    /**
     * 跳转播放
     * @param frame 播放的起始帧 (索引从1开始)
     * @param loop 循环次数
     */
    public gotoAndPlay(frame:number, loop:number = 0){
        if(frame <= this.totalFrame){
            this.loop = loop;
            this.curFrame = frame;
            this.texture = this.textureCaches[frame-1];
            this.startTimer();
        }else{
            Log.error("BitmapMovie >> frame超出范围");
        }
    }
    
    /**
     * 跳转并停止
     * @param frame 帧 (索引从1开始)
     */
    public gotoAndStop(frame:number){
        if(frame <= this.totalFrame){
            this.stopTimer();
            this.curFrame = frame;
            this.texture = this.textureCaches[frame-1];
        }else{
            Log.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.textureCaches[this.curFrame-1];
        }else{
            this.loop --;
            this.dispatchEvent(new egret.Event(egret.Event.LOOP_COMPLETE));
            if(this.loop == 0){
                this.stopTimer();
                this.dispatchEvent(new egret.Event(egret.Event.COMPLETE));
            }else{
                this.curFrame = 1;
                this.texture = this.textureCaches[this.curFrame-1];
            } 
        }
    }
    
    /**停止计时 */
    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;
    }

    /**销毁 */
    public destroy(){
        //移除舞台
        this.parent && this.parent.removeChild(this);
        //停止并删除计时器
        this.stop();
        this.timer = null;
        //删除纹理
        this.textureCaches.length = 0;
    }
}

  


五 切图工具类

    /**
     * 切图
     * @param srcTexture 源图
     * @param maxRow 有几行
     * @param maxCol 有几列
     * @param startPos 从第几张位置开始切(包含该位置 索引从0开始)
     * @param pieceNum 切多少张
     * @param width tile宽度
     * @param height tile高度
     * @returns 返回切割的纹理列表
     */
    public static cutTile(srcTexture:egret.Texture,maxRow:number,maxCol:number,startPos:number, pieceNum:number,width:number,height:number){
        var rect:egret.Rectangle = new egret.Rectangle();  //切割矩形区域
        var cutCount:number = 0;                           //当前已切割多少块
        var textureCaches = [];                            //保存切割的纹理
        for(var i=0;i<maxRow;i++){
            for(var j=0;j<maxCol;j++){
                //>=起始位置,并且<=切割数量
                if((i*maxCol + j >= startPos) && cutCount <= pieceNum){
                    let texture:egret.Texture = new egret.Texture();
                    texture.disposeBitmapData = false;
                    texture.$bitmapData = srcTexture.$bitmapData;
                    texture.$initData(j*width, i*height, width, height, 0, 0, width, height, srcTexture.textureWidth, srcTexture.textureHeight);
                    textureCaches.push(texture);
                    cutCount++;
                }else{
                    return textureCaches;
                }
            }
        }
        return textureCaches;
    }
}

  


六 使用示例

 
let mc:BitmapMovie = new BitmapMovie();
 mc.initByOnePic(RES.getRes("login_edge_jpg"),1,10,0,10,48,48);
 mc.x = i*50;
mc.y = 200;
 mc.play(-1);
this.addChild(mc);

  

 
 


七 Demo下载

https://files-cdn.cnblogs.com/files/gamedaybyday/Egret3.2.6_MovieBitmapExample.7z

posted on 2018-06-24 11:20  gamedaybyday  阅读(2629)  评论(0编辑  收藏  举报