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

发布于 2024-10-03 05:34:02 字数 581 浏览 4 评论 0原文

我一直在尝试使用 pygame.transform.rotate() 围绕其中心旋转图像,但它不起作用。具体来说,挂起的部分是 rot_image = rot_image.subsurface(rot_rect).copy() 。我得到例外:

ValueError:地下矩形外表面区域

以下是用于旋转图像的代码:

def rot_center(image, angle):
    """rotate an image while keeping its center and size"""
    orig_rect = image.get_rect()
    rot_image = pygame.transform.rotate(image, angle)
    rot_rect = orig_rect.copy()
    rot_rect.center = rot_image.get_rect().center
    rot_image = rot_image.subsurface(rot_rect).copy()
    return rot_image

I had been trying to rotate an image around its center in using pygame.transform.rotate() but it's not working. Specifically the part that hangs is rot_image = rot_image.subsurface(rot_rect).copy(). I get the exception:

ValueError: subsurface rectangle outside surface area

Here is the code used to rotate an image:

def rot_center(image, angle):
    """rotate an image while keeping its center and size"""
    orig_rect = image.get_rect()
    rot_image = pygame.transform.rotate(image, angle)
    rot_rect = orig_rect.copy()
    rot_rect.center = rot_image.get_rect().center
    rot_image = rot_image.subsurface(rot_rect).copy()
    return rot_image

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

柠栀 2024-10-10 05:34:02

简短回答:

当您使用 pygame.transform.rotate< /code>与原始图像的大小相比,新旋转图像的大小有所增加。您必须确保旋转图像的放置位置使其中心保持在未旋转图像的中心。为此,获取原始图像的矩形并设置位置。获取旋转图像的矩形,并通过原始矩形的中心设置中心位置。
从函数 red_center 返回一个元组,其中包含旋转图像和旋转图像的边界矩形:

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()

< /a>

现在图像似乎可以任意改变其位置,因为图像的大小通过旋转而改变,并且原点始终是图像边界矩形的左上角。

这可以通过比较旋转之前和旋转之后图像的轴对齐边界框来补偿.
对于以下数学 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< 表示/code>并且可以使用 < 进行旋转代码>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) 执行上述所有步骤并将旋转图像“blit”到表面。

  • surf 是目标 Surface

  • image 是必须旋转和 blit

    的 Surface

  • pos 是目标 Surface 上枢轴的位置 surf(相对于 surf 的左上角)

  • originPos< /code> 是 image 表面上枢轴的位置(相对于 image 的左上角)


  • angle 是以度为单位的旋转角度

这意味着,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()

另请参阅 旋转表面以及问题的答案:

Short answer:

When you use pygame.transform.rotate the size of the new rotated image is increased compared to the size of the original image. You must make sure that the rotated image is placed so that its center remains in the center of the non-rotated image. To do this, get the rectangle of the original image and set the position. Get the rectangle of the rotated image and set the center position through the center of the original rectangle.
Returns a tuple from the function red_center, with the rotated image and the bounding rectangle of the rotated image:

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

Or write a function which rotates and .blit the image:

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)

Long answer:

An image (pygame.Surface) can be rotated by pygame.transform.rotate.

If that is done progressively in a loop, then the image gets distorted and rapidly increases:

while not done:

    # [...]

    image = pygame.transform.rotate(image, 1)
    screen.blit(image, pos)
    pygame.display.flip()

This is because the bounding rectangle of a rotated image is always greater than the bounding rectangle of the original image (except some rotations by multiples of 90 degrees).
The image gets distort because of the multiply copies. Each rotation generates a small error (inaccuracy). The sum of the errors is growing and the images decays.

That can be fixed by keeping the original image and "blit" an image which was generated by a single rotation operation form the original image.

angle = 0
while not done:

    # [...]

    rotated_image = pygame.transform.rotate(image, angle)
    angle += 1

    screen.blit(rotated_image, pos)
    pygame.display.flip()

Now the image seems to arbitrary change its position, because the size of the image changes by the rotation and origin is always the top left of the bounding rectangle of the image.

This can be compensated by comparing the axis aligned bounding box of the image before the rotation and after the rotation.
For the following math pygame.math.Vector2 is used. Note in screen coordinates the y points down the screen, but the mathematical y axis points form the bottom to the top. This causes that the y axis has to be "flipped" during calculations

Set up a list with the 4 corner points of the bounding box:

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

Rotate the vectors to the corner points by pygame.math.Vector2.rotate:

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

Get the minimum and the maximum of the rotated points:

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])

Calculate the "compensated" origin of the upper left point of the image by adding the minimum of the rotated box to the position. For the y coordinate max_box[1] is the minimum, because of the "flipping" along the y axis:

origin = (pos[0] + min_box[0], pos[1] - max_box[1])

rotated_image = pygame.transform.rotate(image, angle)
screen.blit(rotated_image, origin)

It is even possible to define a pivot on the original image. Compute the offset vector from the center of the image to the pivot and rotate the vector. A vector can be represented by pygame.math.Vector2 and can be rotated with pygame.math.Vector2.rotate. Notice that pygame.math.Vector2.rotate rotates in the opposite direction than pygame.transform.rotate. Therefore the angle has to be inverted:

Compute the vector from the center of the image to the pivot:

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

Rotate the vector

rotated_offset = offset_center_to_pivot.rotate(-angle)

Calculate the center of the rotated image:

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

Rotate and blit the image:

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)

In the following example program, the function blitRotate(surf, image, pos, originPos, angle) does all the above steps and "blit" a rotated image to a surface.

  • surf is the target Surface

  • image is the Surface which has to be rotated and blit

  • pos is the position of the pivot on the target Surface surf (relative to the top left of surf)

  • originPos is position of the pivot on the image Surface (relative to the top left of image)

  • angle is the angle of rotation in degrees

This means, the 2nd argument (pos) of blitRotate is the position of the pivot point in the window and the 3rd argument (originPos) is the position of the pivot point on the rotating Surface:


Minimal example: 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()

See also Rotate surface and the answers to the questions:

沐歌 2024-10-10 05:34:02

顶部答案存在一些问题:前一个矩形的位置需要在函数中可用,以便我们可以将其分配给新矩形,例如:

rect = new_image.get_rect(center=rect.center) 

在另一个答案中,位置是通过创建一个新矩形来获取的原始图像,但这意味着它将位于默认 (0, 0) 坐标处。

下面的示例应该可以正常工作。新矩形需要旧矩形的中心位置,因此我们也将其传递给函数。然后旋转图像,调用 get_rect 获取具有正确大小的新矩形,并将旧矩形的 center 属性作为 center 参数传递。最后,将旋转后的图像和新的矩形作为元组返回,并将其解压到主循环中。

import pygame as pg


def rotate(image, rect, angle):
    """Rotate the image while keeping its center."""
    # Rotate the original image without modifying it.
    new_image = pg.transform.rotate(image, angle)
    # Get a new rect with the center of the old rect.
    rect = new_image.get_rect(center=rect.center)
    return new_image, rect


def main():
    clock = pg.time.Clock()
    screen = pg.display.set_mode((640, 480))
    gray = pg.Color('gray15')
    blue = pg.Color('dodgerblue2')

    image = pg.Surface((320, 200), pg.SRCALPHA)
    pg.draw.polygon(image, blue, ((0, 0), (320, 100), (0, 200)))
    # Keep a reference to the original to preserve the image quality.
    orig_image = image
    rect = image.get_rect(center=(320, 240))
    angle = 0

    done = False
    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True

        angle += 2
        image, rect = rotate(orig_image, rect, angle)

        screen.fill(gray)
        screen.blit(image, rect)
        pg.display.flip()
        clock.tick(30)


if __name__ == '__main__':
    pg.init()
    main()
    pg.quit()

这是另一个旋转 pygame 精灵的示例。

import pygame as pg


class Entity(pg.sprite.Sprite):

    def __init__(self, pos):
        super().__init__()
        self.image = pg.Surface((122, 70), pg.SRCALPHA)
        pg.draw.polygon(self.image, pg.Color('dodgerblue1'),
                        ((1, 0), (120, 35), (1, 70)))
        # A reference to the original image to preserve the quality.
        self.orig_image = self.image
        self.rect = self.image.get_rect(center=pos)
        self.angle = 0

    def update(self):
        self.angle += 2
        self.rotate()

    def rotate(self):
        """Rotate the image of the sprite around its center."""
        # `rotozoom` usually looks nicer than `rotate`. Pygame's rotation
        # functions return new images and don't modify the originals.
        self.image = pg.transform.rotozoom(self.orig_image, self.angle, 1)
        # Create a new rect with the center of the old rect.
        self.rect = self.image.get_rect(center=self.rect.center)


def main():
    screen = pg.display.set_mode((640, 480))
    clock = pg.time.Clock()
    all_sprites = pg.sprite.Group(Entity((320, 240)))

    while True:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                return

        all_sprites.update()
        screen.fill((30, 30, 30))
        all_sprites.draw(screen)
        pg.display.flip()
        clock.tick(30)


if __name__ == '__main__':
    pg.init()
    main()
    pg.quit()

There are some problems with the top answer: The position of the previous rect needs to be available in the function, so that we can assign it to the new rect, e.g.:

rect = new_image.get_rect(center=rect.center) 

In the other answer the location is obtained by creating a new rect from the original image, but that means it will be positioned at the default (0, 0) coordinates.

