http://denvish.net/u..1150395360_angle.php
It works great so long as the sphere is not completely surrounded by land. Which you shouldnt have happen in a game anyway.
NOTE: For purposes of a demonstration, the edge is divided into 360 segments. This would not be practical for a use in a game as that is a heavy loop for flash, so in a game it would be more practical to set it to a much lower number.
So the code. Don't be alarmed at the immense complexity and mathematical difficulty of the script.
onClipEvent (load) {
r = _width/2;
seg = 360;
}
onClipEvent (enterFrame) {
_x = _root._xmouse;
_y = _root._ymouse;
var nmbr = 0;
xval = 0;
yval = 0;
for (i=1; i<seg; i++) {
var tx = _x+r*Math.sin(i*(360/seg)*(Math.PI/180));
var ty = _y-r*Math.cos(i*(360/seg)*(Math.PI/180));
if (_root.land.hitTest(tx, ty, true)) {
nmbr++;
xval += tx;
yval += ty;
}
}
if (nmbr>0) {
_root.arr._x = xval/nmbr;
_root.arr._y = yval/nmbr;
_root.arr._rotation = Math.atan2(_x-xval/nmbr, _y-yval/nmbr)/(Math.PI/180)*-1+90;
_root.arr._visible = true;
} else {
_root.arr._visible = false;
}
}
Ok so I lied about the complexity of it. So what exactly does it do? It seems simple but is very powerful. Let's look at it line by line.
onClipEvent (load) {
r = _width/2;
seg = 360;
}
r is the radius of the circle. Seg is the amount of points on the circle we are going to check. I did 360 for demonstration purposes.
onClipEvent (enterFrame) {
_x = _root._xmouse;
_y = _root._ymouse;
var nmbr = 0;
xval = 0;
yval = 0;
this drags the circle, and initiates some key temporary variables. nmbr is the amount of points colliding with the wall. xval and yval will be used later to find the average of the points hitting the wall, the center so to say.
for (i=1; i<seg; i++) {
var tx = _x+r*Math.sin(i*(360/seg)*(Math.PI/180));
var ty = _y-r*Math.cos(i*(360/seg)*(Math.PI/180));
if (_root.land.hitTest(tx, ty, true)) {
nmbr++;
xval += tx;
yval += ty;
}
}
this for loop chacks the points on the circle against the wall. tx and ty are temporary variables used to represent the x and y of points on the circumference of the circle. It uses a little trig to find the values, there's another AS tutorial on that... look it up. Then it does a shapeflag collision detection between the edge point and the ground. If it's hitting, it increases the NMBR variable, and adds the x and y of the edge point to the xval and yval variables
if (nmbr>0) {
_root.arr._x = xval/nmbr;
_root.arr._y = yval/nmbr;
_root.arr._rotation = Math.atan2(_x-xval/nmbr, _y-yval/nmbr)/(Math.PI/180)*-1+90;
_root.arr._visible = true;
} else {
_root.arr._visible = false;
}
and the last part of the code. Rather simple. _root.arr is the MC used to show the normal of the wall where the ball is hitting. It places it's _x and _y at the average of the points that are colliding with the wall, and then finds the direction using arctangents from that point to the center of the ball. It's rather simple. Finding the average of the points colliding with the wall will find a point that is basicall in the center of these points.
So now what can you do with this normal? Well, for starters it would be a useful tool for bouncing objects on an art based map. You can also use it to rotate a character so he's aligned with the slope of the ground. It could help in making a pinball game, and many other circumstances.
NOTE: When i originally was thinking up how to do this, i thought of taking the midpoint of the line made by connecting the points where the sphere enters and exits hitting the ground, where it collides with the edges of the ground. But, it would still have to loop through all the points, so this method is better.
Oh ya, and
AS: Main