Collision detection can be divided into two categories: Collision Detection of objects and objects, and Collision Detection of objects and points.
To facilitate the test, first write a box class (generate a small rectangle)
Package {import flash. display. sprite; public class box extends sprite {private var W: Number; private var H: Number; private var color: uint; Public var VX: Number = 0; Public var Vy: number = 0; Public Function box (width: Number = 50, height: Number = 50, color: uint = 0xff0000) {W = width; H = height; this. color = color; Init ();} public function Init (): void {graphics. beginfill (color); graphics. drawrect (-W/2,-H/2, W, H); graphics. endfill ();}}}
The most basic object collision detection: hittestobject
Package {import flash. display. sprite; import flash. events. event; public class boxes extends sprite {private var box: box; private var boxes: array; private var gravity: Number = 0.1; Public Function boxes () {Init ();} private function Init (): void {boxes = new array (); createbox (); addeventlistener (event. enter_frame, onenterframe);} private function onenterframe (Event: Event): void {box. vy + = gravity; box. Y + = Box. vy; // such If the object falls to the bottom boundary of the stage, it will be recreated and dropped down if (box. Y + box. height/2> stage. stageheight) {box. y = stage. stageHeight-box.height/2; createbox ();} else {for (var I: uint = 0; I <boxes. length; I ++) {// Collision Detection of IF (box!) between each falling object and other objects! = Boxes [I] & box. hittestobject (boxes [I]) {box. y = Boxes [I]. y-boxes [I]. height/2-box.height/2; // If the heap is reached, stop if (box. Y <= Box. height/2) {removeeventlistener (event. enter_frame, onenterframe) ;}else {createbox () ;}}} private function createbox (): void {box = new box (math. random () * 40 + 10, math. random () * 40 + 10, math. random () * 0 xffffff); box. X = math. random () * stage. stagewidth; addchild (box); boxes. push (box );}}}
If you replace box with the ball in the previous example, it will look like the following:
Obviously: After the rectangle is changed to a ball, the collision detection becomes inaccurate. Some balls do not seem to have really crashed into other balls. Why?
The answer is: Flash object collision detection uses "rectangular boundary of objects" by default as the basis for detection. The two pictures above demonstrate this detail: although the first picture looks to have only two rectangles at the intersection, in the Flash view, in fact, every pair of images have been met (the second figure), so we should be able to understand why some balls will float in the air after being replaced by the ball.
Collision Detection between objects and points: hittestpoint
Package {import flash. display. sprite; import flash. events. event; import flash. text. textfield; public class pointhittest extends sprite {private var ball: ball; private var box: box; private var TXT: textfield = new textfield (); Public Function pointhittest () {Init ();} private function Init (): void {BALL = new ball; addchild (ball); ball. X = stage. stagewidth/2; ball. y = stage. stageheight/2; box = new box (90, 90); addchild ( Box); box. X = 100; box. y = ball. y; addeventlistener (event. enter_frame, enterframehandler); addchild (txt); TXT. selectable = false;} private function enterframehandler (Event: Event): void {If (ball. hittestpoint (mousex, Mousey) | box. hittestpoint (mousex, Mousey) {TXT. TEXT = "met! ";}Else {TXT. Text =" ";}txt. x = mousex + 15; TXT. Y = Mousey ;}}}
When you move the mouse over two objects, you can see the collision detection result between the point where the mouse is located and the rectangle and the ball. The problem also exists here: for the ball, the rectangular boundary is also used by default, so when you move the cursor to the corner of the ball, even though the ball has not been touched, it also prompts "hit". Fortunately, flash provides an optional parameter, to improve the detection accuracy, you only need to set the third optional parameter of hittestpoint to true.
If (ball. hittestpoint (mousex, Mousey) | box. hittestpoint (mousex, Mousey,True)){
Distance-based detection: checks whether the distance between the two objects between the centers is lower than the minimum distance.
VaR ball_1: ball = new ball (70, 0xff0000); var ball_2: ball = new ball (70, 0x0000ff); ball_1.x = stage. stagewidth/2; ball_1.y = stage. stageheight/2; ball_2.x = stage. stagewidth/2; ball_2.y = stage. stageheight/2; ball_1.vx = math. random () * 20-20; ball_1.vy = math. random () * 20-20; ball_2.vx = math. random () * 20-20; ball_2.vy = math. random () * 20-20; addchild (ball_1); addchild (ball_2); addeventlistener (event. enter_frame, enterframehandler); function enterframehandler (E: Event): void {ball_1.x + = ball_1.vx; ball_1.y + = balance; ball_2.x + = ball_2.vx; balance + = balance; checkboundary (ball_1 ); checkboundary (ball_2); var DX: Number = ball_1.x-ball_2.x; var DY: Number = ball_1.y-ball_2.y; var Dist: Number = math. SQRT (dx * dx + dy * Dy); If (Dist <(ball_1.radius + ball_2.radius) {var angle: Number = math. atan2 (dy, dx); ball_1.vx = DIST * Math. cos (angle) * 0.1; ball_1.vy = DIST * Math. sin (angle) * 0.1; ball_2.vx = DIST * Math. cos (angle) *-0.1; ball_2.vy = DIST * Math. sin (angle) *-0.1;} function checkboundary (B: ball) {If (B. x> stage. stageWidth-b.width/2 | B. x <= B. width/2) {B. x-= B. VX; B. VX * =-1;} If (B. y> stage. stageHeight-b.height/2 | B. Y <= B. height/2) {B. y-= B. vy; B. vy * =-1 ;}}
Obviously, this method is very accurate for circular objects, but it can only be approximate for irregular shapes.
If you combine the elastic motion mentioned in the previous two articles, you can make more complex animations:
Package {import flash. display. sprite; import flash. events. event; public class bubbles extends sprite {private var bils: array; private var numbils: Number = 10; private var centerball: ball; private var bounce: Number =-1; private var spring: Number = 0.2; Public Function bubbles () {Init ();} private function Init (): void {bballs = new array; centerball = new ball (xcccccc); addchild (centerball); centerball. X = stage. stagewidth/2; centerball. y = stage. stageheight/2; for (var I: uint = 0; I <numbils; I ++) {var ball: ball = new ball (math. random () * 40 + 5, math. random () * 0 xffffff); ball. X = math. random () * stage. stagewidth; ball. y = math. random () * stage. stageheight; ball. VX = (math. random () * 2-1) * 10; ball. vy = (math. random () * 2-1) * 10; addchild (ball); bballs. push (ball);} addeventlistener (event. enter_frame, onenterframe);} private function onenterframe (Event: Event): void {for (var I: uint = 0; I <numbils; I ++) {var ball: ball = bils [I]; move (ball); var DX: Number = ball. x-centerBall.x; var DY: Number = ball. y-centerBall.y; var Dist: Number = math. SQRT (dx * dx + dy * Dy); var mindist: Number = ball. radius + centerball. radius; If (Dist <mindist) {var angle: Number = math. atan2 (dy, dx); var TX: Number = centerball. X + math. cos (angle) * mindist; // point of the auto motion X coordinate var Ty: Number = centerball. Y + math. sin (angle) * mindist; // y coordinate ball of the auto-Moving Target point. VX + = (tx-ball.x) * spring; ball. vy + = (ty-ball.y) * spring ;}} private function move (ball: ball): void {ball. X + = ball. VX; ball. Y + = ball. vy; If (ball. X + ball. radius> stage. stagewidth) {ball. X = stage. stageWidth-ball.radius; ball. VX * = bounce;} else if (ball. x-ball.radius <0) {ball. X = ball. radius; ball. VX * = bounce;} If (ball. Y + ball. radius> stage. stageheight) {ball. y = stage. stageHeight-ball.radius; ball. vy * = bounce;} else if (ball. y-ball.radius <0) {ball. y = ball. radius; ball. vy * = bounce ;}}}}
Schematic:
Distance-based Collision Detection for multiple objects:
Package {import flash. display. sprite; import flash. events. event; public class bubbles2 extends sprite {private var bils: array; private var numbils: Number = 20; private var bounce: Number =-0.9; private var spring: Number = 0.2; private var gravity: Number = 1; Public Function bubbles2 () {Init ();} private function Init (): void {bballs = new array (); For (var I: uint = 0; I <numbils; I ++) {var ball: ball = new ball (math. random () * 30 + 20, math. random () * 0 xffffff); ball. X = math. random () * stage. stagewidth; ball. y = math. random () * stage. stageheight; ball. VX = math. random () * 6-3; ball. vy = math. random () * 6-3; addchild (ball); bils. push (ball);} addeventlistener (event. enter_frame, onenterframe);} private function onenterframe (Event: Event): void {for (var I: uint = 0; I <numbils-1; I ++) {var ball0: ball = bils [I]; for (var j: uint = I + 1; j <numbils; j ++) {var ball1: ball = bils [J]; var DX: number = ball1.x-ball0.x; var DY: Number = ball1.y-ball0.y; var Dist: Number = math. SQRT (dx * dx + dy * Dy); var mindist: Number = ball0.radius + ball1.radius; If (Dist <mindist) {/* var angle: Number = math. atan2 (dy, dx); var TX: Number = ball0.x + math. cos (angle) * mindist; var Ty: Number = ball0.y + math. sin (angle) * mindist; */var TX: Number = ball0.x + (dx/Dist) * mindist; var Ty: Number = ball0.y + (dy/Dist) * mindist; vaR ax: Number = (TX-ball1.x) * spring; var ay: Number = (ty-ball1.y) * spring; ball0.vx-= ax; ball0.vy-= Ay; ball1.vx + = ax; ball1.vy + = Ay ;}}for (I = 0; I <numbils; I ++) {var ball: ball = bils [I]; move (ball) ;}} private function move (ball: ball): void {ball. vy + = gravity; ball. X + = ball. VX; ball. Y + = ball. vy; If (ball. X + ball. radius> stage. stagewidth) {ball. X = stage. stageWidth-ball.radius; ball. VX * = bounce;} else if (ball. x-ball. radius <0) {ball. X = ball. radius; ball. VX * = bounce;} If (ball. Y + ball. radius> stage. stageheight) {ball. y = stage. stageHeight-ball.radius; ball. vy * = bounce;} else if (ball. y-ball. radius <0) {ball. y = ball. radius; ball. vy * = bounce ;}}}}