The tangent of the angle between two points is defined as delta y / delta x
That is (y2 - y1)/(x2-x1). This means that math.atan2(dy, dx) give the angle between the two points assuming that you know the base axis that defines the co-ordinates.
Your gun is assumed to be the (0, 0) point of the axes in order to calculate the angle in radians. Once you have that angle, then you can use the angle for the remainder of your calculations.
Note that since the angle is in radians, you need to use the math.pi instead of 180 degrees within your code. Also your test for more than 360 degrees (2*math.pi) is not needed. The test for negative (< 0) is incorrect as you then force it to 0, which forces the target to be on the x axis in the positive direction.
Your code to calculate the angle between the gun and the target is thus
myradians = math.atan2(targetY-gunY, targetX-gunX)
If you want to convert radians to degrees
mydegrees = math.degrees(myradians)
To convert from degrees to radians
myradians = math.radians(mydegrees)
Python ATAN2
The Python ATAN2 function is one of the Python Math function which is used to returns the angle (in radians) from the X -Axis to the specified point (y, x).
math.atan2()
Answer from sabbahillel on Stack OverflowDefinition Returns the tangent(y,x) in radius.
Syntax
math.atan2(y,x)Parameters
y,x=numbersExamples
The return is:>>> import math >>> math.atan2(88,34) 1.202100424136847 >>>
I have a function called angle_between which calculates the angle between two 2D coordinates and returns it in degrees, its supposed to work with any coordinates given but when y1 and y2 are close and x2 is less than x1, it flips polarity which makes it turn wildly, not sure how to fix it atm and any help would be appreciated.
Pastebin: https://pastebin.com/FyejNCb1
The tangent of the angle between two points is defined as delta y / delta x
That is (y2 - y1)/(x2-x1). This means that math.atan2(dy, dx) give the angle between the two points assuming that you know the base axis that defines the co-ordinates.
Your gun is assumed to be the (0, 0) point of the axes in order to calculate the angle in radians. Once you have that angle, then you can use the angle for the remainder of your calculations.
Note that since the angle is in radians, you need to use the math.pi instead of 180 degrees within your code. Also your test for more than 360 degrees (2*math.pi) is not needed. The test for negative (< 0) is incorrect as you then force it to 0, which forces the target to be on the x axis in the positive direction.
Your code to calculate the angle between the gun and the target is thus
myradians = math.atan2(targetY-gunY, targetX-gunX)
If you want to convert radians to degrees
mydegrees = math.degrees(myradians)
To convert from degrees to radians
myradians = math.radians(mydegrees)
Python ATAN2
The Python ATAN2 function is one of the Python Math function which is used to returns the angle (in radians) from the X -Axis to the specified point (y, x).
math.atan2()
Definition Returns the tangent(y,x) in radius.
Syntax
math.atan2(y,x)Parameters
y,x=numbersExamples
The return is:>>> import math >>> math.atan2(88,34) 1.202100424136847 >>>
In general, the angle of a vector (x, y) can be calculated by math.atan2(y, x). The vector can be defined by 2 points (x1, y1) and (x2, y2) on a line. Therefore the angle of the line is math.atan2(y2-y1, x2-x1).
Be aware that the y-axis needs to be reversed (-y respectively y1-y2) because the y-axis is generally pointing up but in the PyGame coordinate system the y-axis is pointing down. The unit of the angle in the Python math module is Radian, but the unit of the angle in PyGame functions like pygame.transform.rotate() is Degree. Hence the angle has to be converted from Radians to Degrees by math.degrees:
import math
def angle_of_vector(x, y):
return math.degrees(math.atan2(-y, x))
def angle_of_line(x1, y1, x2, y2):
return math.degrees(math.atan2(-(y2-y1), x2-x1))
This can be simplified by using the angle_to method of the pygame.math.Vector2 object. This method computes the angle between 2 vectors in the PyGame coordinate system in degrees. Therefore it is not necessary to reverse the y-axis and convert from radians to degrees. Just calculate the angle between the vector and (1, 0):
def angle_of_vector(x, y):
return pygame.math.Vector2(x, y).angle_to((1, 0))
def angle_of_line(x1, y1, x2, y2):
return angle_of_vector(x2-x1, y2-y1)
Minimale example:

import pygame
import math
def angle_of_vector(x, y):
#return math.degrees(math.atan2(-y, x)) # 1: with math.atan
return pygame.math.Vector2(x, y).angle_to((1, 0)) # 2: with pygame.math.Vector2.angle_to
def angle_of_line(x1, y1, x2, y2):
#return math.degrees(math.atan2(-y1-y2, x2-x1)) # 1: math.atan
return angle_of_vector(x2-x1, y2-y1) # 2: pygame.math.Vector2.angle_to
pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 50)
angle = 0
radius = 150
vec = (radius, 0)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
cpt = window.get_rect().center
pt = cpt[0] + vec[0], cpt[1] + vec[1]
angle = angle_of_vector(*vec)
window.fill((255, 255, 255))
pygame.draw.circle(window, (0, 0, 0), cpt, radius, 1)
pygame.draw.line(window, (0, 255, 0), cpt, (cpt[0] + radius, cpt[1]), 3)
pygame.draw.line(window, (255, 0, 0), cpt, pt, 3)
text_surf = font.render(str(round(angle/5)*5) + "°", True, (255, 0, 0))
text_surf.set_alpha(127)
window.blit(text_surf, text_surf.get_rect(bottomleft = (cpt[0]+20, cpt[1]-20)))
pygame.display.flip()
angle = (angle + 1) % 360
vec = radius * math.cos(angle*math.pi/180), radius * -math.sin(angle*math.pi/180)
pygame.quit()
exit()
angle_to can be used to calculate the angle between 2 vectors or lines:
def angle_between_vectors(x1, y1, x2, y2):
return pygame.math.Vector2(x1, y1).angle_to((x2, y2))
Minimal example:

import pygame
import math
def angle_between_vectors(x1, y1, x2, y2):
return pygame.math.Vector2(x1, y1).angle_to((x2, y2))
def angle_of_vector(x, y):
return pygame.math.Vector2(x, y).angle_to((1, 0))
pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 50)
angle = 0
radius = 150
vec1 = (radius, 0)
vec2 = (radius, 0)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
cpt = window.get_rect().center
pt1 = cpt[0] + vec1[0], cpt[1] + vec1[1]
pt2 = cpt[0] + vec2[0], cpt[1] + vec2[1]
angle = angle_between_vectors(*vec2, *vec1)
window.fill((255, 255, 255))
pygame.draw.circle(window, (0, 0, 0), cpt, radius, 1)
pygame.draw.line(window, (0, 255, 0), cpt, pt1, 3)
pygame.draw.line(window, (255, 0, 0), cpt, pt2, 3)
text_surf = font.render(str(round(angle/5)*5) + "°", True, (255, 0, 0))
text_surf.set_alpha(127)
window.blit(text_surf, text_surf.get_rect(bottomleft = (cpt[0]+20, cpt[1]-20)))
pygame.display.flip()
angle1 = (angle_of_vector(*vec1) + 1/3) % 360
vec1 = radius * math.cos(angle1*math.pi/180), radius * -math.sin(angle1*math.pi/180)
angle2 = (angle_of_vector(*vec2) + 1) % 360
vec2 = radius * math.cos(angle2*math.pi/180), radius * -math.sin(angle2*math.pi/180)
pygame.quit()
exit()
mathematics - Pygame : problem with calculating an angle between two points - Game Development Stack Exchange
python - Calculate angle (clockwise) between two points - Stack Overflow
How to calculate the angle between two points in Python 3? - Stack Overflow
Calculate angle between two coordinates
Videos
Numpy's arctan2(y, x) will compute the counterclockwise angle (a value in radians between -π and π) between the origin and the point (x, y).
You could do this for your points A and B, then subtract the second angle from the first to get the signed clockwise angular difference. This difference will be between -2π and 2π, so in order to get a positive angle between 0 and 2π you could then take the modulo against 2π. Finally you can convert radians to degrees using np.rad2deg.
import numpy as np
def angle_between(p1, p2):
ang1 = np.arctan2(*p1[::-1])
ang2 = np.arctan2(*p2[::-1])
return np.rad2deg((ang1 - ang2) % (2 * np.pi))
For example:
A = (1, 0)
B = (1, -1)
print(angle_between(A, B))
# 45.
print(angle_between(B, A))
# 315.
If you don't want to use numpy, you could use math.atan2 in place of np.arctan2, and use math.degrees (or just multiply by 180 / math.pi) in order to convert from radians to degrees. One advantage of the numpy version is that you can also pass two (2, ...) arrays for p1 and p2 in order to compute the angles between multiple pairs of points in a vectorized way.
Use the inner product and the determinant of the two vectors. This is really what you should understand if you want to understand how this works. You'll need to know/read about vector math to understand.
See: https://en.wikipedia.org/wiki/Dot_product and https://en.wikipedia.org/wiki/Determinant
from math import acos
from math import sqrt
from math import pi
def length(v):
return sqrt(v[0]**2+v[1]**2)
def dot_product(v,w):
return v[0]*w[0]+v[1]*w[1]
def determinant(v,w):
return v[0]*w[1]-v[1]*w[0]
def inner_angle(v,w):
cosx=dot_product(v,w)/(length(v)*length(w))
rad=acos(cosx) # in radians
return rad*180/pi # returns degrees
def angle_clockwise(A, B):
inner=inner_angle(A,B)
det = determinant(A,B)
if det<0: #this is a property of the det. If the det < 0 then B is clockwise of A
return inner
else: # if the det > 0 then A is immediately clockwise of B
return 360-inner
In the determinant computation, you're concatenating the two vectors to form a 2 x 2 matrix, for which you're computing the determinant.
Using the math library's atan2 function,
p1 = (2,2)
p2 = (-1,5)
# Difference in x coordinates
dx = p2[0] - p1[0]
# Difference in y coordinates
dy = p2[1] - p1[1]
# Angle between p1 and p2 in radians
theta = math.atan2(dy, dx)
In pygame you can compute the angle between 2 vector by the use of pygame.math.Vector2 objects and angle_to():
In the following example, (x0, y0) is the rotation point. (x1, y1) and (x2, y2) are the 2 points, which define the vectors form (x0, y0):
v1 = pygame.math.Vector2(x1-x0, y1-y0)
v2 = pygame.math.Vector2(x2-x0, y2-y0)
angle = v1.angle_to(v2)
angle_to() calculates the angle to a given vector in degrees.
