Python 如何在Pygame中围绕偏心轴旋转图像

Python 如何在Pygame中围绕偏心轴旋转图像,python,pygame,Python,Pygame,我想绕轴旋转图像,该轴不在图像的中心。 轴是图像中的绿色十字: 我知道枢轴在游戏窗口中的位置。 如何在这一点上跟踪图像,并同时围绕这一点旋转图像 image=pygame.image.load(“boomerag64.png”) 位置=(200200) 角度=0 尽管如此: # [...] 旋转直线,旋转图像=围绕绿色十字旋转一个角度 冲浪板(旋转图像,旋转直线) 角度+=1 # [...] 首先必须定义表面上枢轴的位置: image=pygame.image.load(“boomerag64

我想绕轴旋转图像,该轴不在图像的中心。
轴是图像中的绿色十字:

我知道枢轴在游戏窗口中的位置。 如何在这一点上跟踪图像,并同时围绕这一点旋转图像

image=pygame.image.load(“boomerag64.png”)
位置=(200200)
角度=0
尽管如此:
# [...]
旋转直线,旋转图像=围绕绿色十字旋转一个角度
冲浪板(旋转图像,旋转直线)
角度+=1
# [...]

首先必须定义
表面上枢轴的位置

image=pygame.image.load(“boomerag64.png”)#64x64曲面
枢轴=(48,21)#枢轴在图像上的位置
旋转图像时,其大小会增加。我们必须比较旋转前和旋转后图像的颜色。
对于以下情况,使用了数学。注意:在屏幕坐标中,y点位于屏幕下方,但数学y轴点从底部到顶部。这导致在计算过程中y轴必须“翻转”

设置一个包含边界框的4个角点的列表,并将向量旋转到角点。最后找到旋转框的最小值。由于pygame中的y轴指向下方,因此必须通过找到旋转反向高度的最大值(“最大值(旋转(-h))”)来进行补偿:

w,h=image.get_size()
box=[pygame.math.Vector2(p)表示[(0,0),(w,0),(w,-h),(0,-h)]]
box_rotate=[p.rotate(角度)表示框中的p]
min_x,min_y=min(框旋转,键=λp:p[0])[0],max(框旋转,键=λp:p[1])[1]
通过函数直接计算旋转向量的x和y分量,可以改进
min_x
min_y
的计算:

w,h=image.get_size()
sin_a,cos_a=math.sin(math.radians(angle)),math.cos(math.radians(angle))
min_x,min_y=min([0,sin_a*h,cos_a*w,sin_a*h+cos_a*w]),max([0,sin_a*w,-cos_a*h,sin_a*w-cos_a*h])
通过将旋转框的最小值添加到相对于图像上枢轴的位置,计算图像左上点的“补偿”原点:

原点=(位置[0]-原点位置[0]+最小x轴移动[0],位置[1]-原点位置[1]-最小y轴移动[1])
旋转的_image=pygame.transform.rotate(图像,角度)
屏幕。blit(旋转图像,原点)
在以下示例程序中,功能
blitRotate(surf,image,pos,originPos,angle)
执行上述所有步骤,并将旋转后的图像显示到与显示器相关的表面上:

  • surf
    是目标曲面
  • image
    是必须旋转的曲面,并且
    blit
  • pos
    是目标表面上枢轴的位置
    surf
    (相对于
    surf
    的左上角)
  • originPos
    是轴在
    图像
    表面上的位置(相对于
    图像
    的左上角)
  • 角度
    是以度为单位的旋转角度

导入pygame
输入数学
def blitRotate(表面、图像、位置、原始位置、角度):
#计算旋转图像的轴对齐边界框
w、 h=图像。获取大小()
sin_a,cos_a=math.sin(math.radians(angle)),math.cos(math.radians(angle))
min_x,min_y=min([0,sin_a*h,cos_a*w,sin_a*h+cos_a*w]),max([0,sin_a*w,-cos_a*h,sin_a*w-cos_a*h])
#计算轴的平移
pivot=pygame.math.Vector2(originPos[0],-originPos[1])
枢轴旋转=枢轴旋转(角度)
枢轴移动=枢轴旋转-枢轴
#计算旋转图像的左上角原点
原点=(位置[0]-原点位置[0]+最小x轴移动[0],位置[1]-原点位置[1]-最小y轴移动[1])
#得到一个旋转的图像
旋转的_image=pygame.transform.rotate(图像,角度)
#旋转并闪烁图像
冲浪板(旋转的_图像,原点)
pygame.init()
大小=(400400)
screen=pygame.display.set_模式(大小)
clock=pygame.time.clock()
image=pygame.image.load('boomerag64.png')
枢轴=(48,21)
角度,帧=0,0
完成=错误
虽然没有这样做:
时钟滴答(60)
对于pygame.event.get()中的事件:
如果event.type==pygame.QUIT:
完成=正确
屏幕填充(0)
位置=(200+数学余弦(帧*0.05)*100200+数学余弦(帧*0.05)*50)
blitRotate(屏幕、图像、位置、轴、角度)
pygame.draw.line(屏幕,(0,255,0),(位置[0]-20,位置[1]),(位置[0]+20,位置[1]),3)
pygame.draw.line(屏幕,(0,255,0),(位置[0],位置[1]-20),(位置[0],位置[1]+20),3)
pygame.display.flip()
帧+=1
角度+=10
pygame.quit()

同样的算法也可用于a。
在这种情况下,位置(
self.pos
)、枢轴(
self.pivot
)和角度(
self.angle
)是类的实例属性。 在
update
方法中,计算
self.rect
self.image
属性

最简单的例子:

导入pygame
输入数学
类精灵(pygame.sprite.sprite):
定义初始化(自身、图像名称、位置、轴):
super()。\uuuu init\uuuuu()
self.image=pygame.image.load(imageName)
self.original_image=self.image
self.rect=self.image.get_rect(左上方=(位置[0]-轴[0],位置[1]-轴[1]))
self.pos=pos
self.pivot=pivot
自转角=0
def更新(自我):
#计算旋转图像的轴对齐边界框
w、 h=self.original\u image.get\u size()
sin_a,cos_a=math.sin(math.radians(self.angle)),math.cos(math.radians(self.angle))
min_x,min_y=min([0,sin_a*h,cos_a*w,sin_a*h+cos_a*w]),max([0,sin_a*w,-cos_a*h