home subscribe to email updates subscribe to RSS updates

Actionscript Physics: Ball on Ball Reactions.

If you're anything like me, the idea of adding some simple physics to your next game is freaking exciting... though a little intimidating. Unfortunately I lost my Math mojo around year 10 when girls and football stole the spotlight.

I recently purchased "Physics for Game Programmers" looking for some easy answers. It's a great book (highly worth buying) but a little heavy on theory and light on code examples. I was specifically after information on ball-ball reactions and angular momentum though it left me feeling like I should've paid a little more attention in class. Admittedly, I haven't gone through the book chapter by chapter (this probably would solve my problem) but who has time for that?!

In a bid to start giving back to the Flash community, here's a headstart down the track to create realistic looking Billiard/Pool Ball physics in Actionscript.

Let me preface the following information by stressing that by no means am I a physics guru (nothing has changed since grade 10) , I expect you to be at least an intermediate Actionscripter and familiar with basic game-orientated trigonometry to keep up. If you have questions, post comments here and I'll answer them as best I can... if I can! The second disclaimer is that I'm still quite new to Flash. The way I do things may be a little unconventional but they've worked for me so far. Let me know if you think there's a better way to play.

Step 1 - The ball symbol

Firstly, open Flash and set the frame rate to 30 fps. Draw a circle on the stage with a width and height of 100 pixels and convert it to a symbol with its registration point in the middle. Name it anything you like but make sure you 'export for ActionScript' and type "Ball" as the identifier and "Ball" in the "AS 2.0 class:" field.

Once you've done that you can delete it from the stage - just make sure that it's still in your library.

Step 2 - the Ball class

Next step is to sort out the code that makes your ball movieclip behave like a ball. Time to ask yourself what a ball needs to work... are you thinking yet? I'm not going to help you if you're not thinking! Here's the minimum you'll need for the class:

  • variables to hold information describing the current state of the ball (x/y position, radius and mass)
  • variables to hold the temporary positions of balls whilst we're looking for collisions
  • functions to move and draw the ball
  • function to deal with the ball if it is heading off the stage
  • function to see if this ball is hitting any other balls
  • function to determine how the balls react when they hit

A point to note is that you want to make sure that you only check for collisions between each pair of balls once - ie. 3 balls = 3 collision checks each frame. Seems obvious though rookies often forget to implement this.

Follow this link to see my basic Ball class: Ball.as

For those that just want the good stuff... here's the code that deals with the reaction between the balls...

Actionscript:
  1. function ballBallReaction(b1:Ball, b2:Ball, dist:Number, xdiff:Number, ydiff:Number):Void {
  2.         // params
  3.         //    b1 - first ball in collision
  4.         //    b2 - second ball in collision
  5.         //    dist - distance between the middle of the two balls
  6.         //    xdiff - diff between balls on the x axis
  7.         //    ydiff - diff between balls on the y axis
  8.  
  9.         // This function is where the billiard goodness takes place.
  10.         // It's physics madness... I'll explain the bits I think I understand
  11.  
  12.         // find the angle between the balls
  13.         var angle = Math.atan2(ydiff, xdiff);
  14.  
  15.         var cosa = Math.cos(angle);
  16.         var sina = Math.sin(angle);
  17.  
  18.         // find the current linear momentum on each axis for each ball
  19.         // I think this rotates the coordinate system so that we can
  20.         // determine a 2 dimensional collision
  21.         var vx1p = cosa * b1.xmov + sina * b1.ymov;
  22.         var vy1p = cosa * b1.ymov - sina * b1.xmov;
  23.         var vx2p = cosa * b2.xmov + sina * b2.ymov;
  24.         var vy2p = cosa * b2.ymov - sina * b2.xmov;
  25.  
  26.         // P = momentum?
  27.         // V = velocity?
  28.         var P = vx1p * b1.mass + vx2p * b2.mass;
  29.         var V = vx1p - vx2p;
  30.  
  31.         vx1p = (P - b2.mass * V)/(b1.mass + b2.mass);
  32.         vx2p = V + vx1p;
  33.  
  34.         // tell each ball how fast they're going on each axis
  35.         b1.xmov = cosa * vx1p - sina * vy1p;
  36.         b1.ymov = cosa * vy1p + sina * vx1p;
  37.         b2.xmov = cosa * vx2p - sina * vy2p;
  38.         b2.ymov = cosa * vy2p + sina * vx2p;
  39.  
  40.         // Work out the where the balls are colliding along the
  41.         // "Line of Action" so that we can project them far enough
  42.         // away from each other to no longer intersect
  43.         var diff = ((b1.radius + b2.radius) - dist) / 2;
  44.  
  45.         var cosd = cosa * diff;
  46.         var sind = sina * diff;
  47.  
  48.         // update their temporary positions
  49.         b1.tempx -= cosd;
  50.         b1.tempy -= sind;
  51.         b2.tempx += cosd;
  52.         b2.tempy += sind;
  53.     }

