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

2024-01-06

我想围绕一个枢轴旋转图像,该枢轴不在图像的中心Surface https://www.pygame.org/docs/ref/surface.html in Pygame https://www.pygame.org/news.
枢轴是图像中的绿色十字:

我知道游戏窗口中枢轴的位置。 如何跟踪此时的图像并同时围绕该点旋转它。

image = pygame.image.load("boomerang64.png")
pos = (200, 200)
angle = 0

while True:
    # [...]

    rotate_rect, rotate_image = ???? # rotate around green cross by angle 
    surf.blit(rotated_image, rotate_rect)
    angle += 1

    # [...]

首先是枢轴的位置Surface必须定义:

image = pygame.image.load("boomerang64.png") # 64x64 surface
pivot = (48, 21)                             # position of the pivot on the image

当图像旋转时,其尺寸会增加。我们必须比较轴对齐边界框 https://en.wikipedia.org/wiki/Minimum_bounding_box旋转前和旋转后的图像。
对于下面的数学pygame.math.Vector2 https://www.pygame.org/docs/ref/math.html用来。请注意,在屏幕坐标中,y 指向屏幕下方,但数学上的 y 轴点从底部到顶部。这导致在计算过程中必须“翻转”y 轴。请注意pygame.math.Vector2.rotate沿相反方向旋转pygame.transform.rotate。因此必须反转角度。

设置一个包含边界框 4 个角点的列表,并将向量旋转到角点pygame.math.Vector2.rotate https://www.pygame.org/docs/ref/math.html#pygame.math.Vector2.rotate。最后找到旋转框的最小值。由于 pygame 中的 y 轴指向下方,因此必须通过找到旋转反转高度的最大值(“最大(旋转(-h))"):

计算从图像中心到枢轴的向量:

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)执行上述所有步骤并且blit https://www.pygame.org/docs/ref/surface.html#pygame.Surface.blit旋转图像到与显示器关联的 Surface:

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

def blitRotate(surf, image, pos, originPos, angle):
    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)
    surf.blit(rotated_image, rotated_image_rect)
  
pygame.init()
size = (400,400)
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()

image = pygame.image.load('Boomerang64.png')
pivot = (48, 21)

angle, frame = 0, 0
done = False
while not done:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
    screen.fill(0)

    pos = (200 + math.cos(frame * 0.05)*100, 200 + math.sin(frame * 0.05)*50)
    blitRotate(screen, image, pos, pivot, angle)

    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()
    frame += 1
    angle += 10
    
pygame.quit()
exit()

相同的算法可用于Sprite https://www.pygame.org/docs/ref/sprite.html#pygame.sprite.Sprite, too.
在这种情况下,位置(self.pos), 枢轴 (self.pivot)和角度(self.angle) 是类的实例属性。 在里面update方法self.rect and self.image计算属性。

Minimal example: repl.it/@Rabbid76/PyGame-RotateSpriteAroundOffCenterPivot

import math
import pygame

class SpriteRotate(pygame.sprite.Sprite):

    def __init__(self, imageName, origin, pivot):
        super().__init__() 
        self.image = pygame.image.load(imageName)
        self.original_image = self.image
        self.rect = self.image.get_rect(topleft = (origin[0]-pivot[0], origin[1]-pivot[1]))
        self.origin = origin
        self.pivot = pivot
        self.angle = 0

    def update(self):
        
        # offset from pivot to center
        image_rect = self.original_image.get_rect(topleft = (self.origin[0] - self.pivot[0], self.origin[1]-self.pivot[1]))
        offset_center_to_pivot = pygame.math.Vector2(self.origin) - image_rect.center
        
        # roatated offset from pivot to center
        rotated_offset = offset_center_to_pivot.rotate(-self.angle)

        # roatetd image center
        rotated_image_center = (self.pos[0] - rotated_offset.x, self.pos[1] - rotated_offset.y)

        # get a rotated image
        self.image  = pygame.transform.rotate(self.original_image, self.angle)
        self.rect   = self.image.get_rect(center = rotated_image_center)
        self.angle += 10
  
pygame.init()
size = (400,400)
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()

boomerang = SpriteRotate('Boomerang64.png', (200, 200), (48, 21))
all_sprites = pygame.sprite.Group(boomerang)

frame = 0
done = False
while not done:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
    
    pos = (200 + math.cos(frame * 0.05)*100, 200 + math.sin(frame * 0.05)*50)
    boomerang.pos = pos
    all_sprites.update()

    screen.fill(0)
    
    all_sprites.draw(screen)
    #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()
    frame += 1
    
pygame.quit()
exit()

如何使用 Pygame 围绕图像中心旋转图像? https://stackoverflow.com/questions/4183208/how-do-i-rotate-an-image-around-its-center-using-pygame
如何在图像尺寸变大时绕其中心旋转图像(在 Pygame 中) https://stackoverflow.com/questions/54462645/how-to-rotate-an-image-around-its-center-while-its-scale-is-getting-largerin-py

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Pygame 中围绕偏心轴旋转图像 的相关文章

