FOV

by Bravo1
A short supplemental library to include field of view!
ID:1120166
 
Greetings everyone! Another small supplemental library from Bravo1! whoo!

NOTE: This library is meant to be used with the get_ procs library!

This library adds the functionality of field of view to mobs, with some simple (yet lengthy) procs.



Variables:
atom
fov=90 this is the default field of view, and all atoms have it in case you're not looking to use this just for mobs.

Procs:
atom
inFOV(atom/a) - returns true if the given atom (a) is within the fov of src. nfov can be used in place of src's fov.

FOVlist(dist,nfov) - returns a list of all atoms at the given distance (dist) in tileswithin the FOV of the atom calling it.
nfov is a number that can be used in place of the FOV of the atom calling the proc.

mob
inFOV_mobs(mob/a) - returns true if the given mon (a) is within the fov of src. Much more accurate than inFOV() but only works for mobs.
Once again, nfov can be used in place of src's fov.

FOVlist_mobs(dist,nfov) - the same as FOV() however it has a few key differences. dist is done in pixels instead of tiles and is then converted so that a circular range (instead of BYONDs square range) can
be used for distance. This also uses bound_dist to find the distance to the mobs, and get_angle_step to procure a more accurate angle between src and the mobs it's checking.
This will return a list of only the mobs in the given FOV and can only be called by mobs as a result. Once again, nfov can be used instead of the src mob's regular fov.


Once again! NOTE: this library requires my get_ procs library. go download it too. It's cool.


Updates:

1/11/2013: Updated library to include a demo.

1/10/2013[2]: Updated how inFOV works to be much more efficient, as well as removed the need for inFOV_mobs by checking to see if both src and the target are both mobs, then switching to get_angle_step() if they are.

1/10/2013[1]: Added in inFOV() and inFOV_mobs by request. FOV() and FOV() mobs changed to FOVlist() and FOVlist_mobs()
Request: Add a proc that returns if a specific atom is in FOV without having to get a list (over kill).

if(src.inFOV(target)) world << "[src] can see [target]!"


or

if(inFOV(source, target)) world << "[source] can see [target]!"


This feature should avoid using lists (list.Find() or if(x in list)) for speed / efficiency purposes.
I figured using a list would be more helpful, but okay. Give me a minute.
In response to Bravo1
Bravo1 wrote:
I figured using a list would be more helpful, but okay. Give me a minute.

The list is definitely great, and very useful to anyone who is using FOV.

For example:
for(var/mob/m in FOV(x,y))
src.cast_spell(m)


But that's overkill if you want to do something like this:

if(inFOV(b, a)) b.select_target(a)
else b << "[a] is not in your field of view"


It would be inefficient to build a list and check that list, too...

if(a in FOV(x,y))
world << "we built a whole list of mobs just to find if [a] was in the FOV"
Okay I changed it. I kept the list procs, but now the inFOV() and inFOV_mobs() procs get the actual result of whether or not the mob is in the FOV given.

This way you can still use the slightly extra functionality of the FOVlist procs.
In response to Bravo1
Bravo1 wrote:
Okay I changed it. I kept the list procs, but now the inFOV() and inFOV_mobs() procs get the actual result of whether or not the mob is in the FOV given.

This way you can still use the slightly extra functionality of the FOVlist procs.

Code is a little hard to decipher right now, so I'll ask... Are you building a list to calculate inFOV? You shouldn't be. It should be a very very fast calculation, mathematical only.
No list is built from mobs, but lists are used as parameters.

The way I do it is: I get the angle from src, then find the angle from src to the target.

I then find out the range of src's FOV based on their angle. The issue with this is: What happens if the range crosses from 360 to 0 or vice versa?

I can't just do if(angle>leftedge && angle<rightedge)

so what it does is: if the mobs FOV doesn't cross the 360/0 boundary it just gets two lists: left edge of the FOV to the center, then another for center to the right edge.

I then use between() to check if the angle to the target is in either of these two ranges.

I could do the same without lists, but then I'd have to use a bunch of temporary variables and it just looks ugly.

Actually, scratch that: If the boundary isn't crossed then it just uses one range which is center-FOV/2 to center+FOV/2
In response to Bravo1
Bravo1 wrote:
No list is built from mobs, but lists are used as parameters.

The way I do it is: I get the angle from src, then find the angle from src to the target.

I then find out the range of src's FOV based on their angle. The issue with this is: What happens if the range crosses from 360 to 0 or vice versa?

I can't just do if(angle>leftedge && angle<rightedge)

so what it does is: if the mobs FOV doesn't cross the 360/0 boundary it just gets two lists: left edge of the FOV to the center, then another for center to the right edge.

I then use between() to check if the angle to the target is in either of these two ranges.

I could do the same without lists, but then I'd have to use a bunch of temporary variables and it just looks ugly.

Seems like you could do some bit wise math to make this work, with a mask of 360. Unfortunately, I'm not the man for coming up with how that would work. LummoxJR or Stephen001 is, though.
Actually, I just thought of a much simpler way to do it.


If either edge crosses the 360/0 boundary then I could use exclusion rather than inclusion.

Example: instead of checking if A is between 350 and 360, and then also checking if A is between 0 and 10, I could just check if A is NOT between 10 and 350.

That saves tons of code.
In response to Bravo1
Bravo1 wrote:
Actually, I just thought of a much simpler way to do it.


If either edge crosses the 360/0 boundary then I could use exclusion rather than inclusion.

Example: instead of checking if A is between 350 and 360, and then also checking if A is between 0 and 10, I could just check if A is NOT between 10 and 350.

That saves tons of code.

Sounding good. Let's have a look at it :D
Hmm, I'm working on it now, but I also realized my get_turn() procs is tons more strenuous than it needs to be.


Example: angle A needs to reach angle B. If B>A then subtract A from B, (B-A), otherwise, do the opposite (A-B)

If the result is <=180 then then turn in the way the operation entitles, clockwise for B-A and anticlockwise for A-B. Otherwise, do the opposite turn.

Simple as that. I'm sitting here figuring out how far the result of all these angles are when it's really like 3-4 steps either way.

I feel dumb.
And now you're going to have better performance and more efficient calculations on both libraries.
Well, yep, what was InFOV() was... 18 lines is now 14 .I'm using two more temp variables now. so not a big deal, but I don't need lists now, so less work there.

The big difference is get_turn(). 17 lines originally, now 5 lines.

They both work the same as well. I'm happy with these results. Updating soon.

Edit: I've also removed the need for inFOV_mobs by once again, not being stupid, and just using an if() check to see if both src and the target atom are mobs, if they are it uses the more accurate get_angle_step() to find out the angle between the src and the target.

I am leaving in FOVlist_mobs() for the sake of filtering only mobs as well as using a pixel based distance.
In response to Bravo1
Here's my angle_diff() proc in ProcLib:
    //  difference between angles
angle_diff(a, b)
. = (a - b) % 360
if(. < -180) return . + 360
if(. > 180) return . - 360

It might not be perfect but it appears to do fine.
I originally needed this for a missile experiment I made a few years ago. You flew a jet around the map and missiles would chase you down. I needed a way to determine which way to turn the missile to always be facing its target.
Hey, very cool library, I like it. Just one suggestion is to include a demo, not to show how to use it but to show what it does. It'd just let people know whether or not they wanted to use it straight away instead of having to work with it before they decide.
There should already be a demo in there.
In response to Bravo1
Not for me, I just got FOV.dm
Hmm, that's odd. I'll try to fix that
In response to Bravo1
Great thanks, showed up in the latest version.
Page: 1 2 3