如何在一个函数中调用另一个函数内定义的对象方法?(Pygame场景)
如何在PyGame中正确绘制背景与线条,避免移动对象拖尾?
问题说明
我需要在draw_window函数里调用line1.draw_shape()、line2.draw_shape()等方法,让线条绘制在背景之上。目前在shape_generation函数内直接调用draw_shape时,无背景的情况下线条显示正常,但后续要添加可移动的玩家矩形,必须先绘制背景来更新屏幕所有像素,否则玩家移动时会留下拖尾。
之前尝试无背景绘制线条,不仅移动对象会留下颜色痕迹,重新生成线条位置时,旧线条也会因为像素没被背景色覆盖而残留。
原代码
import pygame import sys import random WIDTH, HEIGHT = 1050, 630 WIN = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("game") FPS = 30 GREY = (15, 15, 15) BLUE = (0, 0, 255) GREEN = (0, 255, 0) VEL = 5 class line: def __init__(self, lineX, lineY, dimensions): self.dimensions = dimensions if self.dimensions[2] == 1: self.lineY = lineY - HEIGHT//3 self.lineX = lineX elif self.dimensions[2] == 2: self.lineX = lineX - HEIGHT//3 self.lineY = lineY else: self.lineX = lineX self.lineY = lineY def draw_shape(self): pygame.draw.rect(WIN, BLUE, [self.lineX, self.lineY, self.dimensions[0], self.dimensions[1]] ) def shape_generation(): LINE_DIMENSIONS = ((10, HEIGHT // 3, 1 ), (HEIGHT // 3, 10, 0), (10, HEIGHT // 3, 0), (HEIGHT // 3, 10, 2)) #NORTH, EAST, SOUTH, WEST line0 = line(WIDTH // 5, HEIGHT // 3, random.choice(LINE_DIMENSIONS)) line1 = line((WIDTH // 5) * 2, HEIGHT // 3, random.choice(LINE_DIMENSIONS)) line2 = line((WIDTH // 5) * 3, HEIGHT // 3, random.choice(LINE_DIMENSIONS)) line3 = line((WIDTH // 5) * 4, HEIGHT // 3, random.choice(LINE_DIMENSIONS)) line4 = line(WIDTH // 5, (HEIGHT // 3) * 2, random.choice(LINE_DIMENSIONS)) line5 = line((WIDTH // 5) * 2, (HEIGHT // 3) * 2, random.choice(LINE_DIMENSIONS)) line0.draw_shape() line1.draw_shape() line2.draw_shape() line3.draw_shape() line4.draw_shape() line5.draw_shape() def draw_window(): WIN.fill(GREY) #This is where I would like the walls to be drawn. pygame.display.update() def main(): clock = pygame.time.Clock() shape_generation() run = True while run: clock.tick(FPS) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False pygame.quit() sys.exit() draw_window() pygame.display.update() if __name__ == "__main__": main()
解决方案
核心思路是:把线条对象保存下来,在每次绘制窗口时,先填充背景,再重新绘制所有线条,这样每次刷新都会用背景覆盖旧像素,避免残留。具体修改步骤:
- 修改
shape_generation函数,让它返回生成的所有线条对象列表,不再在函数内直接绘制 - 在
main函数中接收这个线条列表,保存为变量 - 在
draw_window函数中添加参数接收线条列表,遍历列表调用每个线条的draw_shape方法 - 移除原
shape_generation内的draw_shape调用
修改后的完整代码
import pygame import sys import random WIDTH, HEIGHT = 1050, 630 WIN = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("game") FPS = 30 GREY = (15, 15, 15) BLUE = (0, 0, 255) GREEN = (0, 255, 0) VEL = 5 class line: def __init__(self, lineX, lineY, dimensions): self.dimensions = dimensions if self.dimensions[2] == 1: self.lineY = lineY - HEIGHT//3 self.lineX = lineX elif self.dimensions[2] == 2: self.lineX = lineX - HEIGHT//3 self.lineY = lineY else: self.lineX = lineX self.lineY = lineY def draw_shape(self): pygame.draw.rect(WIN, BLUE, [self.lineX, self.lineY, self.dimensions[0], self.dimensions[1]] ) def shape_generation(): LINE_DIMENSIONS = ((10, HEIGHT // 3, 1 ), (HEIGHT // 3, 10, 0), (10, HEIGHT // 3, 0), (HEIGHT // 3, 10, 2)) #NORTH, EAST, SOUTH, WEST lines = [] lines.append(line(WIDTH // 5, HEIGHT // 3, random.choice(LINE_DIMENSIONS))) lines.append(line((WIDTH // 5) * 2, HEIGHT // 3, random.choice(LINE_DIMENSIONS))) lines.append(line((WIDTH // 5) * 3, HEIGHT // 3, random.choice(LINE_DIMENSIONS))) lines.append(line((WIDTH // 5) * 4, HEIGHT // 3, random.choice(LINE_DIMENSIONS))) lines.append(line(WIDTH // 5, (HEIGHT // 3) * 2, random.choice(LINE_DIMENSIONS))) lines.append(line((WIDTH // 5) * 2, (HEIGHT // 3) * 2, random.choice(LINE_DIMENSIONS))) # 移除原函数内的绘制调用,统一放到draw_window里处理 return lines def draw_window(lines): WIN.fill(GREY) # 遍历线条列表,绘制所有线条 for line_obj in lines: line_obj.draw_shape() pygame.display.update() def main(): clock = pygame.time.Clock() # 保存生成的线条列表 lines = shape_generation() run = True while run: clock.tick(FPS) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False pygame.quit() sys.exit() # 传入线条列表到draw_window draw_window(lines) if __name__ == "__main__": main()
关键改动说明
shape_generation现在返回线条对象列表,不再直接绘制,让绘制逻辑统一由draw_window管理draw_window先填充背景(WIN.fill(GREY)),再绘制所有线条,这样每次循环都会刷新整个屏幕,旧的线条和玩家拖尾都会被背景覆盖- 去掉了
main函数里重复的pygame.display.update(),避免重复刷新
内容的提问来源于stack exchange,提问作者Samuel Smith
相关产品推荐
相关产品推荐

