AS3 图片的帧动画实现

貌似现在学习AS3的人越来越少了,空闲的时候写了一个根据位图或者位图数据,并且切割变成帧动画的类。
写的时候没有考虑位图加载以后的缓存,可以在此基础上缓存位图数据,如果下次再有相同路径的话,可以直接调用位图数据的那个函数,这样效率可以高一点。

这个类基本用到了AS3里面的各种基础知识,包括load加载,消息监听,位图数据的处理,函数的回调,TIME的使用等,欢迎大家吐槽。

/** 
 * 单张多帧动画 
 * @author JiExsprite 
 * @time 2014/8/12 
 */  
</pre><pre name="code" class="java">package 
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.TimerEvent;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	import flash.net.URLRequest;
	import flash.utils.Timer;


	
	
	public class SinFrameAni extends Sprite
	{
		/**加载器*/
		private var m_Loader:Loader;
		
		private var m_nRow:int;
		private var m_nCol:int;
		
		/**是否下载完成*/
		private var m_bLoadOver:Boolean = false;
		
		/**是否等待播放*/
		private var m_bWaitPlayAni:Boolean = false;
		
		/**存放所有动画帧*/
		private var m_szFrame:Vector.<Bitmap>;
		
		/**播放控制时间*/
		private var m_PlayTime:Timer;
		
		/**每帧间隔*/
		private var m_nInterval:int = 100;
		
		
		/**开始帧*/
		private var m_nBeginFrame:int = 0;
		
		/**结束帧*/
		private var m_nEndFrame:int = -1;
		
		/**最大帧*/
		private var m_nMaxFrame:int = -1;
		
		/**当前帧*/
		private var m_nCurFrame:int = 0;
		
		/**当前的动画*/
		private var m_CurAni:Bitmap = null;
		
		/**是否播放1次*/
		private var m_bPlayOnce:Boolean = false;
		
		/**回调函数*/
		private var m_CallBackFun:Function;
		/**回调函数参数*/
		private var m_CallParams:Array = [];
		
		/**单张多帧动画类*/
		public function SinFrameAni()
		{
			super();
			
			m_Loader = new Loader();
			
			m_szFrame = new Vector.<Bitmap>;
			m_PlayTime = new Timer(m_nInterval);
		}
		/**通过图片路径创建
		 * filename 图片路径
		 * row 行
		 * col 列
		 * */
		public function SetFile(filename:String = "",row:int=0,col:int=0):void
		{
			if(filename=="")
				return;
			
			m_nRow = row;
			m_nCol = col;	
			if(m_nRow==0)
				m_nRow = 1;
			if(m_nCol==0)
				m_nCol = 1;
					
	
			m_bLoadOver = false;
			
			m_Loader.load(new URLRequest(filename));
			m_Loader.contentLoaderInfo.addEventListener(Event.COMPLETE,OnDownImgOk);
			m_Loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,OnDownImgErr);
		}
		
		/**
		 *  通过bitmapdata创建
		 * 	srcdata 源位图数据
		 * 	row	行
		 * 	col	列
		 * */	
		public function SetBitMapData(srcdata:BitmapData = null,row:int=0,col:int=0):void
		{	
			if(srcdata==null)
				return;
			m_nRow = row;
			m_nCol = col;
			if(m_nRow==0)
				m_nRow = 1;
			if(m_nCol==0)
				m_nCol = 1;
			
			m_bLoadOver = false;
			inciseBmp(srcdata);			
		}
		
		/**播放一次动画
		 * beginIdx 开始帧
		 * endIdx 结束帧
		 * intervalTimes 每帧间隔毫秒数
		 * callback 回调函数
		 * callParams 回调函数参数
		 * */
		public function PlayAndStop(beginIdx:int = 0,endIdx:int = -1,intervalTimes:int = 100,callback:Function=null,callParams:Array=null):void
		{
			m_CallBackFun = callback;
			m_CallParams = callParams;
			
			m_nInterval = intervalTimes;
			m_bPlayOnce = true;	
			
			m_nCurFrame = beginIdx;
			m_nEndFrame = endIdx;
			
			if(m_szFrame.length==0)
				return;
			if(!m_bLoadOver)
				return;
			
			
			if(m_nCurFrame<0||m_nCurFrame>m_nMaxFrame - 1)
				m_nCurFrame = 0;
			
			if(m_nEndFrame<0||m_nEndFrame>m_nMaxFrame - 1)
				m_nEndFrame = m_nMaxFrame - 1;
	
			if(m_CurAni!=null)
				m_CurAni.visible = false;

			m_PlayTime.stop();
			m_PlayTime.removeEventListener(TimerEvent.TIMER,OnTime);
			
			m_CurAni = m_szFrame[m_nCurFrame];
			m_CurAni.visible = true;
			if(m_nCurFrame==m_nEndFrame)
			{
				CallBackFun();
				return;
			}
		
			
			m_PlayTime.delay = intervalTimes;
			m_PlayTime.reset();
			m_PlayTime.start();		
			m_PlayTime.addEventListener(TimerEvent.TIMER,OnTime);

		}
		/**无限循环播放
		 * intervalTimes 每帧间隔毫秒数
		 * */
		public function PlayAni(intervalTimes:int = 100):void
		{				
			m_bWaitPlayAni = true;
			m_nInterval = intervalTimes;
			if(!m_bLoadOver)
				return;
			if(m_szFrame.length==0)
				return;
			
			m_bPlayOnce = false;
			
			m_PlayTime.stop();
			m_PlayTime.removeEventListener(TimerEvent.TIMER,OnTime);
			
			m_nCurFrame = 0;
			m_nEndFrame = m_nMaxFrame - 1;
			
			if(m_CurAni!=null)
				m_CurAni.visible = false;

			m_PlayTime.repeatCount = 0;
			m_PlayTime.delay = m_nInterval;
			m_PlayTime.reset();
			m_PlayTime.start();
			m_PlayTime.addEventListener(TimerEvent.TIMER,OnTime);
			m_CurAni = m_szFrame[m_nCurFrame];
			m_CurAni.visible = true;
		}
		/**停止播放*/
		public function StopAni():void
		{	
			m_PlayTime.stop();
			m_PlayTime.removeEventListener(TimerEvent.TIMER,OnTime);
			
			m_bWaitPlayAni = false;
			m_bPlayOnce = false;
		}
		
		/**设置位置*/
		public function SetPos(xpos:int,ypos:int):void
		{	
			this.x = xpos;
			this.y = ypos;
		}
		
		/**帧切换*/
		private function OnTime(evt:TimerEvent):void
		{
			if(m_nBeginFrame==m_nEndFrame&&m_nBeginFrame==0)
				return;
			
			//trace("当前帧:"+m_nCurFrame);
			m_CurAni.visible = false;
			m_nCurFrame++;
			if(m_nCurFrame>m_nEndFrame)
			{
				if(m_bPlayOnce)
				{
					m_CurAni.visible = true;
					CallBackFun();
					StopAni();
					return;
				}			
				m_nCurFrame = m_nBeginFrame;
			}			
			m_CurAni = m_szFrame[m_nCurFrame];
			m_CurAni.visible = true;
		}
		
		/**加载完毕*/
		private function OnDownImgOk(evt:Event):void
		{
			inciseBmp(evt.target.content.bitmapData);
		}
		
		/**输出加载错误*/
		private function OnDownImgErr(evt:Event):void
		{
			var str:String = "IOERROR : Please check your image path and try again!It is said that this relatively high-end !";
			trace(str);
		}
		
		/**切割图片*/
		private function inciseBmp(srcdata:BitmapData):void
		{
			m_szFrame.length  = 0;
			
			var bigdata:BitmapData = srcdata;
			var width:int = srcdata.width;
			var height:int = srcdata.height;
			var frameW:int = width/m_nCol;
			var frameH:int = height/m_nRow;
			
			var tempdata:BitmapData;
			
			var szRect:Vector.<Rectangle> = new Vector.<Rectangle>;
			
			
			for(var i:int=0;i<m_nRow;i++)
			{
				for(var j:int=0;j<m_nCol;j++)
				{
					var rectangle:Rectangle = new Rectangle();				
					rectangle = new Rectangle();
					rectangle.x = j * frameW;
					rectangle.y = i * frameH;
					rectangle.width = frameW;
					rectangle.height = frameH;
					//trace("矩形大小:"+rectangle);
					szRect.push(rectangle);
				}
			}
			var len:int = szRect.length;
			for(i=0;i<len;i++)
			{
				rectangle = szRect[i];
				var newBMP:Bitmap = new Bitmap();
				tempdata = drawBmp(bigdata,rectangle.x,rectangle.y,rectangle.width,rectangle.height);
				newBMP.bitmapData = tempdata;
				newBMP.visible = false;
				m_szFrame.push(newBMP);
				this.addChild(newBMP);
			}
			m_nMaxFrame = m_szFrame.length;
			
			m_bLoadOver = true;
			
			if(m_bWaitPlayAni)
				PlayAni(m_nInterval);
			else
				PlayAndStop(m_nCurFrame,m_nEndFrame,m_nInterval,m_CallBackFun,m_CallParams);
		}
		
		/**返回一张图片的某个矩形区域BitmapData*/
		private function drawBmp(sourceBmp:BitmapData, x:Number, y:Number, w:Number, h:Number):BitmapData 
		{
			var newBmp:BitmapData = new BitmapData(w, h, true, 0xff);			
			newBmp.draw(sourceBmp, new Matrix(1, 0, 0, 1, -x, -y));
			return newBmp;
		}
		
		/**得到当前动画的帧总数,使用时需要-1*/
		public function get maxframe():int
		{
			return m_nMaxFrame;
		}
		/**得到当前帧*/
		public function get curframe():int
		{
			return m_nCurFrame;
		}
		/**得到当前BitmapData*/
		public function get curbmpdata():BitmapData
		{
			return m_CurAni.bitmapData;
		}
		
		/**CallBack函数执行*/
		private function CallBackFun():void
		{
			if(m_CallBackFun!=null)
				m_CallBackFun(m_CallParams);
			m_CallParams = [];
			m_CallBackFun = null;
		}
		
		/**清空动画*/
		public function Clear():void
		{
			StopAni();
			if(m_CurAni!=null)
			{
				m_CurAni.bitmapData = null;
				m_CurAni = null;
			}
			m_Loader.close();
			m_Loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,OnDownImgOk);
			m_Loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR,OnDownImgErr);
			
			var bmp:Bitmap;
			for each(bmp in m_szFrame)
			{
				this.removeChild(bmp);
				bmp.bitmapData = null;
				bmp = null;
			}
			m_szFrame.length = 0;
		}
	}
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值