I'm trying to make a radial sight function for the enemies in my game
I want them to know if the player has entered a radius around them, and be able to control the angle of their sight according to their direction
So basically it's checking if the player has entered a sector of the radius around them, and also being able to control the percentage of the sector and its direction.
I thought about splitting the radius around them into directions, as seen in the image. I'm not sure if that's right.
I'm terrible at math so I couldn't figure this one out, I'd appreciate the help
this is the closest solution that I found, but I couldn't make it work
https://www.geeksforgeeks.org/check-whether-point-exists-circle-sector-not/
So, that link is almost completely correct on how to check if a dot is in a sector, but doesn't include any consideration for efficiency. The first change I would make to it (after translating to lua with pico-8 functions) would be to not use square root. I say this first, because it means that your enemies should store the radius times itself if you want the checks to be fast. Also, I say "almost" because it fails to consider something really important I'm describe later that makes it not robust enough for game usage.
To explain how the method works in less college-math terms, it's just using the arctangent function to tell direction and then using the basic formula for distance to check distance. I have no idea why that article mentions the term "polar coordinates" since that concept isn't needed. If the distance between the objects is less than or equal to the radius of vision, then the player is close enough to be seen. If the direction from the enemy to the player has an angle between the two you chose for the enemy's vision, then the player is in the right direction to be seen by the enemy.
The big caveat is that pico-8's function for this, atan2()
uses values from 0 to 1 for a full circle. That means if you use degrees when planning the mechanics, then the angle needs to be divided by 360 to convert. Then, if the angle is negative, add 1 to it. The wiki has diagrams that might help.
Now for details, atan2()
takes "dx" and "dy" as parameters. This is short for either "difference in" or "delta" (math way to say "difference in"). As such, dx should be the player's x coordinate minus the enemy's x coordinate, with dy being found the same way using the y coordinates. For distance, the formula is sqrt(dy*dy + dx*dx)
but if you stored the radius times itself to begin with, you can instead just use dy*dy + dx*dx
. Lastly, the angles for comparing can be gotten by figuring out how much of the circle you want, then using half of that as the offset from where the enemy is looking. So if you want an enemy to see 1/4 of the circle and be facing to the left, the angles would be .375 (.5 - 1/8) and .625 (.5 + 1/8).
And here's where the link you looked at fails: if the enemy is looking to the right, the simple check if the direction to player is between the vision angles will fail. To deal with that case, you would need to check if the vision range would have either an angle that goes higher than 1 or an angle that is negative. If so, the offending angle should be offset by 1 and the check should instead be if the direction to the player isn't between them.
Regarding your idea of splitting the circle into quarters, that would be a great solution if you only plan to ever have the enemies look in specific directions and with specific angles of vision. In that case you could then use inequalities and not have to deal with the atan2()
function or any angle awkwardness. It'd also likely be faster. However, it would require figuring out the slope of each of the lines of sight, which might require using arctangent on a calculator anyway. For the quarter circles in your diagram, though, the slopes would be 1 and -1, so it could be simplified down to whether dx > dy
and whether -dx > dy
. That method would also still require checking distance the same way.
the tutos on https://demoman.net/ are great to learn how to do these things
@Mikimation, I remember writing a program that could determine values within triangles of sight and no fancy math. I did this to determine "swipes" where you would slide the mouse across the screen or if using a Tablet, your finger.
https://www.lexaloffle.com/bbs/?tid=27757
. . .
I further wrote a cart to demonstrate "Field Of View." which should cover what you need.
[Please log in to post a comment]