Flash AS3 implementation of irregular collision program class

Source: Internet
Author: User
Tags transparent color

Flas H from the function of the rule collision, when two components collide, you can use Hittestobject or hittestpoint for detection.

But these two functions have a flaw, is only detects the rule the collision, for the Collision detection request is not high, or the component itself is the square words, directly calls this to carry the API to be able to realize, very convenient.

The following figure: the actual component content itself is not contacted, but the components have been contacted.

If you need to perform pixel-level detection on irregular components, you can use a bit-pixel-impact bitmapdata.hittest () which is a high precision pixels collision but is a little less efficient. There are a lot of similar examples, code, the feeling is not good enough, the main is not directly to use, but also to make some changes, more trouble.

Now provide an online search for the class, the original is written by foreigners, the operation of the error, and later modified, has been able to use the normal

The code is as follows Copy Code
Package code
{
Optimization of pixel-level exact collision algorithm
Code: Aone
Import Flash.display.BitmapData;
Import Flash.display.BlendMode;
Import Flash.display.DisplayObject;
Import Flash.geom.ColorTransform;
Import Flash.geom.Matrix;
Import Flash.geom.Point;
Import Flash.geom.Rectangle;
public class HitTest
{
public static var tilesize:int = 20;
public static function Complexhittestobject (Target1:displayobject, target2:displayobject): Boolean
{
The horizontal reduction to the tilesize size required multiples, that is, the desired detection of the time reduced to the size.
var scalex:number = (Target1.width < target2.width? target1.width:target2.width)/Tilesize
The size needed to be reduced lengthwise to tilesize
var scaley:number = (Target1.height < target2.height? target1.height:target2.height)/Tilesize
//
If the multiple is less than 1, then the original magnification is the original size
ScaleX = ScaleX < 1? 1:scalex
ScaleY = ScaleY < 1? 1:scaley
Draw with Point
var pt:point=new point ()
Color used when making 2 times draw
var ct:colortransform=new colortransform ()
ct.color=0xff00000f
Overlapping rectangles under the original size
var oldhitrectangle:rectangle=intersectionrectangle (Target1, Target2)
Overlapping rectangles for zooming in
var hitrectangle:rectangle= new Rectangle ()
Return Complexintersectionrectangle (Target1, Target2, ScaleX, ScaleY, PT, CT, oldhitrectangle,hitrectangle,tilesize,t ilesize). 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 was 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);
Return bounds1.intersection (BOUNDS2);
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)-inte rsection.x);
Intersection.height = math.min (bounds1.y + bounds1.height)-INTERSECTION.Y, (bounds2.y + bounds2.height)-I NTERSECTION.Y);
return intersection;
}
private static function Complexintersectionrectangle (Target1:displayobject, Target2:displayobject, Scalex:number, Scaley:number, Pt:point, Ct:colortransform, Oldhitrectangle:rectangle,hitrectangle:rectangle,noww:int,nowh:int): Rectangle
{
if (!target1.hittestobject (Target2))
return new Rectangle ();
Calculates the reduced overlapping rectangle size based on the narrowing multiple of the aspect
hitrectangle.x = oldhitrectangle.x
Hitrectangle.y = Oldhitrectangle.y
Hitrectangle.width = Oldhitrectangle.width/scalex
Hitrectangle.height = Oldhitrectangle.height/scaley
Set up a temporary BitmapData object for draw, size is expected wide NOWW, expect high NOWH
var bitmapdata:bitmapdata=new bitmapData (Noww,nowh, True, 0);
Drawing Object 1 The scaling and displacement are computed by the Getdrawmatrix () function, and the opacity is drawn to the color of the CT.
Bitmapdata.draw (Target1, Getdrawmatrix (Target1, Hitrectangle, ScaleX, ScaleY), CT);
Replace any colored pixels with the CT color 0xff00000f when the zoom ratio is not 1, because the reduced object will have semitransparent pixels produced when the solid color is drawn, and if not replaced, the filter effect for the following object 2 will be affected.
if (scalex!=1&&scaley!=1)
Bitmapdata.threshold (bitmapdata,bitmapdata.rect,pt, ">", 0,0xff00000f)
Drawing Object 2 Its scaling and displacement are computed by the Getdrawmatrix () function, and the opacity is plotted as the color of the CT, and the pattern is superimposed. So one of the two objects overlapping parts of the color value must be greater than 0xff00000f.
Bitmapdata.draw (Target2, Getdrawmatrix (Target2, Hitrectangle, ScaleX, ScaleY), CT, blendmode.add);
Replace the portion of all color values greater than 0xff00000f (that is, overlapping) with opaque red to facilitate the subsequent getcolorboundsrect () method for calculating dimensions. The reason for this substitution is that getcolorboundsrect () does not support range fetching but only monochrome calculations.
Object 1 can be replaced with a transparent color after zooming, but object 2 cannot use the same method, but object 2 has semitransparent pixels because it is also scaled, so the overlap is not necessarily uniform, although it is all larger than 0xff00000f.
var hits:int=bitmapdata.threshold (bitmapdata,bitmapdata.rect,pt, ">", 0xff00000f,0xffff0000)
Determine the size of the red area
var intersection:rectangle=bitmapdata.getcolorboundsrect (0xFFFFFFFF, 0xffff0000);
Bitmapdata.dispose ();
If the red area is not 0 wide, the bitmapdata contains red pixels. This explains that object 1 and object 2 overlap and collide in this decision.
If any one of the vertical and horizontal scaling ratios is not the original size
And the number of red pixels is relatively small, the collision area of Object 1 and object 2 is smaller.
if (intersection.width!= 0 && (ScaleX > 1 | | scaleY > 1) && hits <= (scalex+scaley) * 1.5)
{
Since BitmapData's wide-high coordinates are represented as integers, the area that is scaled and rounded up is bound to ignore the area where the real possibility of collisions can occur when rounding.
So in order to do the next test when appropriate to expand the detection area Xadd and Yadd is the expansion of the coefficient
var xadd:int = 0.5;
var yadd:int = 0.5;
Expected size of bitmapdata at next Test
If the collision area is found to be the same as the bitmapdata size, then the next time the area will be judged to be the same as the region, the result may be the same as the result. This will cause overflow on the stack, and in order to avoid this situation, the size of the reduced judgment will be enlarged by one time to detect again.
var nextw:int = (intersection.width!= noww)? TILESIZE:NOWW * 2;
var nexth:int = (intersection.height!= nowh)? TILESIZE:NOWH * 2;
The area of the collision is computed according to the detected contraction area to reduce the detection range for the next calculation.
Oldhitrectangle.x + = (intersection.x-xadd) * ScaleX;
Oldhitrectangle.y + = (intersection.y-yadd) * ScaleY;
Oldhitrectangle.width = (intersection.width + xadd*2) * ScaleX;
Oldhitrectangle.height = (intersection.height + yadd*2) * ScaleY;
Recalculate the magnification by reducing the size of the test expectation
ScaleX = (OLDHITRECTANGLE.WIDTH/NEXTW)
ScaleY = (oldhitrectangle.height/nexth)
If the magnification is less than 2, press the original size directly
ScaleX = ScaleX < 2? 1:scalex
ScaleY = ScaleY < 2? 1:scaley
Make the next decision
intersection = Complexintersectionrectangle (Target1,target2, ScaleX, ScaleY, Pt,ct,oldhitrectangle,hitrectangle, Nextw,nexth)
}
return intersection;
}
protected static function Getdrawmatrix (Target:displayobject, Hitrectangle:rectangle, Scalex:number, Scaley: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)/ScaleX;
matrix.ty= (LOCALTOGLOBAL.Y-HITRECTANGLE.Y)/ScaleY;
Matrix.a=matrix.a/rootconcatenatedmatrix.a/scalex;
Matrix.d=matrix.d/rootconcatenatedmatrix.d/scaley;
return matrix;
}
}
}


The use method is also very simple:

  code is as follows copy code

Hittest.complex Hittestobject (component 1, component 2);

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.