如何移动 Pygame 对象并将其擦除到之前的位置?

How to move a Pygame object and erase it in its previous position?

我正在尝试构建一个游戏,其中包含一个由箭头键控制的红色小玩家(矩形)。黑色背景上有一个白色网格、2 个不同颜色的目标(矩形)和几个随机的红色框(矩形)。

我需要帮助的部分是移动红色小播放器。我可以移动它,但它似乎会在新位置绘制自己,但之前绘制的矩形版本仍保留在那里,形成一条线。我希望整个矩形移动并且不留下任何 traces/previous 版本的自身。

根据其他一些帖子,我听说这样做的唯一方法是用背景色(在本例中为黑色)填充屏幕并在其上重新绘制玩家;然而,这对我来说真的很难,因为我的红色框和目标是随机放置的,所以每次我再次绘制它们时,它们都会绘制到一个新的随机位置,而不是原来的位置。我希望红色框和目标保持在相同位置,但让播放器矩形四处移动(同时基本上删除它们自己的旧版本)。

这是我目前拥有的代码(我排除了基础知识,例如定义颜色、导入和设置屏幕 height/width):

p1_velocity_x = 0
p1_velocity_y = 0
p2_velocity_x = 0
p2_velocity_y = 0


def grid():
    for col in range(0, screen_width - 100, 10):
        for row in range(0, screen_height, 10):
            screen.set_at((row, col), white)


def red_boxes():
    for i in range(100):
        pygame.draw.rect(screen, red, (randrange(1, 1200), randrange(1, 470), 25, 25))


def blue_score_box():
    pygame.draw.rect(screen, blue, (randrange(1, 1200), randrange(1, 470), 25, 25))


def yellow_score_box():
    pygame.draw.rect(screen, yellow, (randrange(1, 1200), randrange(1, 470), 25, 25))


class Player:
    color = (0, 0, 0)

    def __init__(self, color):
        self.x = 0
        self.y = 0
        self.color = color


p1 = Player(red)
p1.x = randrange(1, 1200, 10)
p1.y = randrange(1, 470, 10)

p2 = Player(yellow)
p2.x = randrange(1, 1200, 10)
p2.y = randrange(1, 470, 10)


while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                p1.x += 10

    screen.fill(black)
    grid()
    red_boxes()
    yellow_score_box()
    blue_score_box()

    pygame.draw.rect(screen, p1.color, (p1.x, p1.y, 10, 10))
    pygame.draw.rect(screen, p2.color, (p2.x, p2.y, 10, 10))

    pygame.display.update()

以上代码的结果是我可以根据需要移动红色矩形,但是由于我调用了 red_boxes()、yellow_score_box() 和 [= while 循环中的 26=]() 方法,它们会无限期地调用,几乎每秒都会在屏幕上绘制随机的红色、蓝色和黄色矩形。我希望他们保持在一个地方,同时像我现在一样拥有移动播放器的功能。

创建一个 pygame.Surface 大小与红色播放器矩形相同的大小:

bkP1 = pygame.Surface((10, 10))

备份背景(pygame.Surface.blit)并存储玩家的位置,在绘制玩家之前:

prevPos = (p1.x, p1.y)
bkP1.blit(screen, (0, 0), (*prevPos, 10, 10))

当必须擦除播放器时,在播放器顶部绘制背景:

screen.blit(bkP1, prevPos)

流程可能如下:

prevPos = None
bkP1 = pygame.Surface((10, 10))

while True:

    # [...]

    if prevPos:
        screen.blit(bkP1, prevPos)
    prevPos = (p1.x, p1.y)
    bkP1.blit(screen, (0, 0), (*prevPos, 10, 10))
    pygame.draw.rect(screen, p1.color, (p1.x, p1.y, 10, 10))

当然可以将机制添加到 class Player:

class Player:

    def __init__(self, color):
        self.x = 0
        self.y = 0
        self.color = color
        self. prevPos = None
        self.bk = pygame.Surface((10, 10))

    def draw(self, screen):
        if self.prevPos:
            screen.blit(self.bk, self.prevPos)
        self.prevPos = (self.x, self.y)
        self.bk.blit(screen, (0, 0), (*self.prevPos, 10, 10))
        pygame.draw.rect(screen, self.color, (self.x, self.y, 10, 10))

while True:

    # [...]

    p1.draw(screen)