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()更好
*/