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

Posted

技术标签:

【中文标题】在pygame中旋转一个矩形(不是图像)【英文标题】:Rotating a rectangle (not image) in pygame 【发布时间】:2016-04-08 23:15:45 【问题描述】:

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

pygame.transform.rotate(image, angle)

但我正在使用矩形,我没有可以旋转的图像或“表面”。当我尝试用

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

这使得TypeError: must be pygame.Surface, not pygame.Rect 与 .rotate() 一致

我的问题是,如何在 pygame 中旋转并显示 RECTANGLE(x,y,w,h),而不是图像。

这是“潜在重复”的链接帖子不是重复的。一个答案解释了旋转矩形的后果,另一个使用代码来旋转图像。

【问题讨论】:

您可以像这样自己旋转 4 个点中的每一个 x2= cos a * x1 - sin a y1 y2= sin a *x1 + cos a y1,但是 rectangle 函数可能只绘制一个与轴对齐的矩形,所以你必须看用于多边形绘图功能。或者,您可以制作带有可见轮廓和透明填充 (alpha) 的surface,这可能更容易。 rectangle 可能只是 pygame 中的辅助函数,不能直接显示,所以最后一行有两个单独的问题。 我在发布我的问题之前阅读了这一点。这不是重复的,看看答案,他们解释了如何旋转图像。这是来自image2 = pygame.transform.rotate(image1, angle) 答案之一的引述,而接受的答案并没有解释任何关于实际旋转矩形的内容,只是一些意想不到的后果 @roadrunner66 我希望我能够避免在多边形中进行三角和绘图点,但我很欣赏这个建议,如果没有更简单的方法,我会这样做 问题是重复的,因为您无法旋转矩形。您必须创建一个透明的 Surface 并旋转 Surface。 【参考方案1】:

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

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

另一种方法是创建一个类

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)

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

【讨论】:

【参考方案2】:
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()  

【讨论】:

【参考方案3】:

快速替换的更复杂版本,您可以在其中为矩形定义任意旋转中心点 - 甚至在矩形之外(在 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) )
        

【讨论】:

【参考方案4】:

添加旋转的基本 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]) )

【讨论】:

【参考方案5】:

您不能旋转由pygame.draw.rect 绘制的矩形。你必须创建一个透明的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?,以旋转表面

【讨论】:

【参考方案6】:

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

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 行注释掉下来

【讨论】:

以上是关于在pygame中旋转一个矩形(不是图像)的主要内容,如果未能解决你的问题,请参考以下文章

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

如何在pygame中检测两个矩形对象或图像之间的碰撞

如何在 Pygame 中检查变量是不是包含矩形? [复制]

使用pygame旋转图像[重复]

Pygame,围绕中心旋转使图像消失

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