python pygame在旋转图像周围保持一个点位置

r8uurelv  于 2023-01-29  发布在  Python
关注(0)|答案(1)|浏览(158)

在pygame中我有一个0度旋转的护卫舰的图像对象。在它上面我有炮塔,我需要计算他们的新位置,如果护卫舰旋转了90度。
像这样旋转图像后,

rotatedFrigate  = pygame.transform.rotate(gui.frigate[0], facingAngle)

我试过各种方法比如旋转这个点,

point         = pygame.math.Vector2(turretx, turretY)
rotated_point = point.rotate(facingAngle)

即使加上原始的x,y坐标,也仍然相差甚远

t1x,t1y = rotated_point[0]+point[0], rotated_point[1]+point[1]

我也尝试过旋转矩阵的方法,使用中点和增加新的调整暗。

xm,ym = self.x + 0.5*self.w,self.y + 0.5*self.h
a = math.radians(facingAngle)  # Convert to radians
xr = (x - xm) * math.cos(a) - (y - ym) * math.sin(a) + xm
yr = (x - xm) * math.sin(a) + (y - ym) * math.cos(a) + ym
rotatedFrigate       = pygame.transform.rotate(gui.frigate[0], facingAngle)
t1x,t1y             = xr + 0.5*rotatedFrigate.get_width(),yr+ 0.5*rotatedFrigate.get_height()

对于转台:

turretx, turretY               = self.x,self.y+0.05*self.h

自身指的是旋转前的护卫舰坐标
护卫舰图像中心坐标的计算方法为

xm,ym = self.x + 0.5*self.w,self.y + 0.5*self.h

其中w & h是用在护卫舰图像get_width() get_height()上的方法。
再次旋转前。
这两种方法似乎都不起作用,有时它们很接近,但大多数时候它们很遥远。

附加信息

图片是如果我使用rotated_point = (point - pivot).rotate(-facingAngle) + pivot

vuktfyat

vuktfyat1#

我建议使用pygame.math.Vector2.rotate()。如果图像是围绕一个轴旋转的,下面的代码就可以工作。请参阅如何使用PyGame围绕图像中心旋转图像?以及如何为pygame. transform. rotate()?设置轴点(旋转中心)。

  • 计算从轴到点的向量
  • pygame.math.Vector2.rotate()旋转矢量
  • 将轴添加到旋转向量
point = pygame.math.Vector2(turretx, turretY)
pivot = pygame.math.Vector2(self.x + 0.5*self.w, self.y + 0.5*self.h)

rotated_point = (point - pivot).rotate(-facingAngle) + pivot

t1x, t1y = rotated_point.x, rotated_point.y
    • 请注意,需要将矢量旋转负Angular 。pygame.transform.rotate为顺时针方向,pygame.math.Vector2.rotate()为逆时针方向。**

在下面的最小示例中,枢轴点用蓝色十字标记,旋转点用绿色十字标记。旋转向量是蓝色十字和绿色十字之间的蓝色线。

import pygame

pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()

image_size = (160, 80)
point_on_image = (130, 40)
image = pygame.Surface(image_size, pygame.SRCALPHA)
pygame.draw.ellipse(image, "gray", (0, 0, *image_size)) 
pygame.draw.circle(image, "red", point_on_image, 10)
angle = 0

run = True
while run:
    clock.tick(100)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False 
    
    window_center = window.get_rect().center
    rotated_image = pygame.transform.rotate(image, angle)

    px = window_center[0] - image_size[0]//2 + point_on_image[0]
    py = window_center[1] - image_size[1]//2 + point_on_image[1]
    point = pygame.math.Vector2(px, py)
    pivot = pygame.math.Vector2(window_center)
    rotated_point = (point - pivot).rotate(-angle) + pivot

    window.fill("white")
    window.blit(rotated_image, rotated_image.get_rect(center = window_center))
    pygame.draw.line(window, "blue", (window_center[0]-15, window_center[1]), (window_center[0]+15, window_center[1]), 3)
    pygame.draw.line(window, "blue", (window_center[0], window_center[1]-15), (window_center[0], window_center[1]+15), 3)
    pygame.draw.line(window, "green", (rotated_point[0]-15, rotated_point[1]), (rotated_point[0]+15, rotated_point[1]), 3)
    pygame.draw.line(window, "green", (rotated_point[0], rotated_point[1]-15), (rotated_point[0], rotated_point[1]+15), 3)
    pygame.draw.line(window, "blue", window_center, rotated_point, 3)
    pygame.display.flip()

    angle +=1

pygame.quit()
exit()

如果不围绕图像中心旋转图像,而仅将位置保持在左上角,则必须:

  • 计算从原始图像中心到该点的矢量
  • 使用pygame.math.Vector2.rotate()旋转矢量
  • 将旋转图像的中心添加到旋转矢量
point = pygame.math.Vector2(turretx, turretY)
pivot = pygame.math.Vector2(self.x + 0.5*self.w, self.y + 0.5*self.h)

rotatedFrigate = pygame.transform.rotate(gui.frigate[0], facingAngle)
new_pivot = pygame.math.Vector2(
    self.x + 0.5 * rotatedFrigate.get_width(),
    self.y + 0.5 * rotatedFrigate.get_height())

rotated_point = (point - pivot).rotate(-facingAngle) + new_pivot

t1x, t1y = rotated_point.x, rotated_point.y

最小示例:

import pygame

pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()

image_size = (160, 80)
point_on_image = (130, 40)
image = pygame.Surface(image_size, pygame.SRCALPHA)
pygame.draw.ellipse(image, "gray", (0, 0, *image_size)) 
pygame.draw.circle(image, "red", point_on_image, 10)
angle = 0

run = True
while run:
    clock.tick(100)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False 
    
    window_center = window.get_rect().center
    image_rect = image.get_rect(center = window_center)
    rotated_image = pygame.transform.rotate(image, angle)

    px = window_center[0] - image_size[0]//2 + point_on_image[0]
    py = window_center[1] - image_size[1]//2 + point_on_image[1]
    point = pygame.math.Vector2(px, py)
    pivot = pygame.math.Vector2(window_center)
    rotated_image_rect = rotated_image.get_rect(topleft = image_rect.topleft)
    rotated_image_center = rotated_image_rect.center
    rotated_point = (point - pivot).rotate(-angle) + rotated_image_center

    window.fill("white")
    window.blit(rotated_image, rotated_image_rect)
    pygame.draw.rect(window, "black", rotated_image_rect, 3)
    pygame.draw.line(window, "blue", (rotated_image_center[0]-15, rotated_image_center[1]), (rotated_image_center[0]+15, rotated_image_center[1]), 3)
    pygame.draw.line(window, "blue", (rotated_image_center[0], rotated_image_center[1]-15), (rotated_image_center[0], rotated_image_center[1]+15), 3)
    pygame.draw.line(window, "green", (rotated_point[0]-15, rotated_point[1]), (rotated_point[0]+15, rotated_point[1]), 3)
    pygame.draw.line(window, "green", (rotated_point[0], rotated_point[1]-15), (rotated_point[0], rotated_point[1]+15), 3)
    pygame.draw.line(window, "blue", rotated_image_center, rotated_point, 3)
    pygame.display.flip()

    angle +=1

pygame.quit()
exit()

相关问题