0 votes

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?

in Engine by (97 points)

1 Answer

+1 vote

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.

by (4,010 points)

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)

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

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

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.