如何知道两点之间的角度?

时间:2017-02-15 19:43:31

标签: python math pygame angle

我正在用pygame制作小游戏,我制作了一支围绕其中心旋转的枪。 我的问题是我希望枪自己向敌方方向旋转,但是我不能这样做,因为我找不到枪和敌人之间的角度让枪旋转到它 我搜索过,发现我必须使用>>> a = funfunc() >>> next(a) init enter 1 >>> del a # exit because the variable holding the suspended generator is deleted. exit ,但我找不到任何正常工作的代码,所以我希望有人可以帮助我。

这是我的代码:

atan2

这是一张试图说清楚的图片:

enter image description here

感谢。

5 个答案:

答案 0 :(得分:18)

两点之间角度的正切定义为delta y / delta x 即(y2-y1)/(x2-x1)。这意味着math.atan2(dy, dx)给出两个点之间的角度假设您知道定义坐标的基轴。

假设您的喷枪是轴的(0,0)点,以便以弧度计算角度。一旦你有了这个角度,那么你可以在计算的其余部分使用角度。

请注意,由于角度是弧度,因此您需要在代码中使用math.pi而不是180度。此外,您不需要超过360度(2 * math.pi)的测试。负值(< 0)的测试不正确,因为然后将其强制为0,这会强制目标在正方向的x轴上。

因此,您计算枪与目标之间角度的代码是

myradians = math.atan2(targetY-gunY, targetX-gunX)

如果您想将弧度转换为度数

mydegrees = math.degrees(myradians)

将度数转换为弧度

myradians = math.radians(mydegrees)

Python ATAN2

  

Python ATAN2函数是Python Math函数之一   用于返回从X-Axis到角度的角度(以弧度表示)   指定点(y,x)。

math.atan2()

  

定义以半径形式返回切线(y,x)。

     

<强>语法
  math.atan2(Y,X)

     

<强>参数
  Y,X =编号

     

<强>实施例
  回报是:

>>> import math  
>>> math.atan2(88,34)  
1.202100424136847  
>>>

答案 1 :(得分:1)

正如一位评论者所说,三个点之间或两个交叉向量之间只有一个角度,可以从这三个点得出。我假设你想要角度,枪和目标(矢量1)和X轴(矢量2)。这是一个页面链接,解释了如何计算该角度。 http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm

Python示例:

import math

def angle(vector1, vector2):
    length1 = math.sqrt(vector1[0] * vector1[0] + vector1[1] * vector1[1])
    length2 = math.sqrt(vector2[0] * vector2[0] + vector2[1] * vector2[1])
    return math.acos((vector1[0] * vector2[0] + vector1[1] * vector2[1])/ (length1 * length2))

vector1 = [targetX - gunX, targetY - gunY] # Vector of aiming of the gun at the target
vector2 = [1,0] #vector of X-axis
print(angle(vector1, vector2))

答案 2 :(得分:1)

通常,向量{em>(x,y)的角度可以通过math.atan2(y, x)计算。向量可以由直线上的两个点(x1,y1)(x2,y2)定义。因此,线的角度为math.atan2(y2-y1, x2-x1)。 请注意,y轴需要反转(分别{-yy1-y2),因为y轴通常指向上方,但在PyGame坐标系中,y轴指向下方。 Python math模块中的角度单位为Radian,而PyGame函数(如pygame.transform.rotate())中的角度单位为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(-y1-y2, x2-x1))

这可以通过使用pygame.math.Vector2对象的angle_to方法来简化。此方法以度为单位计算PyGame坐标系中两个向量之间的角度。因此,没有必要反转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)

Minimale示例:

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()

答案 3 :(得分:0)

专门用于处理subquery_from_clause ::= FROM subselect_identification_variable_declaration ... subselect_identification_variable_declaration ::= identification_variable_declaration | derived_path_expression [AS] identification_variable {join}* | derived_collection_member_declaration derived_path_expression ::= superquery_identification_variable.{single_valued_object_field.}*collection_valued_field | superquery_identification_variable.{single_valued_object_field.}*single_valued_object_field 对象,假设您的对象(两点)的形式为shapely linestring

(min long, min lat, max long, max lat)

答案 4 :(得分:0)

您只需使用Pygame的Vector2类的as_polar方法即可返回向量的polar coordinates(半径和极角(以度为单位))。

因此,只需从第二个点中减去第一个点向量,然后调用所得向量的as_polar方法即可。

import pygame as pg
from pygame.math import Vector2


pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
BG_COLOR = pg.Color('gray12')

point = Vector2(320, 240)
mouse_pos = Vector2(0, 0)
radius, angle = (mouse_pos - point).as_polar()

done = False
while not done:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            done = True
        elif event.type == pg.MOUSEMOTION:
            mouse_pos = event.pos
            radius, angle = (mouse_pos - point).as_polar()

    screen.fill(BG_COLOR)
    pg.draw.line(screen, (0, 100, 255), point, mouse_pos)
    pg.display.set_caption(f'radius: {radius:.2f} angle: {angle:.2f}')
    pg.display.flip()
    clock.tick(60)