如何使用Pygame将图像绕其中心旋转?

您所在的位置:网站首页 pygame旋转图片后还是矩形吗 如何使用Pygame将图像绕其中心旋转?

如何使用Pygame将图像绕其中心旋转?

2023-11-21 13:11| 来源: 网络整理| 查看: 265

简短的回答。

获取原始图像的矩形并设置位置。获取旋转后的图像的矩形,并通过原始矩形的中心设置中心位置。返回旋转后的图像和矩形的一个元组。

def rot_center(image, angle, x, y): rotated_image = pygame.transform.rotate(image, angle) new_rect = rotated_image.get_rect(center = image.get_rect(center = (x, y)).center) return rotated_image, new_rect

或者写一个可以旋转和.blit图像的函数。

def blitRotateCenter(surf, image, topleft, angle): rotated_image = pygame.transform.rotate(image, angle) new_rect = rotated_image.get_rect(center = image.get_rect(topleft = topleft).center) surf.blit(rotated_image, new_rect)

长答案。

一个图像(pygame.Surface)可以通过以下方式进行旋转pygame.transform.rotate.

如果这是在一个循环中逐步进行的,那么图像就会被扭曲并迅速增加。

while not done: # [...] image = pygame.transform.rotate(image, 1) screen.blit(image, pos) pygame.display.flip()

这是因为旋转的图像的边界矩形总是大于原始图像的边界矩形(除了一些90度的倍数的旋转)。 由于多重拷贝,图像会被扭曲。每次旋转都会产生一个小误差(不准确)。误差的总和在不断增加,图像也在不断衰减。

这可以通过保留原始图像和 "模糊 "一个由单一旋转操作产生的图像来解决,该图像由原始图像组成。

angle = 0 while not done: # [...] rotated_image = pygame.transform.rotate(image, angle) angle += 1 screen.blit(rotated_image, pos) pygame.display.flip()

现在,图像似乎任意改变了它的位置,因为图像的大小因旋转而改变,原点始终是图像边界矩形的左上方。

这可以通过比较轴对齐的包围盒旋转前和旋转后的图像。 对于以下数学问题pygame.math.Vector2被使用。请注意,在屏幕坐标中,Y轴指向屏幕下方,但数学上的Y轴指向底部到顶部。这导致在计算过程中,Y轴必须被 "翻转"。

设置一个列表,其中有包围盒的4个角点。

w, h = image.get_size() box = [pygame.math.Vector2(p) for p in [(0, 0), (w, 0), (w, -h), (0, -h)]]

将向量旋转到角点,方法是pygame.math.Vector2.rotate:

box_rotate = [p.rotate(angle) for p in box]

获取旋转点的最小值和最大值。

min_box = (min(box_rotate, key=lambda p: p[0])[0], min(box_rotate, key=lambda p: p[1])[1]) max_box = (max(box_rotate, key=lambda p: p[0])[0], max(box_rotate, key=lambda p: p[1])[1])

计算图像左上角点的 "补偿 "原点,将旋转框的最小值加到该位置。对于y坐标max_box[1]是最小值,因为沿y轴的 "翻转"。

origin = (pos[0] + min_box[0], pos[1] - max_box[1]) rotated_image = pygame.transform.rotate(image, angle) screen.blit(rotated_image, origin)

甚至可以在原始图像上定义一个支点。计算从图像中心到支点的偏移矢量并旋转该矢量。一个矢量可以用以下方式表示pygame.math.Vector2并且可以用旋转的方式pygame.math.Vector2.rotate.注意,pygame.math.Vector2.rotate的旋转方向与pygame.transform.rotate相反。因此,这个角度必须是倒置的。

计算从图像中心到支点的矢量。

image_rect = image.get_rect(topleft = (pos[0] - originPos[0], pos[1]-originPos[1])) offset_center_to_pivot = pygame.math.Vector2(pos) - image_rect.center

