Forum Topic: AS: Art-based normal detection

(2,373 views • 20 replies)

This topic is 1 page long.

<< < > >>
None

Glaiel-Gamer

Reply To Post Reply & Quote

Posted at: 6/15/06 04:13 PM

Glaiel-Gamer NEUTRAL LEVEL 27

Sign-Up: 12/28/04

Posts: 8,053

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


None

dELtaluca

Reply To Post Reply & Quote

Posted at: 6/15/06 04:23 PM

dELtaluca LIGHT LEVEL 20

Sign-Up: 04/16/04

Posts: 5,548

pretty much the same way i have mine, only ofcourse not 360 points

"Don't be alarmed at the immense complexity and mathematical difficulty of the script."

your sarcasm always seems to amaze me :D

the only thing i would tend to do differently is when working with a large circle like this, to test smaller circles aswell incase of a thin piece of land, to better estimate the normal in all occasions

My social worker says im special!

BBS Signature

Happy

Cema

Reply To Post Reply & Quote

Posted at: 6/15/06 04:31 PM

Cema LIGHT LEVEL 13

Sign-Up: 07/28/05

Posts: 1,941

Very nice tutorial Glaiel. Easy to understand. Only the best from you!

:)

BBS Signature

None

liaaaam

Reply To Post Reply & Quote

Posted at: 6/15/06 04:34 PM

liaaaam NEUTRAL LEVEL 22

Sign-Up: 12/11/04

Posts: 14,536

Nice tutty, but why would you need to know the normal? Can you give an example of where you would use the normal in a 2D game?


None

Glaiel-Gamer

Reply To Post Reply & Quote

Posted at: 6/15/06 04:37 PM

Glaiel-Gamer NEUTRAL LEVEL 27

Sign-Up: 12/28/04

Posts: 8,053

At 6/15/06 04:34 PM, liaaaam wrote: Nice tutty, but why would you need to know the normal? Can you give an example of where you would use the normal in a 2D game?

i did

wall bouncing, pinball, rotating the character to the ground, etc.


None

JD77

Reply To Post Reply & Quote

Posted at: 6/15/06 04:42 PM

JD77 NEUTRAL LEVEL 17

Sign-Up: 03/30/05

Posts: 1,059

Nice lol, Khao had circle to line hittesting which kinda did the same. even thought your code is more simple.

*User Page under construction*

BBS Signature

None

Blaze

Reply To Post Reply & Quote

Posted at: 6/15/06 04:43 PM

Blaze LIGHT LEVEL 22

Sign-Up: 08/04/05

Posts: 6,989

kickass

I still dont see me using this sort of stoff on a game for quite a while.


None

JD77

Reply To Post Reply & Quote

Posted at: 6/15/06 05:08 PM

JD77 NEUTRAL LEVEL 17

Sign-Up: 03/30/05

Posts: 1,059

At 6/15/06 04:43 PM, Darkfire_Blaze wrote: kickass

I still dont see me using this sort of stoff on a game for quite a while.

Its really usefull when it comes to platformers lol. This can be used to get the rotation of a character.

*User Page under construction*

BBS Signature

None

BoMToons

Reply To Post Reply & Quote

Posted at: 6/15/06 05:14 PM

BoMToons LIGHT LEVEL 29

Sign-Up: 11/29/05

Posts: 1,903

Good for accurately calculating the vector a character would realisticically take when jumping off of a slope too...like in fancy pants...excellent tutorial.

(was this practice for your sonic game?)


None

Glaiel-Gamer

Reply To Post Reply & Quote

Posted at: 6/15/06 05:18 PM

Glaiel-Gamer NEUTRAL LEVEL 27

Sign-Up: 12/28/04

Posts: 8,053

At 6/15/06 05:14 PM, bomtoons wrote: (was this practice for your sonic game?)

no.. that boss had no slopes anyway.

I was going to use it for a pinball game but then i realized all the possibilities... like reflections and all that good stuff.


None

23450

Reply To Post Reply & Quote

Posted at: 6/15/06 06:19 PM

