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