Saturday, September 20, 2008

Flash pixel collision detection





The CollisionDetection class is really simple to work with, there is a single static method called checkForCollision with four parameters:

checkForCollision(movieClip1,movieClip2,alphaTolerance);

movieClip1, movieClip2 - The MovieClip instances to check for collision.
alphaTolerance - a number from 0 to 255 that specifies the transparency tolerance when testing the collision. A higher number will increase the tolerance (ie. allow more transparent parts of the MovieClip to register collisions). Defaults to 255.

Returns a Rectangle object specifying the intersection of the two MovieClips in the _root coordinate space, or null if they do not intersect.


code (CollisionDetection.as):

import flash.display.BitmapData;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Rectangle;

class CollisionDetection {
static public function checkForCollision(p_clip1:MovieClip,p_clip2:MovieClip,p_alphaTolerance:Number):Rectangle {

// set up default params:
if (p_alphaTolerance == undefined) { p_alphaTolerance = 255; }

// get bounds:
var bounds1:Object = p_clip1.getBounds(_root);
var bounds2:Object = p_clip2.getBounds(_root);

// rule out anything that we know can't collide:
if (((bounds1.xMax < bounds2.xMin) || (bounds2.xMax < bounds1.xMin)) || ((bounds1.yMax < bounds2.yMin) || (bounds2.yMax < bounds1.yMin)) ) {
return null;
}

// determine test area boundaries:
var bounds:Object = {};
bounds.xMin = Math.max(bounds1.xMin,bounds2.xMin);
bounds.xMax = Math.min(bounds1.xMax,bounds2.xMax);
bounds.yMin = Math.max(bounds1.yMin,bounds2.yMin);
bounds.yMax = Math.min(bounds1.yMax,bounds2.yMax);

// set up the image to use:
var img:BitmapData = new BitmapData(bounds.xMax-bounds.xMin,bounds.yMax-bounds.yMin,false);

// draw in the first image:
var mat:Matrix = p_clip1.transform.concatenatedMatrix;
mat.tx -= bounds.xMin;
mat.ty -= bounds.yMin;
img.draw(p_clip1,mat, new ColorTransform(1,1,1,1,255,-255,-255,p_alphaTolerance));

// overlay the second image:
mat = p_clip2.transform.concatenatedMatrix;
mat.tx -= bounds.xMin;
mat.ty -= bounds.yMin;
img.draw(p_clip2,mat, new ColorTransform(1,1,1,1,255,255,255,p_alphaTolerance),"difference");

// find the intersection:
var intersection:Rectangle = img.getColorBoundsRect(0xFFFFFFFF,0xFF00FFFF);

// if there is no intersection, return null:
if (intersection.width == 0) { return null; }

// adjust the intersection to account for the bounds:
intersection.x += bounds.xMin;
intersection.y += bounds.yMin;

return intersection;
}
}

------------------------------------------------------------------------------------

code (in Flash):

import CollisionDetection;
import flash.geom.Rectangle;

createEmptyMovieClip("drawin",100);
drawin.clear();
// check for collisions:
var collisionRect:Rectangle = CollisionDetection.checkForCollision(mc1,mc2,120);

// if there is a collision, draw the intersection:
if (collisionRect) { with (drawin) {
beginFill(0x00FF00,20);
lineStyle(0,0x00FF00,40);
moveTo(collisionRect.x,collisionRect.y);
lineTo(collisionRect.x+collisionRect.width,collisionRect.y);
lineTo(collisionRect.x+collisionRect.width,collisionRect.y+collisionRect.height);
lineTo(collisionRect.x,collisionRect.y+collisionRect.height);
lineTo(collisionRect.x,collisionRect.y);
}}

if (collisionRect) {
//do your stuff
}

------------------------------------------------------------------------------------

Click here to download. It includes two simple demos to help you get started with it.

No comments: