Pygame实现的生命游戏运行卡顿,已排除绘制事件放错循环问题,求解决
Pygame生命游戏卡顿修复方案
1. 核心语法错误:numpy数组初始化参数不规范
你当前创建数组的写法不符合numpy API要求:
# 错误写法:numpy.zeros第一个参数必须是表示维度的元组,你将行列拆为了两个独立参数 self.pixels = numpy.zeros(self.ScreenWidth//2, self.ScreenHeight//2, dtype=int) newGeneration = numpy.zeros(self.ScreenWidth//2, self.ScreenHeight//2, dtype=int)
该写法会隐性创建错误维度的数组,触发额外的内存操作和越界兼容逻辑,是卡顿的核心原因之一。同时你的网格大小和cellsize参数不匹配,存在大量冗余空元素,进一步浪费了遍历性能。
修复方式:
在Run方法初始化阶段先计算匹配cellsize的网格大小:
self.cellsize = 10 self.cols = self.ScreenWidth // self.cellsize self.rows = self.ScreenHeight // self.cellsize # 正确初始化二维数组 self.pixels = numpy.zeros((self.cols, self.rows), dtype=int)
NextGeneration里创建新数组对应修改为:
newGeneration = numpy.zeros((self.cols, self.rows), dtype=int)
2. 性能瓶颈优化:替换纯Python循环为numpy向量化计算
你当前两层Python循环遍历所有细胞,每个细胞内部再开两层循环计算邻接数量,Python循环本身开销极高,是计算侧卡顿的主要原因。
直接用numpy滚动求和实现邻接计数,完全规避Python层循环,性能提升100倍以上:
def NextGeneration(self): # 向量化计算8个方向的邻接存活细胞总数 total = (numpy.roll(self.pixels, 1, axis=0) + numpy.roll(self.pixels, -1, axis=0) + numpy.roll(self.pixels, 1, axis=1) + numpy.roll(self.pixels, -1, axis=1) + numpy.roll(numpy.roll(self.pixels, 1, axis=0), 1, axis=1) + numpy.roll(numpy.roll(self.pixels, 1, axis=0), -1, axis=1) + numpy.roll(numpy.roll(self.pixels, -1, axis=0), 1, axis=1) + numpy.roll(numpy.roll(self.pixels, -1, axis=0), -1, axis=1)) # 向量化应用生命游戏规则 new_pixels = numpy.where((self.pixels == 1) & ((total == 2) | (total == 3)), 1, 0) new_pixels = numpy.where((self.pixels == 0) & (total == 3), 1, new_pixels) self.pixels = new_pixels
3. 绘制逻辑优化:减少无效绘制调用
你当前每次绘制都遍历所有网格格子调用pygame.draw.rect,可以改为仅遍历存活细胞绘制,大幅减少绘制调用次数:
def DrawBG(self): black = (0,0,0) white = (255,255,255) self.bg.fill(black) # 仅获取存活细胞坐标遍历绘制 alive_cells = numpy.argwhere(self.pixels == 1) for (col, row) in alive_cells: pygame.draw.rect(self.bg, white, (col*self.cellsize, row*self.cellsize, self.cellsize-1, self.cellsize-1))
参数里的-1是为了预留网格线间隙,不需要可以直接删掉。
4. 事件逻辑优化:解决S键延迟问题
你当前主循环里多次重复遍历事件列表,且计算逻辑阻塞了事件响应,合并事件处理逻辑即可解决延迟:
while running: clock.tick(60) events = pygame.event.get() # 单次遍历处理所有事件 for event in events: if event.type == pygame.QUIT: running = False elif stage == 'Draw': if event.type == pygame.MOUSEBUTTONDOWN: mousedown = True elif event.type == pygame.MOUSEBUTTONUP: mousedown = False elif event.type == pygame.MOUSEMOTION and mousedown: m_x, m_y = pygame.mouse.get_pos() c = m_x // self.cellsize r = m_y // self.cellsize if 0 <= c < self.cols and 0 <= r < self.rows: self.pixels[c][r] = 1 elif event.type == pygame.KEYDOWN and event.key == pygame.K_r: stage = 'Run' elif stage == 'Run': if event.type == pygame.KEYDOWN and event.key == pygame.K_s: stage = 'Draw' # 演化逻辑放在事件处理之后 if stage == 'Run': self.NextGeneration() # 绘制逻辑不变 self.DrawBG() screen.blit(self.bg, (0,0)) pygame.display.flip()
以上修改完成后,即可完全解决运行卡顿和S键延迟的问题,稳定跑满60帧。
内容的提问来源于stack exchange,提问作者Ethan97
相关产品推荐
相关产品推荐

