如何知道两个向量之间的角度?

2025-03-07 09:02:00
admin
原创
34
摘要:问题描述:我正在用 pygame 制作小游戏,我制作了一把围绕其中心旋转的枪。我的问题是我想让枪自己旋转到敌人的方向,但我无法做到这一点,因为我找不到枪和敌人之间的角度来让枪旋转到它我搜索了一下,发现我必须使用atan2但我没有找到任何有效的代码所以我希望有人能帮助我。这是我的代码:import pygame...

问题描述:

我正在用 pygame 制作小游戏,我制作了一把围绕其中心旋转的枪。我的问题是我想让枪自己旋转到敌人的方向,但我无法做到这一点,因为我找不到枪和敌人之间的角度来让枪旋转到它我搜索了一下,发现我必须使用atan2但我没有找到任何有效的代码所以我希望有人能帮助我。

这是我的代码:

import pygame
from pygame.locals import*
pygame.init()
height=650
width=650
screen=pygame.display.set_mode((height,width))
clock=pygame.time.Clock()
gun=pygame.image.load("m2.png").convert_alpha() 
gun=pygame.transform.smoothscale(gun,(200,200)).convert_alpha()
angle=0
angle_change=0
RED=(255,0,0)
x=525
y=155
while True :
    screen.fill((150,150,150))
    for event in pygame.event.get():
        if event.type==QUIT:
            pygame.quit()
            quit()
        if event.type==KEYDOWN:
            if event.key==K_a:
                angle_change=+1
            if event.key==K_d:
                angle_change=-1
        elif event.type==KEYUP:
            angle_change=0
    angle+=angle_change
    if angle>360:
        angle=0
    if angle<0:
        angle=360
    pygame.draw.rect(screen,RED,(x,y,64,64))
    position = (height/2,width/2)
    gun_rotate=pygame.transform.rotate(gun,angle) 
    rotate_rect = gun_rotate.get_rect()
    rotate_rect.center = position
    screen.blit(gun_rotate, rotate_rect)
    pygame.display.update()
    clock.tick(60) 

下面是一张图片,可以更清楚地说明这一点:

如何知道两个向量之间的角度?

我该如何解决这个问题?


解决方案 1:

两点之间的角度的正切定义为 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 数学函数之一,用于返回从 X 轴到指定点 (y, x) 的角度(以弧度为单位)。

数学.atan2()

定义 返回半径的切线(y,x)。

语法

math.atan2(y,x)

参数

y,x=数字

示例

返回值为:

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

解决方案 2:

一般来说,向量(x, y)的角度可以通过 来计算math.atan2(y, x)。向量可以由一条线上的两个点(x1, y1)(x2, y2)math.atan2(y2-y1, x2-x1)定义。因此,该线的角度为。请注意,y 轴需要反转(-y分别y1-y2),因为 y 轴通常指向上方,但在 PyGame 坐标系中,y 指向下方。Python 模块中角度的单位math是弧度,但 PyGame 函数中角度的单位类似于pygame.transform.rotate()度。因此,必须通过 将该角度从 弧度 转换为 度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))

可以使用对象angle_to的方法简化此过程pygame.math.Vector2。此方法以度为单位计算 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)

最小示例:

如何知道两个向量之间的角度?

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可用于计算两个向量或直线之间的角度:

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:

专门用于处理shapely linestring对象,假设你的对象(两个点)的形式为(min long, min lat, max long, max lat)

from math import atan2,degrees
line = #Your-LineString-Object
lineList = list(line.coords)

def AngleBtw2Points(pointA, pointB):
  changeInX = pointB[0] - pointA[0]
  changeInY = pointB[1] - pointA[1]
  return degrees(atan2(changeInY,changeInX)) #remove degrees if you want your answer in radians

AngleBtw2Points(lineList[0],lineList[1]) 

解决方案 4:

我使用了以下代码。

import math

def get_angle(x1,y1,x2,y2):
    myradians = math.atan2(y1-y2, x1-x2)
    mydegrees = math.degrees(myradians)
    return mydegrees

# it should return -90 degree
print(get_angle(0,0,0,100))

解决方案 5:

正如一位评论者所说,只有三个点之间或两个相交向量之间的角度才能从这三个点得出。我假设你想要的是枪和目标(向量 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))

解决方案 6:

您可以使用as_polarPygame 的Vector2类的方法,该方法返回矢量的极坐标(半径和极角(以度为单位))。

因此只需从第二个点向量中减去第一个点向量,然后调用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)

解决方案 7:

如果有人想了解更多关于这个主题的信息,请查看 omnicalculator 对该主题的分析:
https://www.omnicalculator.com/math/angle-between-two-vectors

摘录的相关信息:

from math import acos, sqrt, degrees

# returns angle in radians between two points pt1, pt2 where pt1=(x1, y1) and pt2=(x2, y2)
angle = acos((x1 * x2 + y1 * y2)/(sqrt(x1**2 + y1**2) * sqrt(x2**2 + y2**2)))

# convert to degrees
deg_angle = degrees(angle)
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1914  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1432  
  在制造业数字化转型的进程中,PLM(产品生命周期管理)系统、ERP(企业资源计划)系统、MES(制造执行系统)以及 CAD(计算机辅助设计)软件都扮演着至关重要的角色。然而,这些系统和软件各自独立运行时,往往难以发挥出最大的协同效应。实现 PLM 系统与 ERP、MES、CAD 的有效集成,成为提升企业整体竞争力、优化...
plm系统的主要功能模块   23  
  产品生命周期管理(PLM)作为一种先进的管理理念和技术,在电子与半导体行业正发挥着日益重要的作用。随着电子与半导体行业的快速发展,产品更新换代速度加快,市场竞争愈发激烈,企业面临着诸多挑战,如缩短产品上市时间、提高产品质量、降低成本等。而PLM的应用为企业应对这些挑战提供了有效的解决方案,展现出巨大的应用价值。提升产品...
plm项目   20  
  PLM(产品生命周期管理)项目管理软件在现代企业的产品研发、生产与运营中扮演着至关重要的角色。它整合了从产品概念设计到退役的全流程数据与流程,助力企业提升效率、降低成本并增强创新能力。随着科技的飞速发展以及企业需求的不断演变,未来十年 PLM 项目管理软件的发展充满了无限可能,值得深入探讨与预测。智能化与自动化趋势智能...
plm产品全生命周期管理   24  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用