23450 LIGHT LEVEL 27

Sign-Up: 05/28/03

Posts: 7,304

man, i was so close to making this engine one time. I had everything working except i could not get the arrow to be direcly in the middle, it was always at the edge of the ball. Oh wells.

Halo 3 GamerTag: XCornDawgX


None

Glaiel-Gamer

Reply To Post Reply & Quote

Posted at: 6/15/06 06:35 PM

Glaiel-Gamer NEUTRAL LEVEL 27

Sign-Up: 12/28/04

Posts: 8,053

http://denvish.net/u..1150404838_angle.php

I made a slight modification to the engine

onClipEvent (load) {
r = _width/2;
seg = 360;
cvt = Math.PI/180;
xspeed = 0;
yspeed = 0;
_root.arr._visible = false;
}
onClipEvent (enterFrame) {
_x += xspeed;
_y += yspeed;
yspeed += 1;
var nmbr = 0;
xval = 0;
yval = 0;
for (i=1; i<seg; i++) {
var tx = _x+r*Math.sin(i*(360/seg)*(cvt));
var ty = _y-r*Math.cos(i*(360/seg)*(cvt));
if (_root.land.hitTest(tx, ty, true)) {
nmbr++;
xval += tx;
yval += ty;
}
}
if (nmbr>0) {
_root.arr._rotation = Math.atan2(_x-xval/nmbr, _y-yval/nmbr)/(cvt)*-1+90;
_root.arr._x = _x-r*Math.sin((_root.arr._rotation+90)*cvt
);
_root.arr._y = _y+r*Math.cos((_root.arr._rotation+90)*cvt
);
px = _x-r*Math.sin((_root.arr._rotation+90)*cvt
);
py = _y+r*Math.cos((_root.arr._rotation+90)*cvt
);
}
if (nmbr>0 && nmbr<seg) {
ix = ((px-_x)/r)*-1;
iy = ((py-_y)/r)*-1;
speed = Math.sqrt(xspeed*xspeed+yspeed*yspeed)*.9;
//speed<=1?speed=0:0
var spa = Math.atan2(xspeed, yspeed)/(cvt)*-1+90;
var nr = 2*(_root.arr._rotation-spa)+spa-180;
_root.arr._rotation = nr-180;
xspeed = Math.sin((nr+90)*cvt)*speed;
yspeed = -Math.cos((nr+90)*cvt)*speed;
while (_root.land.hitTest(px, py, true)) {
_x += ix;
_y += iy;
px = _x-ix*r;
py = _y-iy*r;
}
}
//Math.abs(xspeed)<.5?xspeed=0:0
//Math.abs(yspeed)<.5?yspeed=0:0
_root._x = 275-_x;
_root._y = 200-_y;
}

//commented code meanns i took it out cause it didnt work right but was going to find out how to make it work later.


None

dELtaluca

Reply To Post Reply & Quote

Posted at: 6/15/06 06:55 PM

dELtaluca LIGHT LEVEL 20

Sign-Up: 04/16/04

Posts: 5,548

in case anyone is interested, here is a nicely encapsulated prototyped function i have written and use, to the same effect as this (slight differences)

mine does like i said earlier, sub circles within the larger circle to get an accurate normal on thin terrain like you can see in demo on top right, and in this, does a total of 160 hittests

_global.rad = Math.PI/180;
_global.deg = 1/rad;
_global.pi2 = Math.PI*2;
var inc:Number = pi2/32;

MovieClip.prototype.findNormal = function(targ:MovieClip):Array
{
var nx:Number = 0;
var ny:Number = 0;
var nn:Number = 0;
for(var r:Number = 1; r<10; r+=2)
{
for(var ang:Number = 0; ang<pi2; ang+=inc)
{
var tx:Number = r*Math.sin(ang);
var ty:Number = r*Math.cos(ang);
if(targ.hitTest(this._x+tx,this._y+ty,true
))
{
nx += tx/r;
ny += ty/r;
++nn;
}
}
}
if(nn==0) ny = 1;
else
{
var d:Number = 1/Math.sqrt(nx*nx+ny*ny);
nx *= d;
ny *= d;
}
return new Array(nx,ny);
}