旋转矢量

rotated_offset = offset_center_to_pivot.rotate(-angle)

计算旋转后图像的中心。

rotated_image_center = (pos[0] - rotated_offset.x, pos[1] - rotated_offset.y)

对图像进行旋转和模糊处理。

rotated_image = pygame.transform.rotate(image, angle) rotated_image_rect = rotated_image.get_rect(center = rotated_image_center) screen.blit(rotated_image, rotated_image_rect)

在下面的示例程序中,函数blitRotate(surf, image, pos, originPos, angle)完成了上述所有步骤,并将旋转的图像 "混合 "到一个表面。

surf是目标表面

替换代码24】是需要旋转的表面,blit是需要旋转的表面。

替换代码26】是目标面surf上的支点位置(相对于surf的左上方)。

替换代码29】是枢轴在image上的位置。表面的位置(相对于image的左上方)

替换代码32】是旋转的角度,单位是度。

这意味着,blitRotate的第二个参数(pos)是窗口中的支点位置,第三个参数(originPos)是旋转中的支点位置。表面:

最小的例子。repl.it/@Rabbid76/PyGame-RotateAroundPivot

import pygame pygame.init() screen = pygame.display.set_mode((300, 300)) clock = pygame.time.Clock() def blitRotate(surf, image, pos, originPos, angle): # offset from pivot to center image_rect = image.get_rect(topleft = (pos[0] - originPos[0], pos[1]-originPos[1])) offset_center_to_pivot = pygame.math.Vector2(pos) - image_rect.center # roatated offset from pivot to center rotated_offset = offset_center_to_pivot.rotate(-angle) # roatetd image center rotated_image_center = (pos[0] - rotated_offset.x, pos[1] - rotated_offset.y) # get a rotated image rotated_image = pygame.transform.rotate(image, angle) rotated_image_rect = rotated_image.get_rect(center = rotated_image_center) # rotate and blit the image surf.blit(rotated_image, rotated_image_rect) # draw rectangle around the image pygame.draw.rect(surf, (255, 0, 0), (*rotated_image_rect.topleft, *rotated_image.get_size()),2) def blitRotate2(surf, image, topleft, angle): rotated_image = pygame.transform.rotate(image, angle) new_rect = rotated_image.get_rect(center = image.get_rect(topleft = topleft).center) surf.blit(rotated_image, new_rect.topleft) pygame.draw.rect(surf, (255, 0, 0), new_rect, 2) try: image = pygame.image.load('AirPlaneFront.png') except: text = pygame.font.SysFont('Times New Roman', 50).render('image', False, (255, 255, 0)) image = pygame.Surface((text.get_width()+1, text.get_height()+1)) pygame.draw.rect(image, (0, 0, 255), (1, 1, *text.get_size())) image.blit(text, (1, 1)) w, h = image.get_size() angle = 0 done = False while not done: clock.tick(60) for event in pygame.event.get(): if event.type == pygame.QUIT: done = True pos = (screen.get_width()/2, screen.get_height()/2) screen.fill(0) blitRotate(screen, image, pos, (w/2, h/2), angle) #blitRotate2(screen, image, pos, angle) angle += 1 pygame.draw.line(screen, (0, 255, 0), (pos[0]-20, pos[1]), (pos[0]+20, pos[1]), 3) pygame.draw.line(screen, (0, 255, 0), (pos[0], pos[1]-20), (pos[0], pos[1]+20), 3) pygame.draw.circle(screen, (0, 255, 0), pos, 7, 0) pygame.display.flip() pygame.quit() exit()

另见旋转表面以及问题的答案。

How can you rotate an image around an off center pivot in Pygame How to rotate an image around its center while its scale is getting larger(in Pygame) How to rotate an image(player) to the mouse direction? How to set the pivot point (center of rotation) for pygame.transform.rotate()? How do you point the barrel towards mouse in pygame?


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3