我加载了图像,并且希望它在其比例越来越大时围绕其中心旋转。我本来就知道如何围绕图像旋转中心,但是如果比例变大,我很难计算位置。我尝试了一下,但是图像只是“跳舞”,而不是居中。
简短回答:
存储源图像矩形的中心,并在旋转和缩放操作后通过存储的中心位置更新旋转和缩放的图像矩形的中心。通过pygame.transform.rotozoom()
旋转和缩放图像:
pygame.transform.rotozoom()
长回答:
对于以下示例和说明,我将使用由渲染的文本生成的简单图像:
def blitRotateCenter(surf, image, topleft, angle):
center = image.get_rect(topleft = topleft).center
rotated_image = pygame.transform.rotozoom(image, angle, scale)
new_rect = rotated_image.get_rect(center = center)
surf.blit(rotated_image, new_rect.topleft)
[图像(font = pygame.font.SysFont('Times New Roman', 50)
text = font.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))
)可以旋转pygame.Surface
。
如果逐步执行此操作,则图像会失真并迅速增加:
pygame.Surface
这是原因,因为旋转图像的边界矩形始终大于原始图像的边界矩形(某些旋转角度为90度的倍数除外)。由于多份复印,图像变形。每次旋转都会产生一个小的误差(不准确)。误差的总和越来越大,图像衰减。
可以通过保留原始图像并将其“变白”一次旋转操作生成的图像来形成原始图像来解决。
pygame.transform.rotate
while not done:
# [...]
image = pygame.transform.rotate(image, 1)
screen.blit(image, pos)
pygame.display.flip()
现在图像似乎可以任意改变其位置,因为图像的大小随旋转而改变,并且原点始终位于图像边界矩形的左上方。
可以通过比较旋转之前和旋转之后图像的来补偿。对于以下数学运算,使用angle = 0
while not done:
# [...]
rotated_image = pygame.transform.rotate(image, angle)
angle += 1
screen.blit(rotated_image, pos)
pygame.display.flip()
。请注意,在屏幕坐标中y指向屏幕下方,但是数学y轴点从底部到顶部。这导致在计算过程中必须“翻转” y轴
使用边界框的四个角点设置列表:
通过axis aligned bounding box将矢量旋转到角点:
pygame.math.Vector2
获得旋转点的最小值和最大值:
pygame.math.Vector2
通过将旋转框的最小值添加到该位置来计算图像左上点的“补偿”原点。对于y坐标,w, h = image.get_size()
box = [pygame.math.Vector2(p) for p in [(0, 0), (w, 0), (w, -h), (0, -h)]]
最小,因为沿y轴“翻转”:
pygame.math.Vector2.rotate
pygame.math.Vector2.rotate
[要在原始图像上定义支点,必须计算支点相对于图像左上角的“平移”,并且必须通过平移来替换图像的“ blit”位置。
[定义一个枢轴,例如在图片的中央:
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])
最后计算旋转图像的原点:
max_box[1]
origin = (pos[0] + min_box[0], pos[1] - max_box[1])
rotated_image = pygame.transform.rotate(image, angle)
screen.blit(rotated_image, origin)
如果必须另外缩放图像,则在计算图像原点时必须考虑缩放:
在下面的示例程序中,函数pivot = pygame.math.Vector2(w/2, -h/2)
执行上述所有步骤,并将旋转后的图像“拉伸”到表面。 pivot_rotate = pivot.rotate(angle)
pivot_move = pivot_rotate - pivot
是图像的位置。 origin = (pos[0] + min_box[0] - pivot_move[0], pos[1] - max_box[1] + pivot_move[1])
rotated_image = pygame.transform.rotate(image, angle)
screen.blit(rotated_image, origin)
是图像上位于和枢轴上的点:
move = (-pivot[0] + min_box[0] - pivot_move[0], pivot[1] - max_box[1] + pivot_move[1])
origin = (pos[0] + zoom * move[0], pos[1] + zoom * move[1])
rotozoom_image = pygame.transform.rotozoom(image, angle, zoom)
screen.blit(rotozoom_image, origin)
blitRotate
缩放(旋转)后,您需要重新设置图像的中心,因为这两个都可以改变图像的大小。
pos
要考虑的另一件事是确保图像内容位于其内部居中。 (想象一个仅将内容绘制到一侧的矩形)旋转将在几何上居中,但旋转时在视觉上仍然看起来很奇怪。