随机推荐

  • 如何在 Binding 中加载控件而不阻塞 UI?

    我有这种情况 我想在主窗口的 ViewModel 中加载一个集合 我有一个大数据 所以当我进入人员集合的幻灯片时 它应该等待完成加载 然后我可以看到完整的列表 我有以下内容 在 xaml 代码中我有
  • 无法读取未定义的属性“totalPrice”

    我的 Angular 2 模板上有这段代码 td class hidden xs text center strong Total 8369 carts totalPrice strong td 当我登录时carts totalPrice在
  • 带有动态子项的 Flutter 可滚动布局

    我想创建一个通用布局 它接受子 Widget 作为参数 其内容布局如下 我在顶部有一个应用程序栏 有一个标题 标题 下面是内容 可以是任何内容 在底部 我有一个带有几个按钮的列 如果内容对于屏幕来说太大 则除 AppBar 之外的所有这些小
  • 什么时候需要 TCP 选项 SO_LINGER (0)?

    我想我理解该选项的正式含义 在我现在处理的一些遗留代码中 使用了该选项 客户抱怨 RST 是其一侧对 FIN 的响应 其连接距离其一侧较近 我不确定是否可以安全地删除它 因为我不知道何时应该使用它 您能否举例说明何时需要该选项 对于我的建议
  • C - 函数类型冲突错误

    我是 C 新手 我试图从用户那里获取大量文本并计算单词 字符 行 空格和字母的数量 这就是我所做的 include
  • 通过 webhook 接收关于创建和删除 Outlook 事件的额外更新更改通知

    我希望收到有关创建 更新和删除 Outlook 事件的更改通知 我通过以下方式创建了订阅https learn microsoft com en us graph change notifications delivery webhooks
  • 从给定的日期范围列表中查找所有重叠的日期范围

    我有一个 BookingDateRange 列表 其中 BookingDateRange 是 public class BookingDateRange private Date fromDate private Date toDate g
  • 如何使用msbuild替换文件中的字符串?

    我想用另一个文件 xy xml 中的字符串 i am Fine 替换文件 test xml 中的 how r u 等字符串 在 ms build 中使用正则表达式 即我必须从一个文件 xy xml 读取字符串并将其替换为另一个文件test
  • Google App Engine - 缓存生成的 HTML

    我编写了一个 Google App Engine 应用程序 它以编程方式生成一堆 HTML 代码 对于登录到我的系统的每个用户来说 这些代码实际上是相同的输出 而且我知道当代码投入生产时 这将是低效的 因此 我试图找出缓存生成页面的最佳方法
  • 处理中带有 Alpha 通道的视频

    我想知道是否有人可以出色地帮助我完成我正在做的事情Processing 我需要在实时源上播放带有透明度的视频文件 以便视频不仅仅是一个矩形 这是我认为需要添加或更改的代码部分 我对这一切都非常陌生 我非常感谢任何可以提供帮助的人 如果您的视
  • C#:异常 - 参数无效 - 表单 Dispose 方法

    在处置时object of a form从另一个exception正在投掷像Parameter is not valid 访问第二种形式的代码 Assembly X Assembly LoadFile Application Startup
  • 在同级元素的单击事件上从内存中删除 Image() 对象 - JavaScript

    我有一个使用 JavaScript 的图像预览器Image 对象在使用 PHP 处理之前预览图像 我有一个包含 x SVG 图形的 div 该图形的目标是通过单击事件来删除图像 在下面的代码中 它使用的函数底部evt target如果用户愿
  • 将 dll 添加到引用后,类库智能感知未显示

    在 C 中 我创建了一个具有一个命名空间和一个类的 ClassLibrary 我保存并构建了它 在其他项目中 当我使用它时 我通过浏览到 dll 位置将其添加到我的引用中 但问题是它的名字没有出现在智能感知中 即当我 using 我的dll
  • 将数据库部署到 Azure SQL 失败,找不到 sp_MSforeachtable

    我正在尝试使用发布 SQL Server 数据库 dacpac并将配置文件发布到 Azure SQL 数据库 我们已经使用本地 SQL Server 很长一段时间了 没有出现任何问题 现在我们正在评估 Azure 和 AWS 看看哪一个最适
  • 阻止所有混合内容

    我怎样才能完全防止任何混合内容 https developer mozilla org en US docs Web Security Mixed content从加载 当前的浏览器已经被阻止active混合内容 脚本 我真正想要的是阻止所
  • 由于 Yoga 错误,React Native iOS 构建失败

    我从博览会中退出到纯反应本机项目 IOS 项目未按预期运行 我得到的错误是 ReactCommon yoga yoga YGEnums h No such file or directory 更多错误如下所示 error Failed to
  • 如何在 Android 中自定义权限对话框?

    假设我在运行时请求如下所示的权限 ActivityCompat requestPermissions thisActivity new String Manifest permission READ CONTACTS MY PERMISSI
  • Opencart 登录后登录到上一个查看的页面?

    Opencart 登录后登录到上一个查看的页面 有人知道可以做到这一点的方法吗 正在开发版本 1 5 4 希望有人可以建议 帮助 Thanks 为了实现这个场景 用户单击登录链接 用户填写登录表单并单击提交按钮 他登录后 您希望他重定向到他
  • 使用卡方检验在文档特征矩阵中进行特征选择

    我正在使用自然语言处理进行短信挖掘 我用了quanteda包生成文档特征矩阵 dfm 现在我想使用卡方检验进行特征选择 我知道已经有很多人问过这个问题了 但是 我找不到相关的代码 答案只是给出了一个简短的概念 如下所示 https stat
  • 如何在 Pygame 中围绕偏心轴旋转图像

    我想围绕一个枢轴旋转图像 该枢轴不在图像的中心Surface https www pygame org docs ref surface html in Pygame https www pygame org news 枢轴是图像中的绿色十