让位图动起来!

这个主要是把一张绘制有几个图像,并且有连续关系的位图利用BitmapData类的copyPixels实例方法截取位图上面的部分图像,然后利用ENTER_FRAME事件或者Timer事件制作动画!

在这个方法里面有好几个重要参数

copyPixels(sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point, alphaBitmapData:BitmapData = null, alphaPoint:Point = null, mergeAlpha:Boolean = false)
sourceBitmapData:要制作动画的图片源
sourceRect:这个参数是一个Rectangle,它表示在源位图上开始切割的坐标,宽,高
destPoint:这个表示把切割好的位图作为Bitmap类的源的时候,左上角所在的坐标(我知道这样解析很难明白,但是我想不到其他的解析方式了)

其他参数请看帮助,因为我也没有去具体了解过,也很少用到!

要想你的位图动起来,还需要在制作位图的时候注意每一个图像之间要有一定的间隔,而且最好都在一个固定大小的矩形内。

好了现在把整个类的代码贴出来~!

因为我想用在项目中,所以也写了它的一个父类和一个支持多帧的类

所以工有三个类(DisplaySuper,BmpMovieClip,MultiFrameBmpMovieClip)

DisplaySuper类的代码(很简单):

 1 package kongfu 
 2 {
 3     import flash.display.DisplayObject;
 4     import flash.display.DisplayObjectContainer;
 5     import flash.display.Sprite;
 6     /**
 7      * ...
 8      * @author kongfuzhou
 9 
10      */
11     public class DisplaySuper extends Sprite
12     {
13         public var parentDpl:DisplayObjectContainer;
14         
15         public function DisplaySuper(self:DisplaySuper) 
16         {
17             if (self!=this) 
18             {
19                 throw new Error("abstract class can't new a instance!");
20             }
21         }
22         /**
23          * 设置显示对象的坐标
24          * @param    xp
25          * @param    yp
26          * @param    basePro 居于某个宽高居中显示  {w:500,h:500}
27          * @example 
28          */
29         public function setPosOrCenter(xp:Number=0,yp:Number=0,basePro:Object=null):void 
30         {
31             if (basePro && basePro.w && basePro.h) 
32             {
33                 this.x = (basePro.w - this.width) / 2;
34                 this.y = (basePro.h - this.height) / 2;
35             }else
36             {
37                 this.x = xp;
38                 this.y = yp;
39             }
40             
41         }
42         protected function removeMySelf():void 
43         {
44             if (this.parent) 
45             {
46                 this.parent.removeChild(this);
47             }
48         }
49         
50     }
51 
52 }

制作动画的主要类BmpMovieClip:

