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.
onClipEvent (load) {
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[15] will be equal to 0 or 1, depending if the box hits the ball at 15 degrees, array[7] 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!