Step 3 - Growing some balls...

So lastly we need a way to populate the Stage. While I'm here... if you haven't got SEPY Actionscript editor yet, go get it. It will save you lots of time and free you from the horror that is the Flash IDE.

Go to the first frame in your .fla file and type

Actionscript:
  1. #include "main.as"

Now get your SEPY on and make a file called, you guessed it, "main.as". If this is new to you then you owe me a coke... I've just saved you a billion hours.

In the main file we need:

  • An array to keep track of all of the balls on the stage
  • A function to create a new ball
  • A function to iterate through the ball array on every frame, moving each ball (which also looks for collisions) and then renders them to the screen.

Here's what I had in my main file: main.as

If you're just interested in how I got the Ball out of the library and onto the Stage with the class attached, here it is:

Actionscript:
  1. function newBall(howMany:Number):Void {
  2.     // creates a new ball on the stage and adds it to the end
  3.     // of the allBalls array
  4.  
  5.     for (var i = 0; i <howMany; i++) {
  6.         allBalls.push(this.attachMovie("Ball", "ball_" + ballCounter++, this.getNextHighestDepth(), getStartPosition())
  7.             .init(allBalls.length, this));
  8.     }
  9. }

The trick resides in the .init() which returns a reference to our new Ball. I remember being pretty impressed when I figured this out for the first time. "this" in the code snippet above refers to the root movieclip.

Step 4 - Watch in awe!

So if all goes to plan you should end up with something like this.

Here's the .zip of everything you see here: Ball_tutorial.zip

Conclusions

This is by no means a comprehensive tutorial, simply the kind information I was looking for a few weeks ago. If this scratches your physics itch then my work here is done.

There are plenty of resources for ActionScript physics online... Kirupa.com has a great forum which helped me out here quite a bit. Also make sure you check out TONYPA's vector tutorials.

Please let me know if you find this information useful... and make sure you send links to your work through to me! For me, this is the first tiny step towards the holy grail that is Pinball!

Cheers.


« Have you met Kevin?
AddThis Social Bookmark Button

Related Posts:

Comments:

Martin Klasson said,

August 25, 2006 @ 8:48 am

Hi there.

Greatest design ever on a blog! I am not sure whether such a great programmer like you can be just as this good on design as well, or can you?

I need a help on this tutorial/sample.
I want to add gravity, so that I can apply that to this example.

I have tried, but havent got it to work. Is there an easy way to implement this at your sample?
If only gravity can be added this, than I am having my idea saved for an intro I am trying to do!

Please do email me, or reply here. Thanks!

MB said,

August 26, 2006 @ 6:11 pm

Hey Martin - thanks very much for the kind words.

I wish I could claim credit for this WordPress theme… alas, it’s not all my work. The theme is called “Quilm” and I grabbed it from http://oriol.f2o.org/qwilm-a-wordpress-theme/ - and then I played with it quite a bit to make it my own.

I do really enjoy the graphic design side of things though haven’t been doing much lately. Check out my portfolio (link in the side nav) for a few examples along these lines.

As for including gravity to the above tutorial… try adding:

[as]
this.tempy += 1;
[/as]

…directly above the checkForWalls() function call in the Ball.as class… where ‘1′ is how much gravity you wish to add on each enterFrame.

I think you’ll find that it _almost_ works… I played with adding gravity and it looks good until some of the balls creep through each other. Hopefully you or someone else will figure out what the issue is and let me know.

