Collision detection is an important part of many different types of animations. Everything from games to menu bars depend on some form of collision detection to trigger events. The main method for dealing with these things is hitTest().
The hitTest method is overloaded. This means the method can operate two different ways based on the parameters you send it. The first way is sometimes refered to as a "basic" hitTest and the second as an "advanced" hitTest.
Basic Hit Tests
For those of you following along at home, create two movie clips, place them on the stage and give them instance names object1 and object2. Add the following actionscript to one of the movie clips.
onClipEvent (load) {
if (_root.object1.hitTest(_root.object2)) {
trace("Objects are touching");
} else {
trace("Objects are not touching");
}}
Now, test the movie and you will see one of the two messages above in the output window. Try moving the objects around and changing their size or shape so that you can see when Flash registers this as a hitTest and when it doesnt.
As it turns out, the basic hit test will return true any time the bounding box of the two objects is overlapping. Fox example, if one of the objects in the above code is a circle, Flash calculates it as a sqaure with sides the length of the diameter of the circle. In laymans terms, this means that it isn't 100 percent accurate for objects that aren't rectangles. So to become more accurate, onward to the advanced hit tests.
Advanced Hit Tests
The basic hit test only accepts one parameter, the movie clip that is going to be tested against. Advanced Hit Tests require three parameters: a x-coordinate, a y-coordinate, and a shape flag boolean. So, to use this type of hit Test you would use something like this:
onClipEvent (load) {
if (_root.object1.hitTest(_root.object2._x, _root.object2._y, true)) {
trace("Objects are touching");
} else {
trace("Objects are not touching");
}}
Again, test it several times moving around the objects and changing the shape and getting a feel for when Flash registers this hitTest.
This will test to see if the x,y coordinate point is touching object1. But why is that any more helpful? Because we were able to set the third parameter (shape flag) to true. This means that if object1 is a circle, then it will only return true when the x,y point is actually touching the circle instead of just the bounding box.
So thats great, but what if you want it to test it against the whole second movie clip instead of just one point? Well, this is where it gets a little hairy. You have two options depending on how important efficiency is to you.
First, you can just simulate it by using several points. For example, you could do a hit test on each corner of your movie clip or you could do the middle of each side. You could easily calcuate each of these points with the getBounds() method.
getBounds() is a method that returns a custom object with four properties. These four properties are xMin, xMax, yMin and yMax. _root.object1.getBounds(_root).xMax will return the maximum x value of object1. So what is the _root part for? Well it is the target coordinate space. If for some reason you wanted the xMax of an embeded movie clip, you could specify that. If you are going to repeatedly use the properties, you could do something like: boundingBox = _root.object1.getBounds(_root); and then call each of the properties by using boundingBox.xMax or boundingBox.yMin.
Second, you can do a sort of double shape flag hit test. This is by far the least efficient way to calculate collision detection, but it is the most accurate. Note: when testing this type, make your objects are small so it will take less time to calculate. The code looks something like this:
onClipEvent (load) {
xArray = new Array();
yArray = new Array();
for (x= _root.object1.getBounds(_root).xMin; x<=_root.object1.getBounds(_root).xMax; x++) {
for (y=_root.object1.getBounds(_root).yMin; y<=_root.object1.getBounds(_root).yMax; y++) {
if (_root.object2.hitTest(x, y, true)) {
xArray = xArray.concat(x);
yArray = yArray.concat(y);
}
}
}
for (z=0; z<xArray.length; z++) {
if (_root.object1.hitTest(xArray[z], yArray[z], true)) {
trace("Point to Point Hit Test True");
break;
}
}
}
This loops through every pixel on the first movie clip using an advanced hit test to see if the pixel is touching the actual shape of the second movie clip. It then tests all of the points that were touching the second movie clip back against the shape of the first to see if it is touching that too. So, if your movie clips are 50 by 50 pixels Flash could comupte up to about 5000 hitTests each time.
Well there you have it. Four different suggestions for collision detection. Pick whichever one best fits your needs. Decide if you just need it to be approximatly accurate in a fast paced high efficiency scenario or if only the end result matters regardless of how many hours it takes to compute.