How to check if an angle is in a range of values?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By SebSharper

I am making a top down shooter game, and I wanted to check if the mouse position converted to angle is equal to some of the following angles: 0, 90, 180 and 360.
Of course, that this won’t work because it is very specific (the player would have to point to the angle directly, with a superhuman precision), so I thought about checking if the mouse position to angle is in a range, so that it would have some sort of tolerance.

This is my code:

const FLOAT_EPSILON = 0.000001
#45 of tolerance, this means that if the direct angle is 90, the corresponding range is (90 - 45): 45 (minimum value) and (90 + 45): 135 (maximum value)

if is_inside_range(angles, 45, 135): #90 direct angle
	print("down")
elif is_inside_range(angles, 136, 225): #180 direct angle
	print("left")
elif is_inside_range(angles, 226, 315): #270 direct angle
	print("up")
elif is_inside_range(angles, 316, 360): or is_inside_range(0, 45) #360 direct angle
	print("right")

func is_inside_range(val : float, min_val : float, max_val : float) -> bool:
	return val >= (min_val - FLOAT_EPSILON) and val <= (max_val + FLOAT_EPSILON)

As you can see, this should work well, and it does, except for one little issue. If the angles variable is too close to the beggining/end of a range of values (for example, if it is 90.1), but not the exact value, it will print two states
How could I fix this error? Is there a better way to achieve this?

:bust_in_silhouette: Reply From: klaas

Hi,
since your solution uses a if - elif statement it can only print one or none state at a time.

I would solve it this way:

#build a normalized vector from player to mouse
var dir = player_position_vector.direction_to(mouse_position_vector)

if abs(x) > abs(y): #x-axis deviation is higher than y-axis
    #its more sideways then up or down
    if x > 0:
        #mouse is right
        pass
    else:
        #mouse is left
        pass
else:
    # its more up or down then sideways
    if y > 0:
        #mouse is lower
        pass
    else:
        #mouse is higher
        pass
 

this is a vector based solution.

This is great, however, how could I detect if it is in another value? For example: Vector(1, 1) or 60° angle (down right the player)

SebSharper | 2020-08-24 17:16

just check if the diviation is in a limit …
do it for both axis

var limit = 0.5 # is about 60 degree

#build a normalized vector from player to mouse
var dir = player_position_vector.direction_to(mouse_position_vector)

if abs(x) > limit: #is in limit
    if x > 0:
        #mouse is right
        pass
    else:
        #mouse is left
        pass

if abs(y) > limit : # is in limit
    if y > 0:
        #mouse is down
        pass
    else:
        #mouse is up
        pass

with the limit you can adjust the overlap of the axis

klaas | 2020-08-24 18:59

could I implement an eight direction (maybe even more) system following this with small modifications?

SebSharper | 2020-08-24 23:07

1 Like