在 pygame 中旋转一个矩形(不是图像)

Rotating a rectangle (not image) in pygame

在 pygame 中,我对程序中的所有矩形使用 pygame.draw.rect(screen, color, rectangle)。我希望能够将这些矩形旋转到任意角度。我看过以下代码来旋转 IMAGES,但我的问题是 RECTANGLES

pygame.transform.rotate(image, angle)

但我正在处理矩形,我没有可以旋转的图像或 "surface"。当我尝试使用

旋转矩形时
rect = pygame.draw.rect(screen, self.color, self.get_rectang())
rotatedRect = pygame.transform.rotate(rect, self.rotation)
screen.blit(rotatedRect)

这在 .rotate()

的行上给出 TypeError: must be pygame.Surface, not pygame.Rect

我的问题是,如何在 pygame.

中旋转并显示 RECTANGLE(x,y,w,h),而不是图像

这是 "potential duplicate" 的链接 post 不是重复项。一个答案解释了旋转矩形的后果,另一个使用旋转图像的代码。

在这里查看第二个答案:Rotating a point about another point (2D)

我认为矩形只能是水平的或垂直的。您需要定义角并旋转它们,然后在它们之间绘制和填充。

另一种方法是 class

class myRect(pygame.Surface):
    def __init__(self, parent, xpos, ypos, width, height):
      super(myRect, self).__init__(width, height)
      self.xpos = xpos
      self.ypos = ypos
      self.parent = parent

    def update(self, parent):
      parent.blit(self, (self.xpos, self.ypos))

    def rotate(self, angle):
      #(your rotation code goes here)

并改用它,因为这样您就可以使用变换功能旋转它。

import pygame as py  

# define constants  
WIDTH = 500  
HEIGHT = 500  
FPS = 30  

# define colors  
BLACK = (0 , 0 , 0)  
GREEN = (0 , 255 , 0)  

# initialize pygame and create screen  
py.init()  
screen = py.display.set_mode((WIDTH , HEIGHT))  
# for setting FPS  
clock = py.time.Clock()  

rot = 0  
rot_speed = 2  

