python+pygame实现推箱子小游戏之一

经典的推箱子Sokoban是一个来自日本的古老游戏,目的是在训练你的逻辑思考能力。在一个狭小的仓库中,要求把木箱放到指定的位置,稍不小心就会出现箱子无法移动或者通道被堵住的情况,所以需要巧妙的利用有限的空间和通道,合理安排移动的次序和位置,才能顺利的完成任务。

下面将python+pygame实现推箱子小游戏的过程记录下来,以便学习。

基本逻辑是将箱子推到指定位置,虽然简单,但这个游戏其实很烧脑。开发实现时,计划为:

页面元素共有:推箱子的工人,箱子,外墙,终点

1、推箱子的工人class workerSprite,继承自pygame.sprite.Sprite,由于它和其他的页面元素有点不一样,它可以前后左右动,所以显示的图像不一样。它可以移动,还有就是要计算它在当前的位置和方向上的下一个位置能不能到达(这个要先判断),因此要返回下一个位置。

2、其他的页面元素(箱子box,外墙wall,终点target)class  gameElementSprite,同样继承自pygame.sprite.Sprite,用elementtype来区别,只有box可以被移动,同时在移动之前,要判断在当前的位置和方向上的下一个位置能不能到达,因此要返回下一个位置。

3、游戏地图的构造及相关判断动作class gameMap,主要是加载地图上对应的元素,判断是否通关,判断1和2中计算出的位置是否可以到达。这里不涉及到pygame的应用,可以理解为就是个后端的服务。

4、游戏的界面展示class gameDisplay,主要完成关卡地图的读取,借助 3 来完成构造,同时draw到屏幕上。另外,有些地图较大,所以这里还会涉及到随着人物走动时的屏幕滚动的操作控制。

5、套娃结束,写主函数了。包含某一关的主循环(主要是键盘的控制),退出游戏及过渡附属页面。

注意:为方便起见,将程序用到的公共参数放在params.py文件中,这样:

'''
	参数配置文件
'''
Params = {
			'WIDTH': 650,    #游戏界面宽度
			'HEIGHT': 520,   #游戏界面高度
			'blockSize': 50,    #每块大小
			'levelsPath': './levels',  #关卡文件夹
			'resourcePath': './resource', #资源文件夹
			'imgFolder': 'imgs',   #图片文件夹
			'fontFolder': 'font',  #字体文件夹
			'audioFolder': 'audios',  #音乐文件夹
			'bgColor': (38, 38, 38)  #背景色
		}

为方便查看,给出目录结构:

先从基本的class workerSprite写起,继承自pygame.sprite.Sprite,

import os
import pygame
from params import Params

'''
	推箱子的工人
'''
class workerSprite(pygame.sprite.Sprite):
    def __init__(self,col,row):
        pygame.sprite.Sprite.__init__(self)
        self.imagepath = os.path.join(Params.get('resourcePath'), Params.get('imgFolder'), 'right.png')
        self.image = pygame.image.load(self.imagepath).convert_alpha()
        self.rect = self.image.get_rect()
        self.col = col
        self.row = row
        
    '''
    移动工人
    '''
    def move(self,direction):
        if direction == 'up':
            self.row -= 1
        elif direction == 'down':
            self.row += 1
        elif direction == 'left':
            self.col -= 1
        elif direction == 'right':
            self.col += 1
    
        self.imagepath = os.path.join(Params.get('resourcePath'), Params.get('imgFolder')) + '\\' + direction + '.png'
        self.image = pygame.image.load(self.imagepath).convert_alpha()
    
    '''
    获取下一个点的位置
    '''
    def getNextPos(self,direction): 
        if direction == 'up':
            return self.col, self.row - 1
        elif direction == 'down':
            return self.col, self.row + 1
        elif direction == 'left':
            return self.col - 1, self.row
        elif direction == 'right':
            return self.col + 1, self.row


    '''
    画到屏幕上
    '''
    def draw(self,gamescreen):
        self.rect.x = self.rect.width * self.col
        self.rect.y = self.rect.height * self.row
        gamescreen.blit(self.image, self.rect)

注解:

1、__init__中本质是在位置col,row上画图片,默认方向是right.png,convert_alpha()包含了透明度,用convert()也可以

