00:00
00:00
Newgrounds Background Image Theme

NobeastcanDefeatme just joined the crew!

We need you on the team, too.

Support Newgrounds and get tons of perks for just $2.99!

Create a Free Account and then..

Become a Supporter!

AS3: circumference rect collisions.

1,571 Views | 5 Replies
New Topic Respond to this Topic

AS3:Main

Working on a game, I have to make a circumference and line collision detection.
This is what I get. Hope it help some one :)

First we have the circumference equation:
center is (h,k) and radius r.

pow(x) + pow(y) +Dx + Ey + F = 0

we have:

D=-2h, E=-2k, F=pow(h) + pow(k) + pow(r)

Then we have the line equation:

y = mx + n

where m is the slope and n the ordinate( where the line cut the x ordinate, or in other words, where y = 0).
m = tan(alpha) where alpha is the angle that makes the line with the x ordinate.
if we have one point of the line, we can calculate

= y - (m * x)

.

Supplanting y in the circumference equation:

pow(x) + pow(mx+n) + Dx + E(mx + n) + F = 0

if we do some math here we end having this:

( 1+pow(m) )*pow(x) + (2mn+D+Em)*x + pow(n) + E*n + F = 0

Then we have to remember something about quadratic equations:

a*pow(x) + b*x + c = 0

so from the resulting equation we have:

a = 1+pow(m), b = 2*m*n + D + E*m, c = pow(n) + E*n + F

and to resolve it:

x = ( -b +- sqrt(pow(b) - 4*a*c) ) / (2*a)

and from here we know that:

pow(b) - 4*a*c

must be positive to be real, so:
resuming all here is the function:

private function circumferenceRectInterception(x:Number, y:Number, radius:Number, slope:Number, intercept:Number = 0):Boolean {
   var intercepted:Boolean;
   var result:Number;
   var D:Number, E:Number, F:Number, a:Number, b:Number, c:Number;
   D = round(-2 * x,5);
   E = round(-2 * y,5);
   F = round((x*x) + (y*y) - (radius*radius),5);
   a = round(1 + (slope*slope),5);
   b = round((2*slope*intercept) + D + (E*slope),5);
   c = round((intercept*intercept) + (E*intercept) + F,5);
   result = round((b*b) - (4*a*c),5);
   intercepted = false;
   if (result >= 0) {
          intercepted = true;
    }
	  return intercepted;
    }

And that is all. I hope it understandable.
And I'm sorry about my bad English.
Any doubt or criticism are welcome.

Response to AS3: circumference rect collisions. 2012-03-21 20:48:42


If you're putting collisions on objects that are perfectly round (not oval) you can base it on the distance from the center of that object. It's hard for me to tell if that will work with what you're doing.

Response to AS3: circumference rect collisions. 2012-03-22 08:26:08


Hi Kellexx,
This code is for, if you have a ball and other object, and the last one is moving flowing a straight line, and you need to know if they are going to collided, before doing all the animation.
Thank you anyway abut your tip ;), it can be helpful.

Response to AS3: circumference rect collisions. 2012-03-22 10:36:54


Hi PSvils,
Yes you are true, when the object is moving straight up it should explode because of tan(90) but As3 resolve it to a big number...
I do this test: You can test it ;). And it looks like it work ok.

private function tanAngleTest():void {
			var angle:Number = 0;
			var radians:Number = angle*Math.PI/180;
			var slope:Number = Math.tan(radians); 
			trace("Angle:" + angle + " p(100,0), colision:" + circumferenceRectInterception(100, 0, 10, slope));
			trace("Angle:" + angle + " p(100,50), colision:" + circumferenceRectInterception(100, 50, 10, slope));
			
			angle = 90;
			radians = angle*Math.PI/180;
			slope = Math.tan(radians);
			trace("Angle:" + angle + " p(0,100), colision:" + circumferenceRectInterception(0, 100, 10, slope));
			trace("Angle:" + angle + " p(20,100), colision:" + circumferenceRectInterception(20, 100, 10, slope));
			
			angle = 45;
			radians = angle*Math.PI/180;
			slope = Math.tan(radians);
			trace("Angle:" + angle + " p(100,100), colision:" + circumferenceRectInterception(100, 100, 10, slope)); 
			trace("Angle:" + angle + " p(100,30), colision:" + circumferenceRectInterception(100, 30, 10, slope)); 
		}
		
		private function circumferenceRectInterception(x:Number, y:Number, radius:Number, slope:Number, intercept:Number = 0):Boolean {
			var intercepted:Boolean;
			var result:Number;
			var D:Number, E:Number, F:Number, a:Number, b:Number, c:Number;
			D = -2 * x;
			E = -2 * y;
			F = (x*x) + (y*y) - (radius*radius);
			a = 1 + (slope*slope);
			b = (2*slope*intercept) + D + (E*slope);
			c = (intercept*intercept) + (E*intercept) + F;
			result = (b*b) - (4*a*c);
			intercepted = false;
			if (result >= 0) {
				intercepted = true;
			}
			return intercepted;
		}

It will be very nice to learn from your tutorial ;) and much better if it is much more effective!
Sorry about my wording... as you can deduct my natural language is not English, and I don't know it very well.

About rounding the values... This is a mistake I have copied from my code. It's because I have to reproduce the same algorithm in the server side, write in Java, that work differently with floating points, so I round the Number(client) and float(server) with 5 digits after the coma at the tow sides (client and server).

Response to AS3: circumference rect collisions. 2012-03-22 15:06:37


At 18 hours ago, Kellexx wrote: If you're putting collisions on objects that are perfectly round (not oval) you can base it on the distance from the center of that object. It's hard for me to tell if that will work with what you're doing.

It's the circle's equation.
(x-u)²+(y-v)²=r²

x: the object's X coordinate
y: the object's Y coordinate
u: the object with the "invisible" circle centre's X coordinate
v: the object with the "invisible" circle centre's Y coordinate
r: the circle's radius

if(((x-centre.x)*(x-centre.x)) + ((y-centre.y)*(y-centre.y)) <  50*50) //radius in pixels...
{
  //It's within the circle!
}

"Stand up and fight! Stand up and see the sky turn bright! Fight for a better day!"

-Turisas

Response to AS3: circumference rect collisions. 2012-03-22 15:17:11


Hi scearezt,
Thanks for the code snippet, it will help me.
But, for using this on the situation of something thrown from a point with some angle, and testing if collided with the ball, you have to do the test at almost every point of the trajectory. With the junction of the circumference equation and the straight line equation, you just do it one time per ball.