You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pygame迷宫游戏关卡切换失效、重叠绘制问题求助

问题核心原因

你之前两个方案失效都是代码细节bug导致的,不是方案本身逻辑有问题,核心问题有3个:

  • 你在createMaze函数里修改的level是函数局部变量,修改后不会同步到全局的level变量,所以关卡根本不会切换
  • 全局的blocks列表每次调用createMaze都会追加当前关卡的碰撞块,从来没有清空过,旧关卡的块一直留在列表里,就会出现两个关卡同时生效、同时绘制的问题
  • 碰撞终点触发关卡切换的逻辑写在createMaze里,和绘制逻辑耦合在一起,容易出时序问题
  • 额外小bug:玩家向右移动的边界判断写错了,player.right < windowHeight应该改成player.right < windowWidth,不然右边界判定会异常
现有方案修复方法

你不需要换方案,把现有逻辑修正就能正常切换了,操作步骤如下:

  1. 每次生成新关卡前先清空blocks列表,避免旧关卡的块残留
  2. 把level变量的修改逻辑从createMaze里抽出来,或者声明global level让函数内可以修改全局变量
  3. 切换关卡后重置玩家位置到起点,避免玩家直接卡在新关卡的墙里

修改后的核心代码参考:

# 提前把所有关卡存成列表,后续加新关卡直接往列表里加即可
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 23:39:02