Copy link to clipboard
Copied
Hello again everyone - I'm in the middle of attempting to write my own collision detection algorithm because the built in 'hitTestObject' function seems to be incredibly inaccurate (it's registering 'hits' when the objects are still a considerable distance from each other).
I need to be able to calculate the position of each of the 4 corners of a rectangle, based on its rotation. Obviously one of the corners will simply be the rectangle's x and y coordinates. I have made a little test program to make sure I am calculating the positions of the corners accurately - it works when the rectangle is rotated to 0, 90, 180 and 270 degrees, but produces strange results for any other angles...
I have attached the program at the bottom, but here is the code:
package
{
import flash.display.MovieClip;
import flash.geom.Point;
public class CornerFinder extends MovieClip
{
//vars
var myRect:MovieClip;
//constructor
public function CornerFinder():void
{
myRect = new MyRectangle();
myRect.x = stage.stageWidth/2;
myRect.y = stage.stageHeight/2;
myRect.rotationZ = 270;
addChild(myRect);
AddCornerMarkers();
}
private function AddCornerMarkers():void
{
//The rotation of the rectangle in radians
var rectRotation = myRect.rotationZ*(Math.PI/180);
var corners:Array = new Array();
corners[0] = new Point(myRect.x, myRect.y);
corners[1] = new Point( (myRect.x + myRect.width * Math.cos(-rectRotation)), (myRect.y + myRect.height*Math.sin((rectRotation) )) );
corners[2] = new Point( (myRect.x + myRect.width * Math.sin(-rectRotation)), (myRect.y + myRect.height*Math.cos((rectRotation) )) );
corners[3] = new Point(corners[2].x + (corners[1].x - corners[0].x) , corners[2].y + (corners[1].y - corners[0].y));
for(var i:uint = 0; i < corners.length; i++)
{
var marker:MovieClip = new CornerMarker();
marker.x = corners.x - marker.width/2;
marker.y = corners.y - marker.height/2;
trace("Adding marker at: " + marker.x + ", " + marker.y);
addChild(marker);
}
}
}
}
MyRectangle, as you may have guessed is a simple rectangular symbol that is in the library of my fla file. The CornerMarker is just a red circle symbol.
Can anyone see what the problem is? I thought if it worked for the 'main' angles (e.g. 0, 90, 180, etc) it would work for everything in between, but apparently not...
Copy link to clipboard
Copied
if you want an accurate hittest you should be using the bitmapdata's hittest.
Copy link to clipboard
Copied
Would this not be rather slow? I need to perform a large number of collision detection checks every update so I'm trying to get a balance between accuracy and preformance - at the moment hitTestObject is simply too innacurate, but I think using bitmap data could cause a major performance hit...
Copy link to clipboard
Copied
So no one has any idea why my code isn't working? I had assumed that I'd just made a simple error in my maths - it's been a while since I've had to do anything like this haha
If anyone has any other possible solutions then please let me know, failing that, how do I get the bitmap data from a MovieClip?
Copy link to clipboard
Copied
you have some basic problems.
1. assign myRect's rotationZ to zero, then compute your corners, then reassign the rotationZ to myRect
2. your calculations are wrong. here's corners[1] to get you started:
corners[1] = new Point( (myRect.x + myRect.width * Math.cos(rectRotation)), (myRect.y + myRect.width*Math.sin((rectRotation) )) );
3. to create a bitmapdata object from a displayobject, use the draw() method of the bitmapdata class.
Copy link to clipboard
Copied
Forgive me if I'm misunderstanding you here, but if I assign the rotationZ to 0 first then change it back the locations of the CornerMarkers will not change - they'll just be sitting where they were before the rotation... It's calculating it with the rotation that's being the major problem here, if I could do it without the rotation corner[1] would simply be (corner[0].x + width, corner[0].y), etc
Also if I change my formulas to use the one you suggest it only works for 0 and 180 degrees, and not for 90 or 270 anymore... that's why I changed it in the first place I think lol Originally I had the same as you suggest.
I'm considering changing the rotated rectangles to circles at this rate - that way I can avoid having to rotate them at all ![]()
Copy link to clipboard
Copied
you misunderstand.
try:
package
{
import flash.display.MovieClip;
import flash.geom.Point;
public class CornerFinder extends MovieClip
{
//vars
var myRect:MovieClip;
//constructor
public function CornerFinder():void
{
myRect = new MyRectangle();
myRect.x = stage.stageWidth/2;
myRect.y = stage.stageHeight/2;
myRect.rotationZ = 270;
addChild(myRect);
AddCornerMarkers();
}
private function AddCornerMarkers():void
{
//The rotation of the rectangle in radians
var rectRotation = myRect.rotationZ*(Math.PI/180);
var corners:Array = new Array();myRect.rotationZ=0;
corners[0] = new Point(myRect.x, myRect.y);
corners[1] = new Point( (myRect.x + myRect.width * Math.cos(rectRotation)), (myRect.y + myRect.width*Math.sin((rectRotation) )) );
// corners[2] = new Point( (myRect.x + myRect.width * Math.sin(-rectRotation)), (myRect.y + myRect.height*Math.cos((rectRotation) )) );
// corners[3] = new Point(corners[2].x + (corners[1].x - corners[0].x) , corners[2].y + (corners[1].y - corners[0].y));myRect.rotationZ=rectRotation*180/Math.PI;
for(var i:uint = 0; i < corners.length; i++)
{
var marker:MovieClip = new CornerMarker();
marker.x = corners.x - marker.width/2;
marker.y = corners.y - marker.height/2;
trace("Adding marker at: " + marker.x + ", " + marker.y);
addChild(marker);
}
}
}
}
Copy link to clipboard
Copied
This could be accomplished by using the transform matrix for your rectangle. Try the following:
var matrixClone:Matrix = rectangleItem.transform.matrix.clone();
matrixClone.rotate(degreesOfRotation * (Math.PI / 180));
Then using the original boundary points of your rectangle, use the transformPoint() method of the rotated matrix:
ie.
var newTopLeft:Point = matrixClone.transformPoint(originalTopLeft.x, originalTopLeft.y);
var newTopRight:Point = matrixClone.transformPoint(originalTopLeft.x + rectangleItem.width, originalTopLeft.y);
...
Do the transformPoint call on each of the corners to return the new point location based on the rotation.
Realize this is a very late reply to the thread, but hopefully this helps out folks in the future.
Get ready! An upgraded Adobe Community experience is coming in January.
Learn more