 00:00
00:00 As :ball Angle Hittest And Bouncing

6,358 Views | 21 Replies

AS Main : One thread to rule them all!

Hi, in this tutorial, I will fully explain how to check angle hittest with a ball, how to make it bounce perpendicularly to the thing it touches, and how to make it bounce using physic laws to make it more realistic.

You should know some medium ActionScript to fully understand how this works.

Youl will end up with something like THIS

First, make your circle movieclip. Make sure the registration point is in the perfect middle. To do so, I draw a circle into a movieclip, then go with the properties and place the circle in the middle.
W: 30 H:30 X:-15 Y:-15

Now we need something that will hit the ball, draw a ground or whatever you want inside a movieclip and name it whatever you want. I named mine "box" for this tutorial.

Now open the ball's(lol) action panel to write down the AS.

r = _width/2; // radius of the ball
xspeed = 0; //xspeed, set to 0 to start
yspeed = 0; //yspeed, set to 0 to start
gravity = .05; //gravity force, change to whatever you want. 0 for no gravity
array = new Array(360);//create an array that will hold data for the 360 degrees hitTest
}

Now we need to detect the hitTest 360 degrees around the ball.
onClipEvent (enterFrame) {
for (i=0; i<360; i += 5) {// loop from 0 to 360 with a gap of 5 degrees between each point
x = _x+r*Math.cos(i/180*Math.PI);
//gets the X position on the perimeter of the ball at this angle
y = _y-r*Math.sin(i/180*Math.PI);//same thing with the Y position
_root.box.hitTest(x, y, true) ? array[i]=1 : array[i]=0;
//detects if there is collision between box and the point we just found, If true, will store
//true (1) into the array at the angle we are, else will store false (0)
}

Ok now our array has 1 or 0 at each 5 variables, for EX: array will be equal to 0 or 1, depending if the box hits the ball at 15 degrees, array will be undefined, because we are testing at every 5 degrees.

Now that we have this, it's time to detect at wich angle we are hit!

strt = 0;
end = 0;
//makes the variables start and end equal to 0, these variables will tell at
//wich angle the collision starts and ends
for (i=0; i<360; i += 5) {//loop again at every 5 degrees into the array
!last and array[i] ? strt=i : 0;
last and !array[i] ? end=i : 0;
last = array[i];
}
strt>end ? angle=(strt+end)/2+180 : angle=(strt+end)/2;

Ok this is getting more complex so I'm not commenting directly in. We need to check where the collision starts and where it ends. It checks if the last degree is 0 (false) and the current degree is 1 (true) it sets the variables strt to the current angle. Same thing for finding the end, it checks if this degree is 0 and the last one was 1, if true it will set the end to the current degree. Then at the end of the loop it stores the the current angle data (0 or 1) into the variable last that will be used for the next loop.

Now we need to take the middle between the start and end of collision. But there is a problem, if it starts at 350 degrees and end at 30 degrees, it's doing weird things. To fix this we have this script
strt>end ? angle=(strt+end)/2+180 : angle=(strt+end)/2;
//if strt is bigger than end, calculates the real angle, else, calculate the angle normally

Now, the action when we hit the box.
yspeed += gravity;//adds gravity to the yspeed
speed = Math.sqrt(xspeed*xspeed+yspeed*yspeed);//c
alculates the speed of the ball
if (strt != end) {//if there is a hit
xspeed = -speed*Math.sin((angle+90)/180*Math.PI);
//calculates the xspeed at the correct bouncing angle
yspeed = -speed*Math.cos((angle+90)/180*Math.PI);
//same thing for yspeed
}

Only 1 thing left.
_y += yspeed;
_x += xspeed;//makes the ball move
}

Now that's the first version, it makes the ball bounce perpendicularly to the surface it touches. Wich isn't realistic, but can be ok for a game if it's how it's supposed to bounce but normally a ball coming at 45 degrees on a flat surface should bounce at an angle of 135 degrees.

