检测碰撞工具类(两个类各有特点 可以结合使用)

 
package 
{
	import flash.display.BitmapData;
	import flash.display.BlendMode;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	public class HitTest
	{
		//========复杂(精确)碰撞测试
		public static function complexHitTestObject( target1:DisplayObject, target2:DisplayObject,  accurracy:Number = 1 ):Boolean
		{
			return complexIntersectionRectangle(target1,target2,accurracy).width != 0;
		}
		//========返回两目标对象重叠的区域矩形
		public static function intersectionRectangle( target1:DisplayObject, target2:DisplayObject ):Rectangle
		{
			//如果目标对象不存在,或者简单碰撞测试为否,那么就不可能重叠
			if (! target1.root || ! target2.root || ! target1.hitTestObject(target2))
			{
				return new Rectangle;
			}
			//获取目标的边界信息Bounds
			var bounds1:Rectangle = target1.getBounds(target1.root);
			var bounds2:Rectangle = target2.getBounds(target2.root);
			// Determine test area boundaries.
			var intersection:Rectangle = new Rectangle();
			intersection.x = Math.max(bounds1.x,bounds2.x);
			intersection.y = Math.max(bounds1.y,bounds2.y);
			intersection.width      = Math.min( ( bounds1.x + bounds1.width ) - intersection.x, ( bounds2.x + bounds2.width ) - intersection.x );
			intersection.height = Math.min( ( bounds1.y + bounds1.height ) - intersection.y, ( bounds2.y + bounds2.height ) - intersection.y );

			return intersection;
		}
		//========返回复杂重叠的区域矩形
		public static function complexIntersectionRectangle( target1:DisplayObject, target2:DisplayObject, accurracy:Number = 1 ):Rectangle
		{
			if (accurracy <= 0)
			{
				throw new Error("ArgumentError: Error #5001: Invalid value for accurracy",5001);
			}
			//如果简单碰撞为否,那么他们没有重叠
			if (! target1.hitTestObject(target2))
			{
				return new Rectangle;
			}

			var hitRectangle:Rectangle = intersectionRectangle(target1,target2);

			if (hitRectangle.width * accurracy < 1 || hitRectangle.height * accurracy < 1)
			{
				return new Rectangle;
			}

			var bitmapData:BitmapData = new BitmapData(hitRectangle.width * accurracy,hitRectangle.height * accurracy,false,0x000000);

			//绘制第一个目标
			bitmapData.draw( target1, HitTest.getDrawMatrix( target1, hitRectangle, accurracy ), new ColorTransform( 1, 1, 1, 1, 255, -255, -255, 255 ) );
			//绘制第二个目标
			bitmapData.draw( target2, HitTest.getDrawMatrix( target2, hitRectangle, accurracy ), new ColorTransform( 1, 1, 1, 1, 255, 255, 255, 255 ), BlendMode.DIFFERENCE );


			//确定位图图像中完全包含指定颜色的所有像素的矩形区域,以找到重叠区域
			var intersection:Rectangle = bitmapData.getColorBoundsRect(0xFFFFFFFF,0xFF00FFFF);

			bitmapData.dispose();
			//释放bitmapData对象的内存,返回width,height为-1;
			if (accurracy != 1)
			{
				intersection.x /=  accurracy;
				intersection.y /=  accurracy;
				intersection.width /=  accurracy;
				intersection.height /=  accurracy;
			}
			intersection.x +=  hitRectangle.x;
			intersection.y +=  hitRectangle.y;
			
			return intersection;
		}

		protected static function getDrawMatrix( target:DisplayObject, hitRectangle:Rectangle, accurracy:Number ):Matrix
		{//返回一个转换矩阵
			//accurracy精确度
			var localToGlobal:Point;
			var matrix:Matrix;
			var rootConcatenatedMatrix:Matrix = target.root.transform.concatenatedMatrix;
			localToGlobal = target.localToGlobal( new Point( ) );
			matrix = target.transform.concatenatedMatrix;
			matrix.tx = localToGlobal.x - hitRectangle.x;
			matrix.ty = localToGlobal.y - hitRectangle.y;

			matrix.a = matrix.a / rootConcatenatedMatrix.a;
			matrix.d = matrix.d / rootConcatenatedMatrix.d;
			if (accurracy != 1)
			{
				matrix.scale( accurracy, accurracy );
			}
			return matrix;
		}

	}

}
package 
{
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.display.BitmapData;
	import flash.display.Bitmap;
	import flash.events.MouseEvent;
	import flash.geom.*;
	import flash.filters.GlowFilter;

	public class HitTest extends MovieClip
	{
		public function HitTest()
		{
			
		}
		
		public function hitTestShape(mc1:Sprite,mc2:Sprite):Boolean
		{
			var rect1:Rectangle = mc1.getBounds(this);//这里要用rect的宽度才合适了
			//trace(this);
			var bmd1:BitmapData = new BitmapData(rect1.width,rect1.height,true,0);//返回的矩阵也是变化的
			var matrix1:Matrix = mc1.transform.matrix;
			matrix1.tx = mc1.x - rect1.x;
			matrix1.ty = mc1.y - rect1.y;
			bmd1.draw(mc1);
			var bit1:Bitmap = new Bitmap(bmd1);
			var rect2:Rectangle = mc2.getBounds(this);
			var bmd2:BitmapData = new BitmapData(rect2.width,rect2.height,true,0);
			var matrix2:Matrix = mc2.transform.matrix;
			matrix2.tx = mc2.x - rect2.x;
			matrix2.ty = mc2.y - rect2.y;
			bmd2.draw(mc2,matrix2);
			var bit2:Bitmap = new Bitmap(bmd2);
			if (bmd1.hitTest(new Point(rect1.x,rect1.y),10,bmd2,new Point(rect2.x,rect2.y),10))//可以改变透明度达到不同的检测效果
			{
				trace("碰撞了");
				mc2.filters = [new GlowFilter  ];
				return true;
			}
			else
			{
				mc2.filters = [];
			}
			return false;
		}

	}
}



