Checking Location of Entity relative to where another Entity is facing
Displaying 1-7 of 7 total.
1
Please enter a numerical value for the importance of this sticky.
Enter 0 to unsticky.
CrazyAznGamer

So I have this Player entity, and I want to check if this Enemy entity is within "line of sight" of Player entity. I have this custom face system set up like so:

321
4X0
567

Where X is the entity and the values represent where the entity is facing. Yep, that means diagonal directions.

Battle system I'm doing (for codename: FunkJuice, because I feel like it), is Real-Time. Therefore, I was wondering if there was any quick way to check line of sight for 8 directions. For me, it's conditionals vs. some math crap(probably Trigonometry) I've yet to figure out. Hope this all makes perfect sense.

Posted on 2005-12-19 19:59:29

Omni

Create an angle for each of your 8 directions (0-7).

For example, 0 = 0 degrees, 1 = 45, 2 = 90, 3 = 135, 4 = 190...

Keep in mind those are unit circle degrees (where angle=0 degrees at perfect horizontal line).



1st thing. Get the actual angle between the player and enemy. Use Arctan(

[what are the arguments for this function? Xdifference, Ydifference? try this:]

enemy.x-player.x, enemy.y-player.y).


2nd thing. Anyway, once you get the angle, then check the player's direction. First give the player a range of sight. Say, I'll say that he has a 180 degree field of version (so he's a frog or he's got a panoramic eye or something...heh).

3rd thing. Check the player's facing direction (0-7). If he's at zero, that means his orientation is zero degrees (since we said facing slot 0 = 0 degrees).

4th thing. Check the orientation of his current field with the enemy. IE, if the field of vision is 180 degrees, then his current field of view is

0 - (fieldangle/2)
0 + (fieldangle/2)

IE, he can see between -90 and +90 degrees relative to himself. (A 180 degree span).

5th thing. Check the arctan angle between the player and the enemy (what we got in step one). If the enemy is exactly at zero degrees, he'll be to the player's right. (remember, we said zero degrees = perfect horizontal line).

Anyway. If the player-enemy angle is within the current field of vision, then we can see him.

Try setting an upper and lower bound on the field of vision. Like so.

upperfieldbound = 0 + (fieldangle/2)
lowerfieldbound = 0 - (fiendangle/2)

If the player-enemy-angle is less than the upperfieldbound and greater than the lowerfieldbound, he's in our field of vision.



...A lot of steps, but shouldn't be too hard to understand. In addition, I'm not sure if Verge provides a built-in Arctan2() function, but they're very useful as they fix problems with using the original Arctan() function. (Technically there's nothing wrong with Arctan. It just has a weird angle range that isn't exactly what we need for a full 360 degree circle).

So, here's an Arctan2 function. I think I might have gotten this from Mythril, perhaps...

int Math_Atan2(int rise, int run) {
/*Rise is the y-delta, run is the x-delta. */
int t;
if (run == 0)
{
if (rise > 0) return 90;
if (rise < 0) return 270;
else return 0;
}
if (rise == 0)
{
if (run < 0) return 180;
else return 0;
}
t = atan((rise*65536)/run);

if (run > 0 && rise < 0) return t + 360;
if (run < 0) return t + 180;

return t;
}


Hope that helps.

Posted on 2005-12-19 20:38:55

CrazyAznGamer

Thanks, I was thinking of something along those lines. I just couldn't figure what Trig function to use.
But a little while ago, I figured out another way using dy/dx (aka slope) and conditionals. I'll try and implement yours as well, only instead of the mathematically correct 360 degrees, I'll implement it in the computer-scientifically impromptu 256 degrees. ;D (Should solve a few things with the strange range of the atan func as well, as well as help with speed)
I guess after that, I would check which one is faster. And use the faster method, because we all love speed. :D

EDIT: I should be saying delta x / delta y instead of dy/dx eh? Might be confused with implicit differentiation, and then, I'd have to deal with the Math Police. :(

Posted on 2005-12-19 21:54:14 (last edited on 2005-12-19 21:56:24)

Kildorf

Uhm... would it be bad of me to point out that there is a built-in atan2?

From v3vergec.txt :
int     atan2(int y, int x)

Posted on 2005-12-20 05:40:57

Omni

...
...
...
*Slaps self in face

Posted on 2005-12-20 08:58:38

CrazyAznGamer

Quote:
Originally posted by Kildorf

Uhm... would it be bad of me to point out that there is a built-in atan2?

From v3vergec.txt :
int     atan2(int y, int x)


Haha, I noticed...

Anyways, I went ahead and performed a speed test on the two different methods.
/*
// TESTING TIME CONSUMPTION OF DIFFERENT LOS CHECKING
int i, time1, time2;
timer = 0;
for(i = 0; i < 10000; i++)
{
CheckLineOfSight(i % 8, i, 10000-i);
} time1 = timer;
timer = 0;
for(i = 0; i < 10000; i++)
{
CheckLineOfSight2(i % 8, i, 10000-i);
} time2 = timer;
Exit(str(time1) + " vs. " + str(time2));
*/
This was in my system.vc.
If you were wondering what the two functions were, here they are, (Go ahead and optimize them as much as you like, but do post here if you do. ;D)
int CheckLineOfSight(int face, int dx, int dy)
{
//By way of Trigonometry...
int t = atan2(dy, dx);
if(!face) //If facing right...
if(t < 45 || t > 315)
return 1;
int r = face * 45;
if(t > r - 45 && t < r + 45) return 1;
return 0;
}

int CheckLineOfSight2(int face, int dx, int dy)
{
//By way of Slope and Conditionals...
if(!dx)
{
if(dy >= 0 && face == FACE_S) return 1;
if(dy < 0 && face == FACE_N) return 1;
return 0;
}
if(!dy)
{
if(dx >= 0 && face == FACE_E) return 1;
if(dx < 0 && face == FACE_W) return 1;
return 0;
}
int m = dy << 8 / dx; //slope in 8.8 fixed

if(m < 256 && m > -256) //E or W
{
if(dx >= 0 && face == FACE_E) return 1;
if(dx < 0 && face == FACE_W) return 1;
return 0;
}
if(m < -256 || m > 256) //N or S
{
if(dy >= 0 && face == FACE_S) return 1;
if(dy < 0 && face == FACE_N) return 1;
return 0;
}
return 0;
}
Again, thanks to you Omni.

Finally, the test results are...
Time (100ths of a sec) it takes to exec functions X times
time(TrigFunc) |time2(Conditionals)
1000x 10000x |1000x 10000x
----- ------ |----- ------
2 16 |1 12
2 15 |1 12
1 16 |1 12
2 15 |1 12
2 15 |2 12

As expected, the conditional function was faster. HOWEVER, it's very inflexible =(. Besides, the Trig one looks cooler.
Both functions execute at a rate that is pretty insubsequential to speed. I'll see if I'll need that extra 0.000003 sec per att, but likely not. :D

Winner of today's Function Battle:
TRIGONOMETRY

Posted on 2005-12-20 10:39:33

Omni

WHEE!

Yay for the Atan2 built-in!
...
...
...
*slaps self in face again

Posted on 2005-12-20 12:48:31


Displaying 1-7 of 7 total.
1
 
Newest messages

Ben McGraw's lovingly crafted this website from scratch for years.
It's a lot prettier this go around because of Jon Wofford.
Verge-rpg.com is a member of the lunarnet irc network, and would like to take this opportunity to remind you that regardless how babies taste, it is wrong to eat them.