Be a Supporter!

AS: Art-based normal detection

  • 3,397 Views
  • 20 Replies
New Topic Respond to this Topic
Glaiel-Gamer
Glaiel-Gamer
  • Member since: Dec. 28, 2004
  • Offline.
Forum Stats
Member
Level 28
Game Developer
AS: Art-based normal detection Jun. 15th, 2006 @ 04:13 PM Reply

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

dELtaluca
dELtaluca
  • Member since: Apr. 16, 2004
  • Offline.
Forum Stats
Member
Level 20
Blank Slate
Response to AS: Art-based normal detection Jun. 15th, 2006 @ 04:23 PM Reply

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


using ShamelessPlug; NapePhysicsEngine.advertise();

BBS Signature
Cema
Cema
  • Member since: Jul. 28, 2005
  • Offline.
Forum Stats
Member
Level 13
Blank Slate
Response to AS: Art-based normal detection Jun. 15th, 2006 @ 04:31 PM Reply

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

:)


BBS Signature
liam
liam
  • Member since: Dec. 11, 2004
  • Offline.
Forum Stats
Member
Level 22
Blank Slate
Response to AS: Art-based normal detection Jun. 15th, 2006 @ 04:34 PM Reply

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?


Sup, bitches :)

BBS Signature
Glaiel-Gamer
Glaiel-Gamer
  • Member since: Dec. 28, 2004
  • Offline.
Forum Stats
Member
Level 28
Game Developer
Response to AS: Art-based normal detection Jun. 15th, 2006 @ 04:37 PM Reply

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.

JD77
JD77
  • Member since: Mar. 30, 2005
  • Offline.
Forum Stats
Member
Level 17
Blank Slate
Response to AS: Art-based normal detection Jun. 15th, 2006 @ 04:42 PM Reply

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
Blaze
Blaze
  • Member since: Aug. 4, 2005
  • Offline.
Forum Stats
Member
Level 22
Programmer
Response to AS: Art-based normal detection Jun. 15th, 2006 @ 04:43 PM Reply

kickass

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

JD77
JD77
  • Member since: Mar. 30, 2005
  • Offline.
Forum Stats
Member
Level 17
Blank Slate
Response to AS: Art-based normal detection Jun. 15th, 2006 @ 05:08 PM Reply

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
BoMToons
BoMToons
  • Member since: Nov. 29, 2005
  • Offline.
Forum Stats
Moderator
Level 38
Game Developer
Response to AS: Art-based normal detection Jun. 15th, 2006 @ 05:14 PM Reply

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?)

Glaiel-Gamer
Glaiel-Gamer
  • Member since: Dec. 28, 2004
  • Offline.
Forum Stats
Member
Level 28
Game Developer
Response to AS: Art-based normal detection Jun. 15th, 2006 @ 05:18 PM Reply

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.

23450
23450
  • Member since: May. 28, 2003
  • Offline.
Forum Stats
Supporter
Level 27
Blank Slate
Response to AS: Art-based normal detection Jun. 15th, 2006 @ 06:19 PM Reply

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.


BBS Signature
Glaiel-Gamer
Glaiel-Gamer
  • Member since: Dec. 28, 2004
  • Offline.
Forum Stats
Member
Level 28
Game Developer
Response to AS: Art-based normal detection Jun. 15th, 2006 @ 06:35 PM Reply

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.

dELtaluca
dELtaluca
  • Member since: Apr. 16, 2004
  • Offline.
Forum Stats
Member
Level 20
Blank Slate
Response to AS: Art-based normal detection Jun. 15th, 2006 @ 06:55 PM Reply

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


using ShamelessPlug; NapePhysicsEngine.advertise();

BBS Signature
dELtaluca
dELtaluca
  • Member since: Apr. 16, 2004
  • Offline.
Forum Stats
Member
Level 20
Blank Slate
Response to AS: Art-based normal detection Jun. 15th, 2006 @ 07:01 PM Reply

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]);


using ShamelessPlug; NapePhysicsEngine.advertise();

BBS Signature
NegativeONE
NegativeONE
  • Member since: Feb. 15, 2003
  • Offline.
Forum Stats
Member
Level 49
Game Developer
Response to AS: Art-based normal detection Jun. 15th, 2006 @ 07:13 PM Reply

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
NegativeONE
NegativeONE
  • Member since: Feb. 15, 2003
  • Offline.
Forum Stats
Member
Level 49
Game Developer
Response to AS: Art-based normal detection Jun. 15th, 2006 @ 07:16 PM Reply

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
rabidbaboy
rabidbaboy
  • Member since: Aug. 21, 2005
  • Offline.
Forum Stats
Member
Level 07
Blank Slate
Response to AS: Art-based normal detection Jun. 15th, 2006 @ 07:57 PM Reply

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

shazwoogle
shazwoogle
  • Member since: Sep. 27, 2004
  • Offline.
Forum Stats
Member
Level 11
Blank Slate
Response to AS: Art-based normal detection Jun. 25th, 2006 @ 02:37 AM Reply

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

Toast
Toast
  • Member since: Apr. 2, 2005
  • Offline.
Forum Stats
Member
Level 09
Blank Slate
Response to AS: Art-based normal detection Jun. 25th, 2006 @ 06:26 AM Reply

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.


BBS Signature
dELtaluca
dELtaluca
  • Member since: Apr. 16, 2004
  • Offline.
Forum Stats
Member
Level 20
Blank Slate
Response to AS: Art-based normal detection Jun. 25th, 2006 @ 06:35 AM Reply

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?


using ShamelessPlug; NapePhysicsEngine.advertise();

BBS Signature
Inglor
Inglor
  • Member since: Jan. 26, 2003
  • Offline.
Forum Stats
Member
Level 17
Blank Slate
Response to AS: Art-based normal detection Jun. 25th, 2006 @ 06:53 AM Reply

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

that's showoff in hebrew,