Circle Collisions

September 22nd, 2008

First tutorial in 9 months, so bare with me. :P

We are going to make a script that will make circles collide with each other. This would be very hard to do with hitTest()’s so we are going to use a small amount of trigonometry. Don’t let the big word or its meaning scare you. All we are going to need is 13 lines of code. Here is what it should look like:

(Either JavaScript is not active or you are using an old version of Adobe Flash Player. Please install the newest Flash Player.)

As always, open up flash and start a new flash file (CS3 users, make sure you select AS2. For AS3 code jump to the bottom of the tutorial). Select the oval tool and draw a circle whatever size you want on the stage. Make sure you hold the shift button when you draw the circle so it is perfectly round, otherwise this won’t work. Select the circle and hit F8 to convert it to a movieclip. Call it whatever you want. Make sure the registration point is in the center.

Converting to a MC

Drag another “circle” MC from the library and onto the stage. Give each MC an instance name of c0 and c1 (obviously make sure you don’t call them both c1). Now we are ready to get into the code.

onEnterFrame = function () {
	c0._x = _xmouse;
	c0._y = _ymouse;
 
	xdist = c1._x - c0._x;
	ydist = c1._y - c0._y;
	dist = Math.sqrt(xdist * xdist + ydist * ydist);
	angle = Math.atan2(ydist, xdist);
 
	if(dist < c0._width) {
		c1._x = c0._x + (c0._width * Math.cos(angle));
		c1._y = c0._y + (c0._width * Math.sin(angle));
	}
};

Paste that code onto the frame.

First of all, we put everything inside an onEnterFrame() funtion. This tells flash that we want this code to be run every frame.

c0._x = _xmouse sets the circle with the instance name c0’s x coordinate to whatever the mouses is that frame. The same goes for the next line, except with the y coordinates. This makes our MC follow the mouse around.

The next 3 lines all have to do with the Pythagorean theorem, or pythag. Pythag is used to get the length of the hypotenuse of a right angled triangle. What are we using it for then? This diagram should be able to explain it better than me:

So basically pythag tells us that if you square xdist and ydist, add them together and then get the square root of that you will have the distance of the red line above, which is handy to us because it tells us how far apart the circles are. Since circles are perfectly round, if they are closer than the half of the width of each circle (or the width of one circle if they are the same size) then they are touching.

Back to the code. We get xdist, then ydist, then do pythag and alakazam. We have the distance between the circles. The next line tells us the angle of the angles in the triangle. You don’t need to understand how this works, it just does :P. We will use this a bit later.

if(dist < c0._width) { checks if the circles are colliding like I explained above. If the are it runs the following code.

c1._x = c0._x + (c0._width * Math.cos(angle));
c1._y = c0._y + (c0._width * Math.sin(angle));

The trig.

This relates back to a right angled triangle. Cosine (cos) and Sine (sin) are both trig functions that tell us a certain side of the right angled triangle if we give it the angle. The answer it gives us is on a triangle with a hypotenuse with the length of 1.

STOP! Diagram time.

As you (probably) can(’t) see from this (crappy) diagram c0._width * Math.cos(angle) returns the x distance the circle needs to move until they aren’t colliding. Same goes for the c0._width * Math.sin(angle) and the y distance. We simply make c1 move those distances from c0 and they shouldn’t be colliding anymore.

If you haven’t already gotten bored from me taking over 9000 lines to explain 13 lines of code, press Ctrl+Enter to test out this nifty little script.

AS3 code thanks to Corey:

addEventListener(Event.ENTER_FRAME, circleCollision);
 
function circleCollision(event:Event):void {
c0.x = mouseX;
c0.y = mouseY;
 
var xdist:Number = c1.x - c0.x;
var ydist:Number = c1.y - c0.y;
var dist:Number = Math.sqrt(xdist * xdist + ydist * ydist);
var angle:Number = Math.atan2(ydist, xdist);
 
if (dist < c0.width) {
c1.x = c0.x + (c0.width * Math.cos(angle));
c1.y = c0.y + (c0.width * Math.sin(angle));
}

(Either JavaScript is not active or you are using an old version of Adobe Flash Player. Please install the newest Flash Player.)

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google
  • description
  • Furl
  • Slashdot
  • StumbleUpon
  • Technorati

14 Responses to “Circle Collisions”

  1. Daniel Says:

    Thanks for the tutorial, as A beginner I find all information very helpful. :

  2. David Says:

    Actually this isn’t really THAT hard to do with hitTest, you can just use it plus the radius but this is much simpler I guess! Thanks! :D

  3. admin Says:

    If you added the radius to the hitTest, you would only be testing 1 point on the circle. To do this with hitTest effectively, you would need to make a loop to run through each point around the circle (the bigger the circle the more loops needed). That could mean you need to check for a collision 360 times a frame, instead of just once like in the tutorial.

  4. David Says:

    True, that’s not good in 2 circles, but 1 circle and a line should work good. However. This code gives me an error, prob. just something that the website did to it, anyway

    unexpected ‘if’ encountered if(dist < c0._width) { at line 10

    unexpected ‘}’ encountered at line 13. Hmmm

  5. awesty Says:

    Oh, change &lt; to <

  6. Kurt Says:

    Nice tutorial :D i finally got back into flash :P. but some stuff I don’t understand like;

    dist = Math.sqrt(xdist * xdist + ydist * ydist);
    angle = Math.atan2(ydist, xdist);
    c1._x = c0._x + (c0._width * Math.cos(angle));
    c1._y = c0._y + (c0._width * Math.sin(angle));

    I just don’t get the math thing because I have no idea what it does.

  7. awesty Says:

    It’s just some trigonometry. You don’t really need to know how it works, just that it does. :P

  8. CoreySteel Says:

    Hey.

    Here is ActionScript 3.0 code, if anyone is interested :)

    addEventListener(Event.ENTER_FRAME, circleCollision);

    function circleCollision(event:Event):void {
    c0.x = mouseX;
    c0.y = mouseY;

    var xdist:Number = c1.x - c0.x;
    var ydist:Number = c1.y - c0.y;
    var dist:Number = Math.sqrt(xdist * xdist + ydist * ydist);
    var angle:Number = Math.atan2(ydist, xdist);

    if (dist < c0.width) {
    c1.x = c0.x + (c0.width * Math.cos(angle));
    c1.y = c0.y + (c0.width * Math.sin(angle));
    }

  9. awesty Says:

    Thanks Corey, I’ll add that to the post.

  10. Jotte Says:

    Thanks a ton! I’ve been looking for something similar for quite a while now. But this is more than enough for my needs.
    You’re awesome!

  11. Terrence Says:

    Nice tutorial.
    Is there any way to keep the circle on the stage?

  12. NOEL Says:

    Very clear, usefull for many things.
    Thanks

  13. Muovimuki Says:

    Very helpful tutorial (for me and for my purposes). I’m very pleased someone really explain something like that.. i don’t really understand math and… it’s frustrating.

    So. Thanks for this tutorial!

  14. LT Squirrel Says:

    why doesn’t the ball stay inside the stage when i hit it out?

Leave a Reply