Cheers and good luck!

Jeroen Beckers said,

November 8, 2006 @ 4:53 am

Nice tutorial :).

You should also try out ‘ActionScript Animation: Making things move’. (Written by Keith Peeters).

Sascha said,

November 28, 2006 @ 6:04 pm

Hi,
This is an awesome Tutorial.
Thanks for that. Due to lack of Programming knowledge and time i can’t figure out how to split balls. I am on something simular like your Balls here. My Scene should start with just one large ball and end up with countless tiny bouncing and coliding balls which have been splitted into 2 pieces each time they hit the border.
Can you give me a hint how to come to a solution with that? I would really appreciate that.
Best regards

Sascha

MB said,

November 28, 2006 @ 9:46 pm

Hey Sascha - thanks for your comment.

If I was to program something similar to the project you’ve mentioned I would include something like a “BallManager” class which would look after creating and deleting balls… along with managing their depths etc.

Whilst it’s a bit hard to go into too much depth here, you need to make it so that clicking on a ball deletes it and creates two balls in it’s place - probably at 50% of the scale of the initial ball. Using your trig knowledge, project the new balls away from the center of the original.

Be careful of creating too many new balls… the Flash player wont cope with too much action.

Have a go and if you get stuck, send the code though and I’ll have a look - we’ll post the result here for everyone else to check out.

Psha said,

December 22, 2006 @ 5:03 am

Thanks a LOT, man. I was looking for examples of this exact thing, and as an added bonus you pointed me to SEPY. It was as if you knew I’d just had an outburst over the Flash GUI :)

fuzz said,

January 2, 2007 @ 9:38 am

hey dude, very nice work. What I was trying to do, working off your example is possibly get the balls to also be able to bounce based on gravity, but then once they came to a stop, other balls could bounce off them and eventually rest on each other: creating a wall of balls.

http://www.fuzzfolio.com/workarea/myBallYugop.html, check out the link, click the screen to add more balls.

Andrew said,

January 21, 2007 @ 7:29 am

Also very appreciative of this tutorial. It’s rare to see people who are so willing to share this sort of stuff with people who haven’t put in the time themselves. It’s especially generous, because it must have taken you countless hours to arrive at your level of skill. So thanks for giving us this for free.

I’ve been looking into Flash Media Server components on my course, and I’m especially interested in the SharedBall idea. I was wondering if you’d given any thought to applying the physics you’ve demonstrated into a multi user-movable balls movie. I’ve tried applying the ActionScript I know to your ball movie here, to allow users to click and drag the balls around, but I’m not getting it right. I know ActionScript generates different instance names for the myBall symbol, but I can’t work out what that instance name formula is.

Anyway, if you think it would be easy to adapt this to the example I’ve described, it would be awesome if you could help me out. I’d be very, very grateful. Best of luck with it all in the future, and thanks again.

MB said,

January 21, 2007 @ 4:25 pm

Hey Andrew - thanks for that. I have no problem sharing the knowledge… I still owe the Flash community so much for helping me out along the way that I probably should have 100 tutorials here!

The truth is that I’ve never had the opportunity to play with the Flash Media Server - though it sounds very exciting. What’s the course you’re doing (and where are you from?!?!).

I’d be more than happy to help out where I can - and hopefully I’ll be able to learn a few things along the way too. If you’d like to get some info together and email it through we can work on something together - michael [at] footloosemoose [dot] com

Cheers.

dm said,

July 24, 2007 @ 5:42 am

Hey thanks for the tutorial, your ball collision code was exactly what I have been looking for and which I found nowhere else.

