Pygame迷宫游戏关卡切换失效、重叠绘制问题求助
问题核心原因
你之前两个方案失效都是代码细节bug导致的,不是方案本身逻辑有问题,核心问题有3个:
- 你在
createMaze函数里修改的level是函数局部变量,修改后不会同步到全局的level变量,所以关卡根本不会切换 - 全局的
blocks列表每次调用createMaze都会追加当前关卡的碰撞块,从来没有清空过,旧关卡的块一直留在列表里,就会出现两个关卡同时生效、同时绘制的问题 - 碰撞终点触发关卡切换的逻辑写在
createMaze里,和绘制逻辑耦合在一起,容易出时序问题 - 额外小bug:玩家向右移动的边界判断写错了,
player.right < windowHeight应该改成player.right < windowWidth,不然右边界判定会异常
现有方案修复方法
你不需要换方案,把现有逻辑修正就能正常切换了,操作步骤如下:
- 每次生成新关卡前先清空
blocks列表,避免旧关卡的块残留 - 把
level变量的修改逻辑从createMaze里抽出来,或者声明global level让函数内可以修改全局变量 - 切换关卡后重置玩家位置到起点,避免玩家直接卡在新关卡的墙里
修改后的核心代码参考:
# 提前把所有关卡存成列表,后续加新关卡直接往列表里加即可 mazes = [maze1, maze2] def createMaze(map): pointX = 0 pointY = 0 end_rect = None # 用来返回终点块的碰撞盒 for i in map: for j in i: if j == "x": block = pygame.Rect(pointX, pointY, blockSize, blockSize) pygame.draw.rect(windowSurface, white, block) blocks.append(block) # 玩家和墙体的碰撞判断可以统一挪到玩家移动后执行,这里不用写 if j == "b": block = pygame.Rect(pointX, pointY, blockSize, blockSize) pygame.draw.rect(windowSurface, red, block) end_rect = block # 保存终点碰撞盒 pointX += 20 pointX = 0 pointY += 20 return end_rect # 主循环修改 while True: # 原有事件处理逻辑不变 for event in pygame.event.get(): if event.type == QUIT: close() # 按键判断逻辑保留 if event.type == KEYDOWN: if event.key == K_w: moveUp = True moveDown = False if event.key == K_s: moveUp = False moveDown = True if event.key == K_a: moveLeft = True moveRight = False if event.key == K_d: moveLeft = False moveRight = True if event.type == KEYUP: if event.key == K_w: moveUp = False if event.key == K_s: moveDown = False if event.key == K_a: moveLeft = False if event.key == K_d: moveRight = False # 玩家移动逻辑修正右边界判断 if moveLeft and player.left > 0: player.move_ip(-1 * speed, 0) if moveRight and player.right < windowWidth: player.move_ip(speed, 0) if moveUp and player.top > 0: player.move_ip(0, -1 * speed) if moveDown and player.bottom < windowHeight: player.move_ip(0, speed * 1) # 墙体碰撞判断统一放在移动后 for block in blocks: if block.colliderect(player): if player.bottom - block.top == 5: player.y = block.top - playerSize if block.bottom - player.top == 5: player.y = block.bottom if block.right - player.left == 5: player.x = block.right if player.right - block.left == 5: player.x = block.left - playerSize windowSurface.fill(black) # 生成当前关卡 blocks.clear() # 每次生成前清空旧关卡的块 current_end = createMaze(mazes[level-1]) # 检测是否碰到终点 if current_end and player.colliderect(current_end): level += 1 # 重置玩家到起点 player.x = 0 player.y = 0 # 超过总关卡数可以触发通关逻辑 if level > len(mazes): print("通关成功") close() pygame.draw.rect(windowSurface, blue, player) pygame.display.update() mainClock.tick(FPS)
其他可选的关卡切换方案
如果后续需要做更复杂的关卡逻辑(比如关卡存档、中间 checkpoint、特殊关卡事件)可以用下面两种方案:
- 关卡状态机:给每个关卡单独封装成类,包含该关卡的地图数据、玩家初始位置、通关条件、特殊事件等,切换关卡时直接实例化对应关卡类,替换当前运行的关卡实例即可
- 场景管理器:把主菜单、关卡1、关卡2、通关页都当成独立场景,每个场景有自己的
update、draw、event_handler方法,切换关卡时直接切换当前激活的场景,主循环只调用当前激活场景的对应方法,逻辑更清晰耦合度更低
内容的提问来源于stack exchange,提问作者Takayuki Senpai
相关产品推荐
相关产品推荐

