首页 > 解决方案 > Pygame中的边界块

问题描述

我正在尝试在 pygame 中制作一些带有黑色边框的简单块。我所做的方法是创建一个矩形,然后填充它两次,一次使用轮廓颜色(黑色),然后再次使用实际块颜色(但使用 rect.inflate())仅填充一个子集块,从而产生边界。我的问题是:当我只做一个街区时,这就像一种魅力。然而,连续制作更多会导致第一个块被正确制作,而其他块只是全黑,我不明白。我产生此问题的 MWE 如下:

import pygame

class Block(pygame.sprite.Sprite):
    def __init__(self, area, pos):
        super().__init__()
        self.area = area
        self.pos = pos
        self.image = pygame.Surface(self.area)
        self.rect = self.image.get_rect(topleft = self.pos)

def draw_brick(brick, outline_color, fill_color):
    # Fill with the outline color
    brick.image.fill(outline_color, brick.rect)
    # Fill with the actual block color
    brick.image.fill(fill_color, brick.rect.inflate(-10, -10))
    return brick.image

def get_brick(area, pos, outline_color, fill_color):
    # Create brick object
    b = Block(area, pos)
    # Draw the object
    b.image = draw_brick(b, outline_color, fill_color)
    return b


# Initialize
pygame.init()

# Set up screen
screen = pygame.display.set_mode((960, 540))

# Colors
white = [255,255,255]
black = [0,0,0]
red = [255,0,0]

# Clock
clock = pygame.time.Clock()

# Make bricks
nbricks = 2
length = int(960. / nbricks)
width = 54
area = (length, width)
y = 0
bricks = []
for i in range(nbricks):
    x = i * (length + 1)
    pos = (x, y)
    bricks.append(get_brick(area, pos, black, red))

# Main loop
running = True

while running:
    # Check for events
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    # Draw to screen
    screen.fill(white)
    for b in bricks:
        screen.blit(b.image, (b.rect.x, b.rect.y))
    pygame.display.flip()
    clock.tick(60)

# Clean up
pygame.quit()

我尝试使用 pdb 单步执行并检查每个块的矩形(和膨胀的矩形)的左上、右上、左下、右下和中心属性是否正确。这些块被绘制在正确的位置,但是第二个块的颜色是全黑的,而不是像第一个块那样带有黑色边框的红色,这让我感到困惑。谢谢!

标签: pythonpygame

解决方案


我已经弄清楚出了什么问题。在您的代码中:

self.rect = self.image.get_rect(topleft = self.pos)

self.rect将获取图像的大小以及应该使用self.pos.

以下代码使用它来使其中心着色。

def draw_brick(brick, outline_color, fill_color):
    # Fill with the outline color
    brick.image.fill(outline_color, brick.rect)
    # Fill with the actual block color
    brick.image.fill(fill_color, brick.rect.inflate(-10, -10))
    return brick.image

brick.rect返回应该填充颜色的位置。brick.rect错误地将颜色放在错误的位置。

试试这个:

import pygame

class Block(pygame.sprite.Sprite):
    def __init__(self, area, pos):
        super().__init__()
        self.area = area
        self.pos = pos
        self.image = pygame.Surface(self.area)
        self.rect = self.image.get_rect()  # note the removed 'topleft = self.pos'

def draw_brick(brick, outline_color, fill_color):
    # Fill with the outline color
    brick.image.fill(outline_color, brick.rect)
    # Fill with the actual block color
    brick.image.fill(fill_color, brick.rect.inflate(-10, -10))
    return brick.image

def get_brick(area, pos, outline_color, fill_color):
    # Create brick object
    b = Block(area, pos)
    # Draw the object
    b.image = draw_brick(b, outline_color, fill_color)
    return b


# Initialize
pygame.init()

# Set up screen
screen = pygame.display.set_mode((960, 540))

# Colors
white = [255,255,255]
black = [0,0,0]
red = [255,0,0]

# Clock
clock = pygame.time.Clock()

# Make bricks
nbricks = 2
length = int(960. / nbricks)
width = 54
area = (length, width)
y = 0
bricks = []
for i in range(nbricks):
    x = i * (length + 1)
    pos = (x, y)
    bricks.append(get_brick(area, pos, black, red))

# Main loop
running = True

while running:
    # Check for events
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    # Draw to screen
    screen.fill(white)
    for b in bricks:
        screen.blit(b.image, b.pos)        # note it uses b.pos instead of b.rect
    pygame.display.flip()
    clock.tick(60)

# Clean up
pygame.quit()

推荐阅读