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; } } } |