The example below should work correctly. The new rect needs the center position of the old rect, so we pass it as well to the function. Then rotate the image, call get_rect to get a new rect with the correct size and pass the center attribute of the old rect as the center argument. Finally, return both the rotated image and the new rect as a tuple and unpack it in the main loop.

import pygame as pg


def rotate(image, rect, angle):
    """Rotate the image while keeping its center."""
    # Rotate the original image without modifying it.
    new_image = pg.transform.rotate(image, angle)
    # Get a new rect with the center of the old rect.
    rect = new_image.get_rect(center=rect.center)
    return new_image, rect


def main():
    clock = pg.time.Clock()
    screen = pg.display.set_mode((640, 480))
    gray = pg.Color('gray15')
    blue = pg.Color('dodgerblue2')

    image = pg.Surface((320, 200), pg.SRCALPHA)
    pg.draw.polygon(image, blue, ((0, 0), (320, 100), (0, 200)))
    # Keep a reference to the original to preserve the image quality.
    orig_image = image
    rect = image.get_rect(center=(320, 240))
    angle = 0

    done = False
    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True

        angle += 2
        image, rect = rotate(orig_image, rect, angle)

        screen.fill(gray)
        screen.blit(image, rect)
        pg.display.flip()
        clock.tick(30)


if __name__ == '__main__':
    pg.init()
    main()
    pg.quit()

Here's another example with a rotating pygame sprite.

import pygame as pg


class Entity(pg.sprite.Sprite):

    def __init__(self, pos):
        super().__init__()
        self.image = pg.Surface((122, 70), pg.SRCALPHA)
        pg.draw.polygon(self.image, pg.Color('dodgerblue1'),
                        ((1, 0), (120, 35), (1, 70)))
        # A reference to the original image to preserve the quality.
        self.orig_image = self.image
        self.rect = self.image.get_rect(center=pos)
        self.angle = 0

    def update(self):
        self.angle += 2
        self.rotate()

    def rotate(self):
        """Rotate the image of the sprite around its center."""
        # `rotozoom` usually looks nicer than `rotate`. Pygame's rotation
        # functions return new images and don't modify the originals.
        self.image = pg.transform.rotozoom(self.orig_image, self.angle, 1)
        # Create a new rect with the center of the old rect.
        self.rect = self.image.get_rect(center=self.rect.center)


def main():
    screen = pg.display.set_mode((640, 480))
    clock = pg.time.Clock()
    all_sprites = pg.sprite.Group(Entity((320, 240)))

    while True:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                return

        all_sprites.update()
        screen.fill((30, 30, 30))
        all_sprites.draw(screen)
        pg.display.flip()
        clock.tick(30)


if __name__ == '__main__':
    pg.init()
    main()
    pg.quit()
筑梦 2024-10-10 05:34:02

您正在删除旋转创建的矩形。您需要保留矩形,因为它在旋转时会改变大小。

如果您想保留对象位置,请执行以下操作:

def rot_center(image, angle):
    """rotate a Surface, maintaining position."""
    
    loc = image.get_rect().center  #rot_image is not defined 
    rot_sprite = pygame.transform.rotate(image, angle)
    rot_sprite.get_rect().center = loc
    return rot_sprite
    
    # or return tuple: (Surface, Rect)
    # return rot_sprite, rot_sprite.get_rect()

You are deleting the rect that rotate creates. You need to preserve rect, since it changes size when rotated.

If you want to preserve the objects location, do:

def rot_center(image, angle):
    """rotate a Surface, maintaining position."""
    
    loc = image.get_rect().center  #rot_image is not defined 
    rot_sprite = pygame.transform.rotate(image, angle)
    rot_sprite.get_rect().center = loc
    return rot_sprite
    
    # or return tuple: (Surface, Rect)
    # return rot_sprite, rot_sprite.get_rect()
我也只是我 2024-10-10 05:34:02

在 pygame 中绘制图像所需的一切

game_display = pygame.display.set_mode((800, 600))

x = 0
y = 0
angle = 0

img = pygame.image.load("resources/image.png")
img = pygame.transform.scale(img, (50, 50)) # image size

def draw_img(self, image, x, y, angle):
    rotated_image = pygame.transform.rotate(image, angle) 
    game_display.blit(rotated_image, rotated_image.get_rect(center=image.get_rect(topleft=(x, y)).center).topleft)

# run this method with your loop
def tick():
    draw_img(img, x, y, angle)

Everything you need for drawing an image in pygame

game_display = pygame.display.set_mode((800, 600))

x = 0
y = 0
angle = 0

img = pygame.image.load("resources/image.png")
img = pygame.transform.scale(img, (50, 50)) # image size