Just something I noticed that might help anyone looking for more performance. Michael you have each ball checking for a collision between with itself and every other balls, this will lead to duplicate collision checks. I have my collision check in a nested loop inside my main as file.
for (var i:Number = 0; i

jf said,

August 28, 2007 @ 7:43 pm

nice tut you have there!

i’ve been trying to build further on your example.and i was wondering, if i want to attach the balls to a movieclip on the stage, what i should change exactly ?

thanx!

Michael said,

August 28, 2007 @ 8:10 pm

Hi jf - I’m more than happy to help out, but can you be a little more specific? Are you wanting to define a rectangular area on the stage in a movieclip and get the balls to bounce in there? What are you trying to do?

jf said,

August 28, 2007 @ 10:15 pm

michael, thank you for the quick response.
that is exactly what i want. i have a rectangle on the stage, and the balls should move in there, not on the stage. i tried to change the parent_mc in the init function in main.as when attaching them. but that didn’t work..

another alteration i’m working on is:

i changed the gravity by setting-> this.tempy += 1;
and the balls who are laying on the bottom should shoot up like there’s some thrust of wind blowing up. but i’m also stuck there.

yeah, i ‘m a physics n00b.. ;)

Michael said,

August 29, 2007 @ 7:24 am

Hey again, jf

From a quick look, there are a few things you’ll have to update:

If you’re wanting to make the balls as children of the rectangle, you’ll have to first create the rectangle on the stage and then update the newBall function in Main.as - instead of this.attachMovie(…) you’d do something like myRectangle.attachMovie(…). Also make sure the random start position is within the parent rectangle.

The next thing is to update the checkForWalls() function in Ball.as. Probably the best thing to do here is, instead of using Stage.width/height etc, change it to _parent.width and _parent.height… this way it’s more flexible and will automatically update if you change the dimensions of the parent rectangle.

I think that’s all you should have to do. If you’re still stuck, email me through what you’ve got and I’ll take a quick look at it. michael [ at ] footloosemoose [ dot ] com

Cheers and good luck!

Easy Only! Glog » Blog Archive » Ball Physics said,

September 8, 2007 @ 10:01 am

[…] van Mol on bouncing balls off vectors Micheal Battle on bouncing balls off other balls Emanuele Feronato on texture mapping on […]

cb said,

October 10, 2007 @ 9:12 am

this is great. thanks! i’m working on a shakeable snowglobe like the one here: http://ww12.e-tractions.com/snowglobe/globe.htm

i’ve got the gravity, friction, and restitution set for the movie, but still need to figure out how to put these bouncing balls (or snow) into the cnowglobe movieclip. any way you could expand on the myRectangle.attach movie(…)? i’m really a novice at this and am doing my best to fumble through tutorials and actionscripting.

Thanks!

iShwaR said,

October 23, 2007 @ 8:44 pm

Hi Michael…

Surely if words could describe your work… Its amazing… and the kind of description against each piece of code… it ROCKS….!!!

Though I haven’t completely read your code, wanted to ask you a couple of things….

1.> How easy is it to use this code for making a game such as pool.

2.> Most of such ball collision code that I have searched on the web has this problem of the balls getting stuck with each other… maybe at high speeds or multiple angle of collision at the same time… I haven’t seen it happening with your code.. but does your code take care of it…

Thanks,
-iShwaR

Michael said,

October 23, 2007 @ 9:15 pm

Hi iShwaR

Thanks for your comment - I’m really glad you’re enjoying the site!

The first comment that I’ll make here is that the code in this tutorial is referred to as ‘frame-based’ which means that the balls only look for collisions onEnterFrame (~30 times each second). Whilst this may be fine for a wide variety of uses, as soon as the balls start to move faster than the particles they’re checking for collisions against, there’s a chance that they’ll jump over them completely.

The alternative to frame-based is ‘time-based’ and involves a greater understanding of physics, vectors, trigonometry etc. The topic goes a little further than my math skills allow, but I’d encourage you to look into that if you’re interested in making a pool game.

If you’re into ActionScript 3, I suggest you check out APE and use their framework to integrate the physics element of whatever you’re interested in building. Albeit currently in beta release, it’s a pretty awesome project and I’ve found it pretty easy to get into. Check out my other post for links and a quick demo.

So, to answer you questions - I’m pretty sure that this code wont be suitable for anything that requires a high degree of robustness or accuracy - but I encourage you to check it out, build on it where possible and share your results with the rest of us! :)

Best of luck mate,

Michael.

iShwaR said,

November 12, 2007 @ 11:25 pm

Hi Michael…