To correct this, we need to calculate the current angle, then the angle of the collision, and calculate at wich angle should the ball bounce.
Go back a litte in your actionscript and add the script in bold
yspeed += gravity;
angle2 = (Math.atan2(yspeed, xspeed))*180/Math.PI;//calculates the current angle
angle = angle*2+angle2;//calcualtes the bouncing angle

speed = Math.sqrt(xspeed*xspeed+yspeed*yspeed);

Now you got realistic movement! Great!

HERE IS A GREAT EXAMPLE

That is all for the tutorial. Thanks for reading it. Please leave comments, example files you managed to do with this tutorial, corrections below.

Thanks!

Response to As :ball Angle Hittest And Bouncing 2005-12-18 17:53:01

Forgot to say, this code may have bugs, especially in close spaces or touching 2 sides it may go trough the ground or things like that. But I've made my best to remove all the bugs.

Response to As :ball Angle Hittest And Bouncing 2005-12-18 17:56:37

its alright. Very buggy.
Generally good work

Response to As :ball Angle Hittest And Bouncing 2005-12-18 18:00:55

Yeah, it's alright.

One thing though, when writing a tutorial it might be a good idea to update stuff such as and to &&. But that's just my humble opinion. Response to As :ball Angle Hittest And Bouncing 2005-12-18 18:06:13

Thats pretty good. The reason it falls through sometimes is that the movie does not have enoguh time to check for the hittest, and the ball is moving more than the frames per second.
Maybe try upping the frames per second or adding a maximum speed

Response to As :ball Angle Hittest And Bouncing 2005-12-18 18:13:42

At 12/18/05 05:56 PM, Ninja-Chicken wrote: its alright. Very buggy.
Generally good work

Thanks Mr. Everything Sucks.

<3
At 12/18/05 06:00 PM, Santazien wrote: Yeah, it's alright.

One thing though, when writing a tutorial it might be a good idea to update stuff such as and to &&. But that's just my humble opinion.

it's the same thing ^^
I've always used and and or so I'm more using them

At 12/18/05 06:06 PM, Naister wrote: Thats pretty good. The reason it falls through sometimes is that the movie does not have enoguh time to check for the hittest, and the ball is moving more than the frames per second.
Maybe try upping the frames per second or adding a maximum speed

Its already at 40 fps and also the reasons that may screw it up is because it's going too fast so use a low gravity (-.5 to .5) and draw with a size of 10 so it will hit more.

When I draw at size 10 i nearly got no problem!

Response to As :ball Angle Hittest And Bouncing 2005-12-18 18:21:44

At 12/18/05 06:13 PM, Christmas_Khao wrote: it's the same thing ^^
I've always used and and or so I'm more using them

Yeah I know, I don't really care what you use personally, it's just that people reading these tutorials might not understand that they are the same thing. That's why it's a good idea to keep to the most up-to-date methods when writing tutorials. It's not like it's a really bad thing though =) Response to As :ball Angle Hittest And Bouncing 2005-12-18 18:25:49

unpractical. 360°? Anymore than 3 balls will make it run at 1 FPS. Delta's example of this was much better. Response to As :ball Angle Hittest And Bouncing 2005-12-18 18:36:15

At 12/18/05 06:25 PM, Glaiel_Gamer wrote: unpractical. 360°? Anymore than 3 balls will make it run at 1 FPS. Delta's example of this was much better.

yeh, this way is quite silly, its alot faster, better, easier to just compare squared distance with squared radius

i.e. for each ball to each other ball

xd = ball1._x-ball2._x;
yd = ball1._y-ball2._y;
if(xd*xd+yd*yd <= ball1.rs+ball2.rs) //hitting eachover

where rs = the radius of the circle squared Response to As :ball Angle Hittest And Bouncing 2005-12-18 18:37:57

At 12/18/05 06:36 PM, -dELta- wrote:
At 12/18/05 06:25 PM, Glaiel_Gamer wrote: unpractical. 360°? Anymore than 3 balls will make it run at 1 FPS. Delta's example of this was much better.
yeh, this way is quite silly, its alot faster, better, easier to just compare squared distance with squared radius

i.e. for each ball to each other ball