package 
{
	import flash.display.*;
	import flash.geom.*;
	public class HitTest
	{
		//按照像素级别来检测碰撞
		private static function _hitTest(shape1:DisplayObject,shape2:DisplayObject):Boolean
		{
			//取得shape1和shape2的坐标
			var p1x:Number = shape1.getRect(shape1).x;
			var p1y:Number = shape1.getRect(shape1).y;
			var p2x:Number = shape2.getRect(shape2).x;
			var p2y:Number = shape2.getRect(shape2).y;
			//取得shape1和shape2的大小
			var p1w:Number = shape1.width;
			var p1h:Number = shape1.height;
			var p2w:Number = shape2.width;
			var p2h:Number = shape2.height;
			//当长宽小于1时取1
			p1w < 1 ? 1:p1w;
			p1h < 1 ? 1:p1h;
			p2w < 1 ? 1:p2w;
			p2h < 1 ? 1:p2h;
			//根据shape1和shape2的大小新建两个透明的BitmapData对象
			//Matrix(a,b,c,d,tx,ty);
			//tx:Number (default = 0) — 沿 x 轴向右平移(移动)的像素数。    
			//ty:Number (default = 0) — 沿 y 轴向下平移(移动)的像素数。 
			var BmpData1:BitmapData = new BitmapData(p1w,p1h,true,0x00000000);
			var BmpData2:BitmapData = new BitmapData(p2w,p2h,true,0x00000000);
			BmpData1.draw(shape1,new Matrix(1,0,0,1, -  p1x, -  p1y));
			BmpData2.draw(shape2,new Matrix(1,0,0,1, -  p2x, -  p2y));
			//取得shape1和shape2相对于舞台的坐标;
			//localToGlobal(point:Point):Point 将 point 对象从显示对象的(本地)坐标转换为舞台(全局)坐标。
			var gp1:Point = shape1.localToGlobal(new Point(p1x,p1y));
			var gp2:Point = shape2.localToGlobal(new Point(p2x,p2y));
			//使用BitmapData类的hitTest方法进行碰撞检测(可以根据情况设置透明度0X05)
			var re:Boolean = BmpData1.hitTest(gp1,0x05,BmpData2,gp2,0x05);
			//dispose():void 释放用来存储 BitmapData 对象的内存。
			BmpData1.dispose();
			BmpData2.dispose();
			return re;
		}
		//按照矩形区域检测碰撞
		public static function hitTestRect(shape1:DisplayObject,shape2:DisplayObject):Boolean
		{
			if (shape1.hitTestObject(shape2))
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		//按照点和形状来检测碰撞
		public static function hiTestPoint(point:Point,shape:DisplayObject):Boolean
		{
			if (shape.hitTestPoint(point.x,point.y,true))
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		//按形状检测
		public static function hitTestShape(shape1:DisplayObject,shape2:DisplayObject):Boolean
		{
			var hit:Boolean = false;

			if (shape1.hitTestObject(shape2))
			{
				//先用hitTestObject检测是否碰撞如果被检测的物体大小小于20那么用hitTestObject来检测直接返回true否则用像素级别检测
				if (shape2.width < 20 && shape2.height < 20)
				{
					hit = true;
				}
				else
				{
					if (HitTest._hitTest(shape1,shape2))
					{
						hit = true;
					}
				}
			}
			return hit;
		}

	}
}
/*先注意是BitmapData对象的方法hitTest(),精确到像素碰撞,
常用于判断比较大的不规则的对象碰撞,它有5个参数(前3个参数必须,后2个参数可选)依次如下(括号中是参数的类型):
firstPoint(Point):BitmapData对象的左上点的位置坐标
firstAlpha(uint):BitmapData对象中视为不透明的最高alpha通道值
secondObject(Object):碰撞的区域,可以是BitmapData对象、RectAngle对象、Point对象等。
secondBitmapDataPoint(Point):只有当secondObject参数为BitmapData对象时,才能使用该参数,表示第二个BitmapData对象的坐上点位置坐标
secondAlpha(uint):只有当secondObject参数为BitmapData对象,才能使用该参数,表示第二个BitmapData对象中视为不透明的最高alpha通道值

该碰撞没有hitTestObject()效率高,所以当对象很小时,比如宽高小于20像素,即使他不规则,采用hitTestObject()更好
*/
posted on 2011-01-11 17:22  602147629  阅读(331)  评论(0编辑  收藏  举报