2、move函数中,会根据其方向使用不同的图片,分别对应使用up.png,down.png,right.png,left.png

3、draw函数注意有个转换,人物占一格,所以要转换为像素,用Params中的blockSize也可以。

待续...

python+pygame实现推箱子小游戏之二

  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个用Python实现推箱子小游戏的示例代码(仅供参考): ``` # 导入必要的模块 import tkinter as tk # 定义游戏界面的类 class Game(tk.Frame): # 初始化游戏界面 def __init__(self, master): super().__init__(master) self.master = master self.pack() # 定义游戏地图和游戏元素 self.map = [ "#### ", "#@### ", "# $ ", "# $ ", "# . ", "######" ] self.player_x, self.player_y = 1, 1 self.box_x, self.box_y = 2, 2 self.target_x, self.target_y = 4, 5 # 创建游戏界面的组件 self.create_widgets() # 创建游戏界面的组件 def create_widgets(self): # 创建游戏地图的画布 self.canvas = tk.Canvas(self, width=300, height=300) self.canvas.pack() # 加载游戏元素的图片 self.wall_img = tk.PhotoImage(file="wall.gif") self.box_img = tk.PhotoImage(file="box.gif") self.target_img = tk.PhotoImage(file="target.gif") self.player_img = tk.PhotoImage(file="player.gif") # 在画布上绘制游戏地图和游戏元素 for y in range(len(self.map)): for x in range(len(self.map[y])): if self.map[y][x] == "#": self.canvas.create_image(x*50+25, y*50+25, image=self.wall_img) elif self.map[y][x] == "$": self.canvas.create_image(x*50+25, y*50+25, image=self.box_img) elif self.map[y][x] == ".": self.canvas.create_image(x*50+25, y*50+25, image=self.target_img) elif self.map[y][x] == "@": self.canvas.create_image(x*50+25, y*50+25, image=self.player_img) # 绑定键盘事件 self.master.bind("<Up>", self.move_up) self.master.bind("<Down>", self.move_down) self.master.bind("<Left>", self.move_left) self.master.bind("<Right>", self.move_right) # 判断游戏是否胜利 def check_win(self): return self.box_x == self.target_x and self.box_y == self.target_y # 移动玩家和箱子 def move(self, dx, dy): new_player_x, new_player_y = self.player_x + dx, self.player_y + dy new_box_x, new_box_y = self.box_x, self.box_y if new_player_x == self.box_x and new_player_y == self.box_y: new_box_x, new_box_y = self.box_x + dx, self.box_y + dy if self.map[new_player_y][new_player_x] != "#": self.player_x, self.player_y = new_player_x, new_player_y self.box_x, self.box_y = new_box_x, new_box_y self.update_game() # 上移 def move_up(self, event): self.move(0, -1) # 下移 def move_down(self, event): self.move(0, 1) # 左移 def move_left(self, event): self.move(-1, 0) # 右移 def move_right(self, event): self.move(1, 0) # 更新游戏界面 def update_game(self): self.canvas.delete("all") for y in range(len(self.map)): for x in range(len(self.map[y])): if self.map[y][x] == "#": self.canvas.create_image(x*50+25, y*50+25, image=self.wall_img) elif self.map[y][x] == "$": self.canvas.create_image(x*50+25, y*50+25, image=self.box_img) elif self.map[y][x] == ".": self.canvas.create_image(x*50+25, y*50+25, image=self.target_img) elif self.map[y][x] == "@": self.canvas.create_image(x*50+25, y*50+25, image=self.player_img) if self.check_win(): self.canvas.create_text(150, 150, text="You Win!", font=("Arial", 20)) # 创建主窗口并运行游戏 if __name__ == "__main__": root = tk.Tk() root.title("Push Box Game") game = Game(root) game.mainloop() ``` 需要注意的是,由于没有使用pygame库,所以在实现游戏界面和游戏元素时,使用了Tkinter库的Canvas组件来绘制游戏界面。同时,由于没有使用外部资源加载函数,所以在代码中需要手动加载游戏元素的图片,并使用Canvas组件的create_image方法来绘制游戏元素。另外,由于没有使用pygame库的事件循环机制,所以在实现玩家移动和箱子移动时,使用了Tkinter库的键盘事件绑定功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值