xd = ball1._x-ball2._x;
yd = ball1._y-ball2._y;
if(xd*xd+yd*yd <= ball1.rs+ball2.rs) //hitting eachover

where rs = the radius of the circle squared

lol im fucking dumb, i just realised youre not doing circle-circle collisions :X nevermind what i said, anways..... yeh what he said Response to As :ball Angle Hittest And Bouncing 2005-12-18 18:39:57

oh fun :D

Response to As :ball Angle Hittest And Bouncing 2005-12-18 18:40:11

At 12/18/05 06:36 PM, -dELta- wrote: if(xd*xd+yd*yd <= ball1.rs+ball2.rs) //hitting eachover

even so it would have to be
if(xd*xd+yd*yd <= (ball1.rs+ball2.rs)*(ball1.rs+ball2.rs)) Response to As :ball Angle Hittest And Bouncing 2005-12-18 18:41:03

ahh.. i see now, what i did in my thing like this, i didnt take into account the radius of the circle, only its position and traced a ray through its velocity so that even if its moves at 200pixels/frame it still knows when it collides, however using bitmaps i can easily determine if it hits the terrain instantly with one hittest, i also used vector math in finding the reflected vector rather than angles and everything Response to As :ball Angle Hittest And Bouncing 2005-12-18 20:17:35

At 12/18/05 06:25 PM, Glaiel_Gamer wrote: unpractical. 360°? Anymore than 3 balls will make it run at 1 FPS. Delta's example of this was much better.

I didn't looked at delta's thing but as I read the posts after you I believe he was making hitest between balls, that is between ball and irregular ground.

Plus, it doesn't lag at all with a lot of balls.

Plus I found a way to annihilate all bugs (SHOULD HAVE THOUGHT OF THIS BEFORE DUMB ME!)

add the parts in bold in that script where it belongs
onClipEvent (enterFrame) {
for (i=0; i<360; i += 5) {
x = _x+xspeed+r*Math.cos(i/180*Math.PI);
y = _y+yspeed-r*Math.sin(i/180*Math.PI);
_root.box.hitTest(x, y, true) ? array[i]=1 : array[i]=0;
}

Here is an example with 5 balls! Now glaeil make excuses please :)
also this example is with the fixed code

Response to As :ball Angle Hittest And Bouncing 2005-12-18 20:22:21

Tasty, I'm sure cutting down to about 24 points around the circle from the full blown 360 couldnt do any hard though could it?

Response to As :ball Angle Hittest And Bouncing 2005-12-18 20:27:42

At 12/18/05 08:22 PM, T-H wrote: Tasty, I'm sure cutting down to about 24 points around the circle from the full blown 360 couldnt do any hard though could it?

it isn't 360, look at the loop it has i+=5, it's only 72 points

Response to As :ball Angle Hittest And Bouncing 2005-12-18 20:33:26

At 12/18/05 08:27 PM, Christmas_Khao wrote:
At 12/18/05 08:22 PM, T-H wrote: Tasty, I'm sure cutting down to about 24 points around the circle from the full blown 360 couldnt do any hard though could it?
it isn't 360, look at the loop it has i+=5, it's only 72 points

I did actually just notice that after I posted. I hate it when that happens :P

Response to As :ball Angle Hittest And Bouncing 2005-12-18 20:40:41

Nice tut... very well explained

Response to As :ball Angle Hittest And Bouncing 2005-12-18 20:42:51

At 12/18/05 08:40 PM, BobRicci wrote: Nice tut... very well explained

Thanks.

Response to As :ball Angle Hittest And Bouncing 2007-07-22 20:31:03

Hey, I read this post a little while ago, but I can't seem to stop the ball from going through the ground, I need help fixing it. =(

If you're thinking it, NO! I'm not the same person as that old black & white cartoon character.

Response to As :ball Angle Hittest And Bouncing 2008-09-22 20:21:58

You my good friend just got me 1000\$ Im not kidding. A programmer asked me to add gravity to a ball for him. Well Now I know how!! YOUR THE BEST!!!!

*Of course I have to make like 8000 more lines of coding for the rest of the game, but the rest should be simple enough since I know know what I am doing.* 