http://denvish.net/u..0406115_testnorm.php

but ofcourse, like anything, numbers can be reduced to give faster, but less accurate approximations

My social worker says im special!

BBS Signature

None

dELtaluca

Reply To Post Reply & Quote

Posted at: 6/15/06 07:01 PM

dELtaluca LIGHT LEVEL 20

Sign-Up: 04/16/04

Posts: 5,548

ah yeh, my function returns a normalised normal vector, so in my sample, i draw the blue line by

var n:Array = mc.findNormal(land);
mc.clear();
mc.lineStyle(1,0xffff,100);
mc.lineTo(20*n[0],20*n[1]);

My social worker says im special!

BBS Signature

None

NegativeONE

Reply To Post Reply & Quote

Posted at: 6/15/06 07:13 PM

NegativeONE DARK LEVEL 45

Sign-Up: 02/15/03

Posts: 7,451

At 6/15/06 04:34 PM, liaaaam wrote: Nice tutty, but why would you need to know the normal? Can you give an example of where you would use the normal in a 2D game?

I used it to help with bullet ricochets in this old engine of mine:
http://www.negativeflash.com/prey6b.html
(Still uploading at time of post, so it might be a broken link for a couple of minutes yet)

BBS Signature

None

NegativeONE

Reply To Post Reply & Quote

Posted at: 6/15/06 07:16 PM

NegativeONE DARK LEVEL 45

Sign-Up: 02/15/03

Posts: 7,451

At 6/15/06 07:13 PM, NegativeONE wrote: (Still uploading at time of post, so it might be a broken link for a couple of minutes yet)

...
Hrm, nevermind, I guess. Damn hosting woes.
Anyway, I used a different method to go about finding the normal, but both seem to work well.

BBS Signature

None

rabidbaboy

Reply To Post Reply & Quote

Posted at: 6/15/06 07:57 PM

rabidbaboy EVIL LEVEL 07

Sign-Up: 08/21/05

Posts: 699

damn.i wish i could code like that.
nice one.


None

shazwoogle

Reply To Post Reply & Quote

Posted at: 6/25/06 02:37 AM

shazwoogle NEUTRAL LEVEL 11

Sign-Up: 09/27/04

Posts: 2,681

hey that looks nice :D i was gonna make a engine like this sooner or latter :P


None

Toast

Reply To Post Reply & Quote

Posted at: 6/25/06 06:26 AM

Toast DARK LEVEL 09

Sign-Up: 04/02/05

Posts: 8,921

At 6/15/06 04:23 PM, -dELta- wrote: "Don't be alarmed at the immense complexity and mathematical difficulty of the script."

your sarcasm always seems to amaze me :D

Lol @ shvitzer fight.


None

dELtaluca

Reply To Post Reply & Quote

Posted at: 6/25/06 06:35 AM

dELtaluca LIGHT LEVEL 20

Sign-Up: 04/16/04

Posts: 5,548

At 6/25/06 06:26 AM, -Toast- wrote:
At 6/15/06 04:23 PM, -dELta- wrote: "Don't be alarmed at the immense complexity and mathematical difficulty of the script."

your sarcasm always seems to amaze me :D
Lol @ shvitzer fight.

shvitzer?

My social worker says im special!

BBS Signature

None

Inglor

Reply To Post Reply & Quote

Posted at: 6/25/06 06:53 AM

Inglor NEUTRAL LEVEL 17

Sign-Up: 01/26/03

Posts: 10,948

At 6/25/06 06:35 AM, -dELta- wrote: shvitzer?

that's showoff in hebrew,


All times are Eastern Standard Time (GMT -5) | Current Time: 04:14 AM

<< Back

This topic is 1 page long.

<< < > >>
You need a Grounds Gold Account to post on the NG BBS! If you don't have one, click here to sign up now! It's fast, free, and easy — and opens up tons of great NG features!