pygame开发推箱子小游戏

项目运行基于python3.11pygame2.5.2的环境,同时,使用了pyinstaller进行文件的打包,如果你只是想体验推箱子的乐趣,clone仓库后使用仓库推箱子小游戏.exe即可

仓库地址:推箱子小游戏

1.地图说明

在文件夹map内,你可以向其中自行添加地图,
map

  • 0:代表外围绿色的背景
  • 1:wall
  • 2:代表蓝色的floor
  • 3:箱子
  • 4:目的地
  • 5:player

在添加完成后,可以在answer中添加对应的答案,1234分别代表上下左右,这样可以给出地图的参考答案。

2.基本代码思路

(1)关于sokoban的类:

我们新建了一个sokoban类,其中可以通过载入的map得到地图,其次,我们对玩家运行的动作进行了规约

def is_valid_move(self, dx, dy):
     new_x = self.playerX + dx
     new_y = self.playerY + dy
     if self.gameMap[new_y][new_x] == '1':   #wall
         return False
     if self.gameMap[new_y][new_x] == '3':   #box
         # 箱子更改
         box_new_x = new_x + dx
         box_new_y = new_y + dy
         # 判断:箱子的下一个位置是2还是4,4是destination
         if self.gameMap[box_new_y][box_new_x] in '24':
             self.gameMap[box_new_y][box_new_x] = '3'
             if self.gameMapInit[new_y][new_x] == '4':
                 self.gameMap[new_y][new_x] = '4'
             else:
                 self.gameMap[new_y][new_x] = '2'
             self.move.append([1,dx, dy]) #第二种情况是参与了箱子
             return True
         return False
     # 剩余2和5的情况为真,第一种情况是只有player参与了move
     self.move.append([0,dx,dy])
     return True

(2)关于其他功能(重置,回退,判断胜利)

  1. 重置
    其实就是把目前要的一些参数全置为初始的状态
 def reset_game(self):
       #回溯到游戏刚开始的状态
       self.gameMap = [list(row) for row in self.gameMapInit]
       self.playerX = self.playerXInit
       self.playerY = self.playerYInit
       self.step = 0
       self.move.clear()
  1. 回退
    这里做了一个异常处理,当回退列表为空时,他就不能在回退了
def game_back(self):
       try:
           listTem = self.move.pop()
           # 判断回溯的上一个
           if listTem[0] == 1:
               self.gameMap[self.playerY][self.playerX] = '3'
               temY = self.playerY + listTem[2]
               temX = self.playerX + listTem[1]
               self.gameMap[temY][temX] = self.gameMapInit[temY][temX] if self.gameMapInit[temY][temX] != '3'  else '2'
           self.playerX -= listTem[1]
           self.playerY -= listTem[2]
           self.step -= 1
       except:
           print("已是最新状态")
  1. 判断胜利
    用一个列表存储他的目的地的位置
    def win(self):
      for i in range(self.destNumber):
          if self.gameMap[int(self.destCoordinate[i][1])][int(self.destCoordinate[i][0])] != '3':
              return False
      return True

3.index主页构造

index

(1)读取外来的地图

我们用python中的os库,统计了map中有几个文件数目,就代表有几个地图

files = os.listdir("./map")
# 统计文件数量,其实就是有多少关
map_count = len(files)

(2)对于关卡的绘制

def draw_box(op,location):
    # 绘制关卡选择
    for i in range(map_count):
        if op and i == location:
            pygame.draw.ellipse(screen, black, input_box[i])  # 画关卡
            print_text(screen, font_theme, 57 + (i % 6) * 70, 235 + (i // 6) * 170, f'{i + 1}',white)
        else:
            pygame.draw.ellipse(screen, black, input_box[i], width=2)  #画关卡
            print_text(screen,font_theme,57+(i%6)*70, 235+(i//6)*170,f'{i+1}',black)

(3)在main.py新增了参考答案的功能

def get_reference_answer(sokoban):
    ans = ""
    with open(f'./answer/answer{goal}.txt','r') as f:
        ans += f.read()
        f.close()
    playerXTem = sokoban.playerX
    playerYTem = sokoban.playerY
    gameMapTem = tuple(tuple(row) for row in sokoban.gameMap)
    move = tuple(sokoban.move)
    stepTem = sokoban.step
    sokoban.reset_game()
    for i in range(len(ans)):
        for event in pygame.event.get():
            continue
        if ans[i]== '1':
            if sokoban.is_valid_move(0, -1):
                sokoban.playerY -= 1
                sokoban.step += 1
        elif ans[i]== '2':
            if sokoban.is_valid_move(0, 1):
                sokoban.playerY += 1
                sokoban.step += 1
        elif ans[i]== '3':
            if sokoban.is_valid_move(-1, 0):
                sokoban.playerX -= 1
                sokoban.step += 1
        elif ans[i]== '4':
            if sokoban.is_valid_move(1, 0):
                sokoban.playerX += 1
                sokoban.step += 1
        sokoban.draw_map(screen)
        print_text(screen, font_step, 380, 10, f"step:{str(sokoban.step)}", white)
        if sokoban.win():
            print_text(screen, font_theme, 200, 30, "挑战成功", white)
        # update the display
        pygame.display.update()
        pygame.time.delay(200)
    pygame.time.delay(1000)
    sokoban.playerX = playerXTem
    sokoban.playerY = playerYTem
    sokoban.gameMap = [list(row) for row in gameMapTem]
    sokoban.move = list(move)
    sokoban.step = stepTem

4.通过pyinstaller生成了exe文件

  1. pyinstaller --onefile --windowed main.py
  • –onefile 选项将所有内容打包到一个独立的 exe 文件中。
  • –windowed 选项用于创建没有控制台窗口的 GUI 应用程序。如果你希望保留控制台窗口,可以省略这个选项。
  1. 运行上述命令后,PyInstaller 会生成几个文件和文件夹:
    一个 build 文件夹,包含临时文件。
    一个 dist 文件夹,包含打包后的可执行文件。
    一个 game.spec 文件,包含打包的配置。
    你的可执行文件会在 dist 文件夹中,
  • 重命名参数-n old_name newname.py
  • 图标参数 -i fanvico.ico
  1. 进一步配置(可选)
    你可以通过修改 game.spec 文件来进行更多自定义配置。例如,添加数据文件,设置图标等。
    如果你需要将数据文件(如图像、声音等)一起打包,你可以修改 spec 文件中的 datas 参数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

且一笑作春温

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值