I noticed with an updateAfterEvent() called within the function called by setInterval()… the performance of the flash movie becomes very smooth… but if you move your mouse while the movie is playing the animation starts to jerk… heres my code…

I have a linkage id “ball_mc” in my library for my ball graphic… and movie plays @ 24fps.
————-
var depth = 0;
var balls = 5;
var speed = 1;
var ball_arr:Array = new Array();
for (var i = 0; i 500) {
ball._x = 500 - ball._width / 2;
ball.vx = -ball.vx;
} else if (ball._x + ball._width / 2 500) {
ball._y = 500 - ball._height / 2;
ball.vy = -ball.vy;
} else if (ball._y + ball._height / 2

Michael said,

November 13, 2007 @ 6:22 am

Hey iShwaR - email me and I’ll see if I can help out…

michael [at symbol] footloosemoose [period] com

Marc said,

January 18, 2008 @ 3:42 am

Hi Michael,
What a fantastic tutorial. This is exactly what I need, but unfortunately I am a rank amateur, not an intermediate Actionscripter. I am a science teacher who has been frustrated by the fact that all the physics simulations on the market are in 2D while the kids I teach are used to sophisticated games in 3D. I have been doing simple Flash animations for a while but have just started to use action script and have recently achieved a passable single ball bouncing around a box in 3D. OK, not quite the sophistication of yours, but one step at a time!
I assume it would be possible to extend your code to take into account positions, vectors and momentum along a z axis to develop your animation into 3D. The layering might be a problem but I would think that any 2 balls intersecting along the x and y axis could swap layer positions if appropriate according to their relative z positions??? If this could be done, it would be possible to do brilliant physics simulations of Kinetic Theory of Gases, Ideal Gas Laws, Brownian Motion, Nuclear Fission, Chemical Reactions, Rates of Reaction and probably loads more. Why this hasn’t been done before is beyond me – I presume all the best programmers are in the games industry where there’s a bit of money!!
This is probably way beyond me, but I am crazy enough to try anything! Unfortunately my understanding is so low at the moment that I have no idea how to reconstruct the animation using your instructions and the code shown, so I tried downloading the zip file. If I could play around with the code and see what it does, I could start to get my head round what it all means (maybe). I have Flash MX 2004 and it will not open the ball_tutorial, refusing it as an unexpected file format. Have you got any suggestions?
Cheers
Marc

Michael said,

January 21, 2008 @ 5:26 am

Hi Marc

Quite a few questions in there, but I’ll have a go. Last question first, the .fla is probably in Flash 8 format. We’re now up to Flash CS3 (and ActionScript 3 - AS3) so it’s time for you to upgrade! If that’s not a possibility, you should find that the above code works fine with your version, you’ll just have to put it together yourself.

As for the 3D ideas, I think the community would really like to see that! First step is to get familiar AS3 as it’s about 10x faster and you’ll need that speed for your more complex simulations. There’s really no way around this so get a book or something and get up to speed.

Once that’s out of the way, I’d recommend looking at a code library like Papervision3D - http://blog.papervision3d.org/ - (you’ll see that I mention it quite often on this blog). That will take care of all the 3D stuff for you so that you can just focus on your algorithms.

You’ve got quite some learning ahead of you but don’t let that dissuade you. My opinion is that Flash is still the quickest and easiest format to achieve you objectives… and it’s web ready and cross platform! Your other option is processing - http://www.processing.org/ - (a good choice if you already know java - and it’s very fast).

Best of luck with it.

Nohama napevno v oblacich <br> Feet firmly on the cloud » Blog Archive » It needs balls, man said,

February 6, 2008 @ 11:09 am

[…] to Michael Battle, his class and tutorial was such a big help to […]

winxalex said,

March 22, 2008 @ 3:28 am

All that is fine for low speeds. If speed is high one ball will pass thru the another and will be not wise to back balls to half passed(intersected) distance. Prediction come here…..

winxalex said,

March 22, 2008 @ 3:46 am

You are right.

winxalex said,

March 22, 2008 @ 5:41 am

little optimization. Check should start from bid+1 and no need of if statement

for (var i = this.bid+1; i this.bid) {}

RSS feed for comments on this post · TrackBack URI

Leave a Comment



« Have you met Kevin?