一般来说,一个向量(x, y)的角度可以通过math.atan2(y, x)来计算。向量可以由直线上的 2 个点 (x1, y1) 和 (x2, y2) 定义。因此线的角度是math.atan2(y2-y1, x2-x1)。
请注意,y 轴需要反转(-y 分别为 y1-y2),因为 y 轴通常指向上方,但在 PyGame 坐标系中,y 轴指向下方。 Python math 模块中的角度单位为Radian,但在pygame.transform.rotate() 等PyGame 函数中的角度单位为Degree。因此角度必须通过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))
这可以通过使用pygame.math.Vector2 对象的angle_to 方法来简化。此方法计算 PyGame 坐标系中 2 个向量之间的角度(以度为单位)。因此,没有必要反转 y 轴并将弧度转换为度数。只需计算向量与(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)
小例子:
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可用于计算2个向量或直线之间的夹角:
def angle_between_vectors(x1, y1, x2, y2):
return pygame.math.Vector2(x1, y1).angle_to((x2, y2))
小例子:
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()