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


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

  • 相关阅读:
    处理流之转换流
    处理流之缓冲流 buffered
    java学习笔记 字符流Reader与Writer
    java学习笔记 OutputStream与InputStream
    java学习笔记 Map接口
    java 学习笔记 Iterator 迭代器
    java学习笔记 genenic 范形
    应急响应介绍
    安全之红蓝对抗简介
    密码学基础下篇
  • 原文地址:https://www.cnblogs.com/gamedaybyday/p/9219954.html
Copyright © 2020-2023  润新知