مهن*_*ليل 10 python math pygame angle
我正在用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)
Run Code Online (Sandbox Code Playgroud)
这是一张试图说清楚的图片:
谢谢.
sab*_*lel 27
两点之间的角度的正切定义为Δ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)
Run Code Online (Sandbox Code Playgroud)
如果要将弧度转换为度数
mydegrees = math.degrees(myradians)
Run Code Online (Sandbox Code Playgroud)
要从度数转换为弧度
myradians = math.radians(mydegrees)
Run Code Online (Sandbox Code Playgroud)
Python ATAN2函数是Python Math函数之一,用于返回从X-Axis到指定点(y,x)的角度(以弧度表示).
定义 以半径形式返回切线(y,x).
语法
math.atan2(y,x)参数
y,x =数字示例
返回的是:Run Code Online (Sandbox Code Playgroud)>>> import math >>> math.atan2(88,34) 1.202100424136847 >>>
一般来说,矢量(x, y)的角度可以通过 计算math.atan2(y, x)。该向量可以由一条线上的2 个点(x1, y1)和(x2, y2)定义。因此,直线的角度为math.atan2(y2-y1, x2-x1)。\n请注意,y 轴需要反转(-y分别y1-y2),因为 y 轴通常指向上方,但在 PyGame 坐标系中 y 轴指向下方。Python 模块中角度的单位math是Radian,但 PyGame 等函数中角度的单位pygame.transform.rotate()是Degree。因此,角度必须通过以下方式从弧度转换为度数math.degrees:
import math\n\ndef angle_of_vector(x, y):\n return math.degrees(math.atan2(-y, x))\n\ndef angle_of_line(x1, y1, x2, y2):\n return math.degrees(math.atan2(-(y2-y1), x2-x1))\nRun Code Online (Sandbox Code Playgroud)\n这可以通过使用对象angle_to的方法来简化pygame.math.Vector2。此方法计算 PyGame 坐标系中 2 个向量之间的角度(以度为单位)。因此,无需反转 y 轴并将弧度转换为度数。只需计算向量和(1, 0)之间的角度:
def angle_of_vector(x, y):\n return pygame.math.Vector2(x, y).angle_to((1, 0))\n\ndef angle_of_line(x1, y1, x2, y2):\n return angle_of_vector(x2-x1, y2-y1)\nRun Code Online (Sandbox Code Playgroud)\n最小示例:
\n\nimport pygame\nimport math\n\ndef angle_of_vector(x, y):\n #return math.degrees(math.atan2(-y, x)) # 1: with math.atan\n return pygame.math.Vector2(x, y).angle_to((1, 0)) # 2: with pygame.math.Vector2.angle_to\n \ndef angle_of_line(x1, y1, x2, y2):\n #return math.degrees(math.atan2(-y1-y2, x2-x1)) # 1: math.atan\n return angle_of_vector(x2-x1, y2-y1) # 2: pygame.math.Vector2.angle_to\n \npygame.init()\nwindow = pygame.display.set_mode((400, 400))\nclock = pygame.time.Clock()\nfont = pygame.font.SysFont(None, 50)\n\nangle = 0\nradius = 150\nvec = (radius, 0)\n\nrun = True\nwhile run:\n clock.tick(60)\n for event in pygame.event.get():\n if event.type == pygame.QUIT:\n run = False\n\n cpt = window.get_rect().center\n pt = cpt[0] + vec[0], cpt[1] + vec[1]\n angle = angle_of_vector(*vec)\n\n window.fill((255, 255, 255))\n pygame.draw.circle(window, (0, 0, 0), cpt, radius, 1)\n pygame.draw.line(window, (0, 255, 0), cpt, (cpt[0] + radius, cpt[1]), 3)\n pygame.draw.line(window, (255, 0, 0), cpt, pt, 3)\n text_surf = font.render(str(round(angle/5)*5) + "\xc2\xb0", True, (255, 0, 0))\n text_surf.set_alpha(127)\n window.blit(text_surf, text_surf.get_rect(bottomleft = (cpt[0]+20, cpt[1]-20)))\n pygame.display.flip()\n\n angle = (angle + 1) % 360\n vec = radius * math.cos(angle*math.pi/180), radius * -math.sin(angle*math.pi/180)\n\npygame.quit()\nexit()\nRun Code Online (Sandbox Code Playgroud)\nangle_to可用于计算 2 个向量或直线之间的角度:
def angle_between_vectors(x1, y1, x2, y2):\n return pygame.math.Vector2(x1, y1).angle_to((x2, y2))\nRun Code Online (Sandbox Code Playgroud)\n最小的例子:
\n\nimport pygame\nimport math\n\ndef angle_between_vectors(x1, y1, x2, y2):\n return pygame.math.Vector2(x1, y1).angle_to((x2, y2))\n\ndef angle_of_vector(x, y):\n return pygame.math.Vector2(x, y).angle_to((1, 0)) \n \npygame.init()\nwindow = pygame.display.set_mode((400, 400))\nclock = pygame.time.Clock()\nfont = pygame.font.SysFont(None, 50)\n\nangle = 0\nradius = 150\nvec1 = (radius, 0)\nvec2 = (radius, 0)\n\nrun = True\nwhile run:\n clock.tick(60)\n for event in pygame.event.get():\n if event.type == pygame.QUIT:\n run = False\n\n cpt = window.get_rect().center\n pt1 = cpt[0] + vec1[0], cpt[1] + vec1[1]\n pt2 = cpt[0] + vec2[0], cpt[1] + vec2[1]\n angle = angle_between_vectors(*vec2, *vec1)\n\n window.fill((255, 255, 255))\n pygame.draw.circle(window, (0, 0, 0), cpt, radius, 1)\n pygame.draw.line(window, (0, 255, 0), cpt, pt1, 3)\n pygame.draw.line(window, (255, 0, 0), cpt, pt2, 3)\n text_surf = font.render(str(round(angle/5)*5) + "\xc2\xb0", True, (255, 0, 0))\n text_surf.set_alpha(127)\n window.blit(text_surf, text_surf.get_rect(bottomleft = (cpt[0]+20, cpt[1]-20)))\n pygame.display.flip()\n\n angle1 = (angle_of_vector(*vec1) + 1/3) % 360\n vec1 = radius * math.cos(angle1*math.pi/180), radius * -math.sin(angle1*math.pi/180)\n angle2 = (angle_of_vector(*vec2) + 1) % 360\n vec2 = radius * math.cos(angle2*math.pi/180), radius * -math.sin(angle2*math.pi/180)\n\npygame.quit()\nexit()\nRun Code Online (Sandbox Code Playgroud)\n
专门用于处理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])
Run Code Online (Sandbox Code Playgroud)