-
Notifications
You must be signed in to change notification settings - Fork 0
/
HitTest.as
111 lines (83 loc) · 3.93 KB
/
HitTest.as
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//****************************************************************************
// Language Version: ActionScript 3.0
// Runtime Versions: Flash Player 9
//****************************************************************************
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 either of the items don't have a reference to stage, then they are not in a display list
// or if a simple hitTestObject is false, they cannot be intersecting.
if (! target1.root||! target2.root||! target1.hitTestObject(target2)) {
return new Rectangle();
}
// Get the bounds of each DisplayObject.
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 a simple hitTestObject is false, they cannot be intersecting.
if (! target1.hitTestObject(target2)) {
return new Rectangle();
}
var hitRectangle:Rectangle=intersectionRectangle(target1,target2);
// If their boundaries are no interesecting, they cannot be intersecting.
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);
// Draw the first target.
bitmapData.draw( target1, HitTest.getDrawMatrix( target1, hitRectangle, accurracy ), new ColorTransform( 1, 1, 1, 1, 255, -255, -255, 255 ) );
// Overlay the second target.
bitmapData.draw( target2, HitTest.getDrawMatrix( target2, hitRectangle, accurracy ), new ColorTransform( 1, 1, 1, 1, 255, 255, 255, 255 ), BlendMode.DIFFERENCE );
// Find the intersection.
var intersection:Rectangle=bitmapData.getColorBoundsRect(0xFFFFFFFF,0xFF00FFFF);
bitmapData.dispose();
// Alter width and positions to compensate for accurracy
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 {
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;
}
}
}