04-03-2011 07:40 PM
Hello,
I am currently playing around with Adobe Flash and found the function:
if(object1.hitTestObject(object2)){
(...)
}
Coming from Java development, this is amazing to have! But now the question:
This function only works/detects when two square objects hit. Is there also a function like this when two circles hit? In my test app, there are two balls bouncing and I want to detect when they hit.
Thanks!
Solved! Go to Solution.
04-03-2011 08:03 PM - edited 04-03-2011 08:03 PM
Circles are the easiest. Simply get the radius and x/y of each in the same coordinate system and check the distance between them. For example:
function hitTestCircles(object1:DisplayObject, radius1:Number, object2:DisplayObject, radius2:Number):Boolean
{
var xDiff:Number = object1.x - object2.x;
var yDiff:Number = object1.y - object2.y;
var distance:Number = Math.sqrt(xDiff * xDiff + yDiff * yDiff);
if (distance < radius1 + radius2) return true;
else return false;
}
If the objects you are passing know their radius, you can easily define the funcion to run the same as the other, IE object1.hitTestCircle(object2).
04-03-2011 08:18 PM
I'd like to add, that if you wish to do very complex physics you may be interested in using a pre-written physics engine like Box2D.
04-03-2011 08:26 PM
04-03-2011 09:02 PM
i completely agree bba ![]()
@kai001: dude thats some pretty sweet stuff -- i've never seen it before. Definitely gonna have to try it out !
04-03-2011 09:06 PM
bba: I think Brandon_Appetizer's solution is probably the best for what you're looking for, but I'm glad to help!
JRab: Yes, it appears to be very flexible, you could probably make some really impressive things with it. I've known of it for awhile, but I've never actually used it as I've never required any very complex physics in any of my projects. (Yet)
(Off-topic: Yay, my first kudos! Thanks everyone!)
04-03-2011 09:09 PM
for hit testing on irregular shapes you can convert your objects into bitmaps that support transparency, then evaluate the pixels of the BitmapData. essentially, if two bitmaps are overlapping in areas that aren't transparent (that don't have an alpha value of zero) then they are hitting.
more in the documentation here: flash.display.BitmapData.hitTest()
this very topic is covered in chapter 1 ("Advanced Collision Detection") of Keith Peters' book "Advanced ActionScript 3.0 Animation". i highly recommend his book (and the prequel) to anyone who is new to ActionScript 3.0.
04-04-2011 01:50 AM
One word of caution regarding the BitmapData hitTest. It does not support rotated bitmaps. There are a few ways to work around this so you can do such tests, but they are not built in.
For example, if you want to hit test a point with a rotated bitmap, you simply apply the negative rotation to the point (in the bitmap's space, you can use a Matrix) before doing the hit test. I actually had to do exactly this for the app I submitted for the playbook offer. If there's any demand, I'd be happy to post the relevant pieces of source code.
04-04-2011 09:12 AM
@cycletronic, I'd be interested to see that. In one of my apps, I'm using a combination of getObjectsUnderPoint() and a Bitmap.hitTest(), currently with unrotated objects. I had intended to allow rotated ones at some point, but just tested and confirmed what you say, that the rotation confuses the test.
My first instinct (since I'm not much of a game programmer) would have been to draw the rotated bitmap into a new bitmap, and use that so the hit test would work. The inverse Matrix idea makes total sense, so if you'd like to share, I'm a ready audience. ![]()
04-04-2011 01:34 PM
Ok, here's the sample code. This checks to see if a Point is colliding with a BitmapData object. The bitmap has an alpha mask, essentially.
// A GameObject is my custom Sprite-like object, with position, velocity, etc.
public function checkCollision(other:GameObject):Boolean
{
// Get the center position of the other object.
var opt:Point = other.position.add(new Point(other.width/2, other.height/2));
var sizept:Point = new Point(width/2, height/2);
// Get the center position of this object.
var tpt:Point = position.add(sizept);
// Setup the matrix.
var mat:Matrix = new Matrix();
// First move the rotation center point to make it as if
// this (bitmap) object is centered at 0,0.
// In other words, temporarily move the bitmap to 0,0.
mat.translate(-tpt.x, -tpt.y);
// Then rotate the opposite direction from which this
// object is currently rotated.
mat.rotate(-rotation);
// Apply the matrix to the "other" point.
var testpt:Point = mat.transformPoint(opt);
// Perform the test. The first parameter is the point to
// use as the origin of the test. In our case, the center
// of the bitmap.
return img.bitmap.hitTest(new Point(-width/2, -height/2), 0xFF, testpt);
}
If you want to collide between two rotate bitmaps, then you need to do what peter9477 thought of. That is, you draw the rotated bitmaps to new bitmaps and then do testing. I'm fairly confident there are examples of that elsewhere.