package kongfu
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.DisplayObject;
    import flash.display.DisplayObjectContainer;
    import flash.events.Event;
    import flash.events.TimerEvent;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.utils.Timer;
    
    /**
     * 实现将连续位图转换成动画的类
     * @author kongfuzhou
     */
    public class BmpMovieClip extends DisplaySuper
    {
        /**
         * 各种属性
         *
         * @example var obj:Object = {
         * startXY:{startX:Number,startY:Number},
           sizeDiff: { xDiff:106, yDiff:119 }, xDiff:左右两张图的x坐标间隔,yDiff:上下两张图的y坐标间隔
           sizePos: { w:80, h:60},
           control: { len:12, col:8, row:2 }
           };
        
         */
        private var vars:Object;
        /**
         * 最终显示的位图
         */
        private var bmp_mc:Bitmap;
        /**
         * 源位图数据
         */
        public var bmpdResouce:BitmapData;
        /**
         * 最终位图数据
         */
        private var bmpMcData:BitmapData;
        private var index:int = 0;
        private var startPoint:Point;
        private var rectDataArr:Array;
        private var frameRate:int;
        public var firstIsEnd:Boolean = false;
        private var frameTimer:Timer;
        private var transParent:Boolean = true;
        private var color:uint = 0x00ffffff;
        private var resBmpdObj:Object;
        private var boolObj:Object;
        public var isStop:Boolean = true;
        public var oneTimesFunc:Function;
        
        /**
         *  构造函数
         * 
         * @param    vars 调用动画的各种属性
         * @param    resBmpdObj {bmpdRes:BitmapData,bmpdCs:Class}
         * @param    parentDpl 父层
         * @param    boolObj 该对像的属性是boolean类型的{opentFrameEvent:Boolean=true,useTimer:Boolean=false,autoPlay:Boolean=false}
         * @param    frameRate 使用timer来进行切割位图做动画时的虚拟帧频
         * @param    startPoint  destPoint参数
         * @param    rectDataArr  BitmapData实例的copyPixels函数里面的Rectangle参数的参数(当你想每一个图片的宽、高、切割的X和Y坐标是自己随意定义的时传该参数)
         */
        public function BmpMovieClip(vars:Object, resBmpdObj:Object, parentDpl:DisplayObjectContainer, boolObj:Object = null, frameRate:int = 0, startPoint:Point = null, rectDataArr:Array = null)
        {
            super(this);
            this.boolObj = boolObj;
            this.boolObj == null ? this.boolObj = {opentFrameEvent: true, useTimer: false, autoPlay: true} : "";
            this.boolObj.opentFrameEvent == null ? this.boolObj.opentFrameEvent = true : "";
            this.boolObj.useTimer == null ? this.boolObj.useTimer = false : "";
            this.boolObj.autoPlay == null ? this.boolObj.autoPlay = true : "";
            this.resBmpdObj = resBmpdObj;
            this.frameRate = frameRate;
            this.rectDataArr = rectDataArr;
            this.startPoint = startPoint;
            this.startPoint == null ? this.startPoint = new Point(0, 0) : "";
            this.parentDpl = parentDpl;
            this.vars = vars;
            init();
        }
        
        private function init():void
        {
            if (this.vars.control == null || this.vars.startXY == null || this.vars.sizeDiff == null || this.vars.sizePos == null)
            {
                throw new Error("vars's property must four or more!");
            }
            this.rectDataArr ? this.vars.control.len = this.rectDataArr.length : "";
            
            this.bmp_mc = new Bitmap();
            this.vars.transParent ? this.transParent = this.vars.transParent : "";
            this.vars.color ? this.color = this.vars.color : "";
            this.bmpMcData = new BitmapData(this.vars.sizePos.w, this.vars.sizePos.h, this.transParent, this.color);
            
            if (this.resBmpdObj.bmpdRes)
            {
                this.bmpdResouce = this.resBmpdObj.bmpdRes;
            }
            else if (this.resBmpdObj.bmpdCs)
            {
                this.bmpdResouce = new this.resBmpdObj.bmpdCs();
            }
            if (this.resBmpdObj.bmpdRes == null && this.resBmpdObj.bmpdCs == null)
            {
                throw new Error("resBmpdObj must be not null!");
            }
            if (this.bmpdResouce)
            {
                this.bmp_mc.bitmapData = this.bmpMcData;
                this.addChild(this.bmp_mc);
                this.parentDpl ? this.parentDpl.addChild(this) : "";
                if (this.boolObj.useTimer == true)
                {
                    addTimerEvent();
                }
            }
            if (this.boolObj.autoPlay == true)
            {
                play();
            }
            else
            {
                letItMove();
            }
        
        }
        
        private function addTimerEvent():void
        {
            this.boolObj.opentFrameEvent = false;
            this.frameRate == 0 ? this.frameRate = 30 : "";
            this.frameTimer = new Timer(int(1000 / this.frameRate));
            this.frameTimer.addEventListener(TimerEvent.TIMER, timerHandler);
        }
        
        /**
         * 播放
         */
        public function play():void
        {
            if (this.boolObj.useTimer == true)
            {
                if (this.frameTimer.hasEventListener(TimerEvent.TIMER))
                {
                    this.frameTimer.start();
                }
                else
                {
                    addTimerEvent();
                    this.frameTimer.start();
                }
                
            }
            else if (this.boolObj.opentFrameEvent == true)
            {
                this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
            }
        }
        
        /**
         * 停止在第一个画面
         */
        public function stop():void
        {
            this.removeEvent();
            this.index = 0;
            letItMove();
        }
        
        private function timerHandler(e:TimerEvent):void
        {
            letItMove();
        }
        
        private function onEnterFrame(e:Event):void
        {
            letItMove();
        }
        
        /**
         * 截取bitmapdata上面的图像生成动画
         */
        public function letItMove():void
        {
            if (this.index < this.vars.control.len)
            {
                if (this.rectDataArr)
                {
                    var obj:Object = this.rectDataArr[this.index];
                    if (obj==null || obj.xp==null || obj.yp==null || obj.w==null || obj.h==null) 
                    {
                        throw new Error(" bitmapData.copyPixels() args of Rectangle got a unable args!");
                    }
                    this.bmpMcData.copyPixels(this.bmpdResouce, new Rectangle(obj.xp, obj.yp, obj.w, obj.h), new Point((this.width - obj.w) / 2, 0))
                }
                else
                {
                    var xp:Number = this.vars.startXY.startX + (this.index % this.vars.control.col) * this.vars.sizeDiff.xDiff;
                    var yp:Number = this.vars.startXY.startY + int(this.index / this.vars.control.col) * this.vars.sizeDiff.yDiff;
                    this.bmpMcData.copyPixels(this.bmpdResouce, new Rectangle(xp, yp, this.vars.sizePos.w, this.vars.sizePos.h), this.startPoint);
                }
                this.index++;
            }
            else if (this.oneTimesFunc != null)
            {
                this.firstIsEnd = true;
                this.oneTimesFunc();
            }
            else
            {
                this.index = 0;
            }
        }
        
        /**
         * 把自己从显示列表中删除并且删除事件侦听器
         */
        public function remove():void
        {
            this.removeMySelf();
            removeEvent();
        }
        
        /**
         * 删除事件侦听器
         */
        public function removeEvent():void
        {
            if (this.boolObj.opentFrameEvent == true)
            {
                this.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
            }
            if (this.boolObj.useTimer == true)
            {
                this.frameTimer.removeEventListener(TimerEvent.TIMER, timerHandler);
            }
        }
    
    }

}