# define a surface (RECTANGLE)  
image_orig = py.Surface((100 , 100))  
# for making transparent background while rotating an image  
image_orig.set_colorkey(BLACK)  
# fill the rectangle / surface with green color  
image_orig.fill(GREEN)  
# creating a copy of orignal image for smooth rotation  
image = image_orig.copy()  
image.set_colorkey(BLACK)  
# define rect for placing the rectangle at the desired position  
rect = image.get_rect()  
rect.center = (WIDTH // 2 , HEIGHT // 2)  
# keep rotating the rectangle until running is set to False  
running = True  
while running:  
    # set FPS  
    clock.tick(FPS)  
    # clear the screen every time before drawing new objects  
    screen.fill(BLACK)  
    # check for the exit  
    for event in py.event.get():  
        if event.type == py.QUIT:  
            running = False  

    # making a copy of the old center of the rectangle  
    old_center = rect.center  
    # defining angle of the rotation  
    rot = (rot + rot_speed) % 360  
    # rotating the orignal image  
    new_image = py.transform.rotate(image_orig , rot)  
    rect = new_image.get_rect()  
    # set the rotated rectangle to the old center  
    rect.center = old_center  
    # drawing the rotated rectangle to the screen  
    screen.blit(new_image , rect)  
    # flipping the display after drawing everything  
    py.display.flip()  

py.quit()  

基础pygame功能的快速替换添加旋转:

def rectRotated( surface, color, pos, fill, border_radius, angle ):
    """
    - angle in degree
    """
    max_area = max(pos[2],pos[3])
    s = pg.Surface((max_area,max_area))
    s = s.convert_alpha()
    s.fill((0,0,0,0))
    pg.draw.rect(s, color,(0,0,pos[2],pos[3]),fill, border_radius=border_radius)
    s = pygame.transform.rotate(s,angle)
    surface.blit( s, (pos[0],pos[1]) )

快速替换的更复杂版本,您可以在其中为矩形定义任意旋转中心点 - 甚至在矩形之外(在 python3 中测试):

    def rectRotated( surface, color, pos, fill, border_radius, rotation_angle, rotation_offset_center = (0,0), nAntialiasingRatio = 1 ):
        """
        - rotation_angle: in degree
        - rotation_offset_center: moving the center of the rotation: (-100,0) will turn the rectangle around a point 100 above center of the rectangle,
                                             if (0,0) the rotation is at the center of the rectangle
        - nAntialiasingRatio: set 1 for no antialising, 2/4/8 for better aliasing
        """
        nRenderRatio = nAntialiasingRatio
        
        sw = pos[2]+abs(rotation_offset_center[0])*2
        sh = pos[3]+abs(rotation_offset_center[1])*2

        surfcenterx = sw//2
        surfcentery = sh//2
        s = pg.Surface( (sw*nRenderRatio,sh*nRenderRatio) )
        s = s.convert_alpha()
        s.fill((0,0,0,0))
        
        rw2=pos[2]//2 # halfwidth of rectangle
        rh2=pos[3]//2

        pg.draw.rect( s, color, ((surfcenterx-rw2-rotation_offset_center[0])*nRenderRatio,(surfcentery-rh2-rotation_offset_center[1])*nRenderRatio,pos[2]*nRenderRatio,pos[3]*nRenderRatio), fill*nRenderRatio, border_radius=border_radius*nRenderRatio )
        s = pygame.transform.rotate( s, rotation_angle )        
        if nRenderRatio != 1: s = pygame.transform.smoothscale(s,(s.get_width()//nRenderRatio,s.get_height()//nRenderRatio))
        incfromrotw = (s.get_width()-sw)//2
        incfromroth = (s.get_height()-sh)//2
        surface.blit( s, (pos[0]-surfcenterx+rotation_offset_center[0]+rw2-incfromrotw,pos[1]-surfcentery+rotation_offset_center[1]+rh2-incfromroth) )
        

您不能旋转由 pygame.draw.rect. You have to create a transparent pygame.Surface 绘制的矩形并旋转 Surface:

rect_surf = pygame.Surface((widht, height), pygame.SRCLAPHA)
rect_surf.fill(color)

参见 How do I rotate an image around its center using PyGame?,旋转 表面

此代码模拟旋转的矩形落向地面。我在我的一个游戏中使用它来使背景看起来很棒

import pygame
import random

class Square(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super(Square, self).__init__()

        self.win = win
        self.color = (128, 128, 128)
        self.speed = 3
        self.angle = 0

        self.side = random.randint(15, 40)

        self.surface = pygame.Surface((self.side, self.side), pygame.SRCALPHA)
        self.surface.set_colorkey((200,200,200))
        self.rect = self.surface.get_rect(center=(x, y))

    def update(self, win):
        center = self.rect.center
        self.angle = (self.angle + self.speed) % 360
        image = pygame.transform.rotate(self.surface , self.angle)
        self.rect = image.get_rect()
        self.rect.center = center

        self.rect.y += 1.5

        if self.rect.top >= HEIGHT:
            self.kill()

        pygame.draw.rect(self.surface, self.color, (0,0, self.side, self.side), 4)
        win.blit(image, self.rect)

if __name__ == '__main__':
    pygame.init()
    SCREEN = WIDTH, HEIGHT = 288, 512
    win = pygame.display.set_mode(SCREEN, pygame.NOFRAME)

    clock = pygame.time.Clock()
    FPS = 60
    count = 0

    square_group = pygame.sprite.Group()

    running = True
    while running:
        win.fill((200,200,200))

        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    running = False

        count += 1
        if count % 100 == 0:
            x = random.randint(40, WIDTH-40)
            y = 0
            square = Square(x, y)
            square_group.add(square)
            count = 0

        square_group.update(win)

        pygame.draw.rect(win, (30,30,30), (0, 0, WIDTH, HEIGHT), 8)
        clock.tick(FPS)
        pygame.display.update()
pygame.quit()

这是输出,虽然它不是 gif

现在,如果您想要填充颜色的矩形而不是仅带边框的矩形,请在第 31 行更新此行

pygame.draw.rect(self.surface, self.color, (0,0, self.side, self.side))

如果你不想让矩形掉下来评论第 26 行