def draw_img(self, image, x, y, angle):
    rotated_image = pygame.transform.rotate(image, angle) 
    game_display.blit(rotated_image, rotated_image.get_rect(center=image.get_rect(topleft=(x, y)).center).topleft)

# run this method with your loop
def tick():
    draw_img(img, x, y, angle)
じее 2024-10-10 05:34:02

发现问题:示例效果很好,但宽度和高度需要相同的尺寸。修复了图片就可以了。

Found the problem: Example works good, but needs equal dimensions for width and height. Fixed pictures and it works.

山田美奈子 2024-10-10 05:34:02

我必须如下修改 skrx 解决方案,这种方法对我有用。

angle=0
roll = true
while roll:
    # clean surface with your background color
    gameDisplay.fill(color)
    self.image = yourImage
    rotate_image = pygame.transform.rotate(self.image, angle)
    rect = rotate_image.get_rect()
    pos = (((your_surface_width - rect.width)/2),((your_surface_height - rect.height)/2))
    gameDisplay.blit(rotate_image,pos)
    pygame.display.flip()
    angle+=2
    if angle == 360:
        roll=False 

I had to modify skrx solution as below, this way works for me.

angle=0
roll = true
while roll:
    # clean surface with your background color
    gameDisplay.fill(color)
    self.image = yourImage
    rotate_image = pygame.transform.rotate(self.image, angle)
    rect = rotate_image.get_rect()
    pos = (((your_surface_width - rect.width)/2),((your_surface_height - rect.height)/2))
    gameDisplay.blit(rotate_image,pos)
    pygame.display.flip()
    angle+=2
    if angle == 360:
        roll=False 
寂寞花火° 2024-10-10 05:34:02

旋转图像时的另一个重要点是图像必须具有 Alpha 通道。许多人使用矩形、均匀填充的表面来测试他们的代码,而忘记了 Alpha 通道。这会产生一个看似随机拉伸的矩形。问题的答案解释了如何创建带有 alpha 通道的表面:pygame 不不旋转表面。在示例中,我创建了 pygame.Surface使用 pygame.SRCALPHA 标志来获取带有 alpha 通道的图像:

surface = pygame.Surface((100, 50), pygame.SRCAPLHA)

第二个重要的事情是您绝不能重复旋转 pygame.Surface 对象,因为这会导致不断增加的 pygame.Surface 和扭曲,但您必须保存原始曲面并始终从中创建旋转的 pygame.Surface 。请参阅以下示例,其中我使用 pygame.sprite< /a> 模块:

import pygame

class Player(pygame.sprite.Sprite):
    def __init__(self, image, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.original_image = image
        self.image = self.original_image
        self.rect = self.image.get_rect(center = (x, y))
        self.angle = 0
    def update(self):
        self.image = pygame.transform.rotate(self.original_image, self.angle)
        self.rect = self.image.get_rect(center=self.rect.center)
        self.angle = (self.angle + 1) % 360

pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()

surface = pygame.Surface((100, 50), pygame.SRCALPHA)
surface.fill("black")
player = Player(surface, *window.get_rect().center)
all_sprites = pygame.sprite.Group(player)

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    all_sprites.update()

    window.fill((255, 255, 255))
    all_sprites.draw(window)
    pygame.display.flip()

pygame.quit()
exit()

Another important point when rotating an image is that the image must have an alpha channel. Many people use rectangular, uniformly filled surfaces to test their code, forgetting about the alpha channel. This results in what appears to be a randomly stretched rectangle. How to create a surface with an alpha channel is explained in the answer to the question: pygame doesn't rotate surface. In the example I create the pygame.Surface with the pygame.SRCALPHA flag to get an image with an alpha channel:

surface = pygame.Surface((100, 50), pygame.SRCAPLHA)

The second important thing is that you must never rotate a pygame.Surface object repeatedly, because this leads to an ever increasing pygame.Surface and distortions, but you must save the original surface and always create a rotated pygame.Surface from it. See the following example, where I use the pygame.sprite module:

import pygame

class Player(pygame.sprite.Sprite):
    def __init__(self, image, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.original_image = image
        self.image = self.original_image
        self.rect = self.image.get_rect(center = (x, y))
        self.angle = 0
    def update(self):
        self.image = pygame.transform.rotate(self.original_image, self.angle)
        self.rect = self.image.get_rect(center=self.rect.center)
        self.angle = (self.angle + 1) % 360

pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()

surface = pygame.Surface((100, 50), pygame.SRCALPHA)
surface.fill("black")
player = Player(surface, *window.get_rect().center)
all_sprites = pygame.sprite.Group(player)

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    all_sprites.update()

    window.fill((255, 255, 255))
    all_sprites.draw(window)
    pygame.display.flip()

pygame.quit()
exit()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文