制作多帧动画的类MultiFrameBmpMovieClip:

  1 package kongfu
  2 {
  3     import flash.display.DisplayObjectContainer;
  4     import flash.events.Event;
  5     import flash.utils.Dictionary;
  6     
  7     /**
  8      * 多帧位图mc
  9      * ...
 10      * @author kongfuzhou
 11     
 12      */
 13     public class MultiFrameBmpMovieClip extends DisplaySuper
 14     {
 15         private var framesObj:Object = new Object();
 16         private var framesArr:Array;
 17         public var curFrameBmp_mc:BmpMovieClip;
 18         public var totalFrames:int;
 19         public var curFrameLabel:String;
 20         public var curFrame:int;
 21         private var framesDict:Dictionary = new Dictionary();
 22         private var frameLabelsDict:Dictionary = new Dictionary();
 23         private var curIndex:int = 1;
 24         
 25         /**
 26          * @param    framesObj 每一帧的
 27          * @param    parentDlp 父层
 28          */
 29         public function MultiFrameBmpMovieClip(framesArr:Array, parentDlp:DisplayObjectContainer = null)
 30         {
 31             super(this);
 32             this.parentDpl = parentDlp;
 33             this.framesArr = framesArr;
 34             init();
 35         
 36         }
 37         
 38         private function init():void
 39         {
 40             if (this.framesArr)
 41             {
 42                 var index:int = 0;
 43                 for (var i in this.framesArr)
 44                 {
 45                     index++;
 46                     if (i is Number)
 47                     {
 48                         var str:String = "frame" + (i + 1);
 49                         this.framesObj[str] = this.framesArr[i];
 50                         this.frameLabelsDict[this.framesObj[str]] = str;
 51                     }
 52                     else if (i is String)
 53                     {
 54                         this.framesObj[i] = this.framesArr[i];
 55                         this.frameLabelsDict[this.framesObj[i]] = i;
 56                     }
 57                     this.framesDict[this.framesArr[i]] = index;
 58                     if (index == 1)
 59                     {
 60                         setCurFrame(this.framesArr[i]);
 61                     }
 62                     
 63                 }
 64                 setTotalFrame();
 65                 gotoPlay();
 66             }
 67             else
 68             {
 69                 this.framesArr = new Array();
 70             }
 71             if (this.parentDpl)
 72             {
 73                 this.parentDpl.addChild(this);
 74             }
 75         
 76         }
 77         
 78         /**
 79          * 播放某帧
 80          * @param    frame 帧名字符串,数字也可以直接输入
 81          */
 82         public function gotoStop(frame:String):void
 83         {
 84             var fm:Number = Number(frame);
 85             if (isNaN(fm))
 86             {
 87                 //不是数字
 88                 if (this.framesObj[frame])
 89                 {
 90                     setShow(this.framesObj[frame]);
 91                 }
 92             }
 93             else
 94             {
 95                 //是数字
 96                 if (this.framesArr[fm - 1])
 97                 {
 98                     setShow(this.framesArr[fm - 1]);
 99                 }
100             }
101         }
102         
103         /**
104          * 播放所有帧
105          */
106         public function gotoPlay():void
107         {
108             //trace("gotoPlay: curIndex = "+this.curIndex+" totalFrames = "+this.totalFrames);
109             if (this.curIndex < this.totalFrames)
110             {
111                 (this.framesArr[this.curIndex - 1] as BmpMovieClip).oneTimesFunc = playAll;
112                 (this.framesArr[this.curIndex - 1] as BmpMovieClip).play();
113             }
114         
115         }
116         
117         /**
118          * 控制播放所有帧
119          */
120         private function playAll():void
121         {
122             if (this.curIndex > this.totalFrames)
123             {
124                 for each (var item:BmpMovieClip in this.framesObj)
125                 {
126                     item.removeEvent();
127                 }
128                 return;
129             }
130             if (this.framesArr[this.curIndex - 1])
131             {
132                 if ((this.framesArr[this.curIndex - 1] as BmpMovieClip).firstIsEnd)
133                 {
134                     this.curIndex++;
135                 }
136                 else
137                 {
138                     if (this.numChildren > 1)
139                     {
140                         while (this.numChildren > 0)
141                         {
142                             this.removeChildAt(0);
143                         }
144                         this.addChild(this.framesArr[this.curIndex - 1]);
145                         setCurFrame(this.framesArr[this.curIndex - 1]);
146                     }
147                     else if (this.numChildren == 1)
148                     {
149                         var child:BmpMovieClip = (this.getChildAt(0) as BmpMovieClip);
150                         if (child != this.framesArr[this.curIndex - 1])
151                         {
152                             this.removeChildAt(0);
153                             this.addChild(this.framesArr[this.curIndex - 1]);
154                             setCurFrame(this.framesArr[this.curIndex - 1]);
155                         }
156                         else
157                         {
158                             (this.framesArr[this.curIndex - 1] as BmpMovieClip).oneTimesFunc = playAll;
159                             (this.framesArr[this.curIndex - 1] as BmpMovieClip).play();
160                         }
161                     }
162                     else
163                     {
164                         this.addChild(this.framesArr[this.curIndex - 1]);
165                         setCurFrame(this.framesArr[this.curIndex - 1]);
166                     }
167                 }
168             }
169         }
170         
171         private function setCurFrame(bmp_mc:BmpMovieClip):void
172         {
173             if (this.framesDict[bmp_mc])
174             {
175                 this.curFrame = this.framesDict[bmp_mc];
176             }
177             if (this.frameLabelsDict[bmp_mc])
178             {
179                 this.curFrameLabel = this.frameLabelsDict[bmp_mc];
180             }
181             this.curFrameBmp_mc = bmp_mc;
182             this.curFrameBmp_mc.play();
183             this.addChild(this.curFrameBmp_mc);
184         
185         }
186         
187         /**
188          * 增加帧
189          * @param    frame 帧标签
190          * @param    addBmpMc 该帧的动画
191          */
192         public function addFrame(frame:String, addBmpMc:BmpMovieClip):void
193         {
194             var fm:Number = Number(frame);
195             if (isNaN(fm))
196             {
197                 //不是数字
198                 if (this.framesObj[frame])
199                 {
200                     throw new Error("this framlabel is exit!");
201                 }
202                 else
203                 {
204                     this.framesObj[frame] = addBmpMc;
205                     this.frameLabelsDict[addBmpMc] = frame;
206                 }
207                 
208             }
209             else
210             {
211                 //是数字
212                 if (this.framesArr[fm - 1] || (fm - 1) < 0)
213                 {
214                     throw new Error("this framlabel is not exit!");
215                 }
216                 else
217                 {
218                     var str:String = "frame" + (this.framesArr.length + 1);
219                     this.framesObj[str] = addBmpMc;
220                     this.frameLabelsDict[addBmpMc] = str;
221                 }
222                 
223             }
224             this.framesArr.push(addBmpMc);
225             this.framesDict[addBmpMc] = this.framesArr.length;
226             this.setTotalFrame();
227         
228         }
229         
230         /**
231          * 删除帧
232          * @param    frame
233          */
234         public function removeFrame(frame:String):void
235         {
236             var fm:Number = Number(frame);
237             if (isNaN(fm))
238             {
239                 //不是数字                
240                 for (var i in this.framesArr)
241                 {
242                     if (this.framesArr[i] == this.framesObj[frame])
243                     {
244                         this.framesArr.splice(i, 1);
245                         break;
246                     }
247                 }
248                 (this.framesObj[frame] as BmpMovieClip).remove();
249                 this.framesObj[frame] = null;
250             }
251             else
252             {
253                 //是数字
254                 var j:int = int(frame);
255                 if (this.framesArr[j - 1])
256                 {
257                     for (var frameName in this.framesObj)
258                     {
259                         if (this.framesObj[frameName] == this.framesArr[j - 1])
260                         {
261                             this.framesObj[frameName] = null;
262                             break;
263                         }
264                     }
265                     (this.framesArr[j - 1] as BmpMovieClip).remove();
266                     this.framesArr.splice(j - 1, 1);
267                     
268                 }
269                 
270             }
271             this.setTotalFrame();
272             setFrameDict();
273         
274         }
275         
276         /**
277          * 显示某帧内容
278          * @param    showBmp_mc 该帧上的动画
279          */
280         private function setShow(showBmp_mc:BmpMovieClip):void
281         {
282             while (this.numChildren > 0)
283             {
284                 this.removeChildAt(0);
285             }
286             setCurFrame(showBmp_mc);
287         }
288         
289         /**
290          * 设置总帧数
291          */
292         private function setTotalFrame():void
293         {
294             this.totalFrames = this.framesArr.length;
295         }
296         
297         /**
298          * 设置每个对象对应的帧
299          */
300         private function setFrameDict():void
301         {
302             var index:int = 0;
303             for (var i in this.framesObj)
304             {
305                 index++;
306                 this.framesDict[this.framesObj[i]] = index;
307                 this.frameLabelsDict[this.framesObj[i]] = i;
308             }
309         
310         }
311         
312         public function remove():void
313         {
314             this.removeMySelf();
315         }
316     
317     }
318 
319 }

一个使用实例:

 1 var obj0:Object = {
 2                 transParent:true,
 3                 color:0x00ffffff,
 4                 startXY:{startX:20,startY:37}, //在原始图片中的那个位置开始切割
 5                 sizeDiff: { xDiff:106, yDiff:119 }, //xDiff:左右两张图的x坐标间隔,yDiff:上下两张图的y坐标间隔
 6                 sizePos: { w:80, h:60}, 
 7                 control: { len:12, col:8, row:2 }
 8                 };            
 9             var offBmp_mc:BmpMovieClip=new BmpMovieClip(obj0,{bmpdCs:Global.bmpdCsObj.offBmpdCS},Global.dplLayer,{autoPlay:true}); //动画流畅 Global.dplLayer
10             offBmp_mc.setPosOrCenter(50,50);

使用实例用到的图片(来源于网络):

可以到我的微盘下载完整的测试程序和图片素材!

地址: http://vdisk.weibo.com/s/jH3tR

 

 

posted @ 2012-12-03 22:30  kongfu  阅读(230)  评论(0编辑  收藏  举报