「Python」数字推盘游戏
🎮数字推盘游戏
前面知识只是简单的对pygame进行参数的介绍,后面还需要用到MVC设计模式,在这里不多做说明,建议直接观察源代码😅
前期知识储备pygame是为了开发2D游戏而设计的Python跨平台模块,使用前需要导入
pip install pygame
然后出现
Installing collected packages: pygame
Successfully installed pygame-2.0.1
即安装成功此游戏需要用到以下7个模块
pygame的初始化和退出 创建游戏窗口 游戏循环与游戏时钟 图形和文本绘制 元素位置控制 动态效果 时间与事件处理
1.pygame初始化
init()函数
init()函数可以一次性初始化pygame所有模块
quit()函数
quit()函数可以卸载所有之前被初始化的pygame模块。python在退出之前解释器会释放所有的模块,quit()函数并非必须调用。开发人员应当在需要时主动调用quit()函数卸载模块资源
"""数字推盘""" import pygame # 导入制作游戏的模块 def main(): pygame.init() # 初始化所有模块 pygame.quit() # 卸载所有模块 if __name__ == '__main__': main()
2.创建游戏窗口
pygame通过display子模块创建图形界面窗口 相关函数说明如下
set_mode() 初始化游戏窗口
set_caption() 设置窗口标题
update() 更新屏幕显示内容
set_mode()函数声明:set_mode(resolution=(0,0), flags=0, depth=0) -> Surface
①resolution 图形窗口分辨率。参数resolution本质上是一个元祖,该元祖的两个元素分别指定图形窗口的宽和高,单位为像素。默认情况下与屏幕大小一致。
②flags 标志位,用于设置窗口特性,默认0
③depth 色深,该参数只取整数,取值范围为【8,32】
set_mode()函数的额返回值为Surface对象,Surface可以被视为画布,图形在画布上才能展现。画布默认背景黑色,fill()方法可以填充画布
**set_caption() **用于设置窗口标题,函数声明如下:set_caption(title, icontitle=None) -> None
icontitle设置显示在任务栏上的程序标题,默认与title一致
窗口一闪而过:因为程序在设置完标题后就结束了
**update() ** 用于刷新窗口,在使用fill()方法填充后背景颜色却未变,是因为程序中未调用该函数对窗口进行刷新。在pygame.quit()之前调用update()函数
3.游戏循环与游戏时钟
要使得游戏保持运行需要在程序中天健一个无限循环,循环代码如下:
while True: pass
动态的效果实际上无数静态的组合起来快速播放形成的 在计算机上一秒绘制60(桢)Frame便可以达到连续、高品质的动画效果。换言之,窗口中刷新图像的频率只要不低于每秒60Frame,即可以达到动画的效果。 修改后的代码如下:
i = 0 while True: Print(i) i += 1
过高的帧率意味着超高的负荷,所以需要设置游戏时钟 可以调用pygame的time模块里面的clock类,通过该类的tick()方法就可设置游戏循环的执行频率
FPS = 60 # 预设频率 def main(): ... FPSCLOCK= pygame.time.Clock() # 创建clock模块 ... while True: print(i) i += 1 FPSCLOCK.tick(FPS) # 控制帧率
4.图形和文本绘制
pygame中的图形窗口是一个surface对象,在窗口上进行绘制实质上就是surface对象上进行绘制。
①图形绘制
加载图片load(filename) -> Surface
从当前路径加载图片imgSurf = pygame.image.load('bg.jpg')
绘制图片
绘制图像就是将surface对象叠加在另一个surface对象之上。通过blit()
方法可以实现图像绘制,具体语法如下:blit(source, dest, area=None, special_flags = 0) -> Rect
- source接收被绘制的surface对象
- dest接收一个表示位置的元组,该元祖指定left和top两个值,left和top分别表示图片距离窗口左边和顶部的距离。该参数也可接收一个表示矩形的元组(left,top,width,height)
- area可选参数,通过该参数可设置矩形区域。若设置的矩形区域小于source所设置的surface对象的区域,那么仅绘制surface对象的部分内容
- special_flags是标志位
WINSET.blit(imgSurf, (0, 0)) # 将imgSurf加载到窗口WINSET中
(0,0)代表的是位置
②文本绘制
使用font类
Font(filename,size) -> Font # 创建字体对象 """filename用于设置字体对象的字体,size用于设置字体大小 具体用法如下:""" BASICFONT = pygame.font.Font('STKAITI.TTF', 25) """ SysFont()函数常见一个系统字体对象。SysFont()函数的声明如下 SysFont(name, size, bold=False, italic=False) -> Font name 系统字体的名字,可以通过pygame.font.get_fonts()函数获得当前系统的所有可用字体列表 size 大小 bold 粗体,默认不加粗 italic 斜体 Font()1函数更加灵活 """ # 渲染文本内容 render() render(text, antialias, color, background=None) -> Surface """ text:文字内容 antialias:是否抗锯齿(抗锯齿让绘制的文字更平滑) render方法返回surface对象---即一张内容为文字的图片 """ msgSurf = BASICFONT.render('初始化...', True, MSGCOLOR, MSGBGCOLOR) # 渲染 """" 使用save方法将图片保存到本地 """ pygame.image.save(msgSurf,'msg.png') """ 渲染之后仍然需要绘制渲染结果,用blit """
到此,所有的代码如下:
把while循环删了,电脑可以的话你可以不删~hahahah
"""set_mode模块""" import pygame WINWIDTH = 640 # 窗口宽度 WINHEIGHT = 480 # 窗口高度 # -----颜色预设----- DARKTURQUOISE = (3, 54, 73) YELLOW = (255, 255, 193) # -----颜色变量----- BGCOLOR = DARKTURQUOISE # 预设背景颜色 MSGCOLOR = DARKTURQUOISE # 设置字体颜色 MSGBGCOLOR = YELLOW # 按钮背景颜色 FPS = 60 # 预设频率 def main(): pygame.init() # 初始化所有模块 FPSCLOCK = pygame.time.Clock() # 创建clock模块 # 创建窗体,即创建爱你surface对象 WINSET = pygame.display.set_mode((WINWIDTH, WINHEIGHT)) WINSET.fill(BGCOLOR) # 填充背景颜色 pygame.display.set_caption('数字推盘') # 设置窗口标题 image = pygame.image.load('bg.jpg') # 加载背景图片 WINSET.blit(image, (0, 0)) # 绘制背景图片 BASICFONT = pygame.font.Font('hua_wen_xing_kai.ttf', 25) # 创建字体对象 msgSurf = BASICFONT.render('初始化...', True, MSGCOLOR, MSGBGCOLOR) # 渲染 WINSET.blit(msgSurf, (0, 0)) WINSET.blit(image, (0, 0)) # 绘制图片 pygame.display.update() # 刷新窗口 pygame.quit() # 卸载所有模块 if __name__ == '__main__': main()
5.元素位置控制
Rect()类,放置图片and文本
x轴水平向右为正
y轴水平向下为正
""" Rect(x, y, width, height) -> Rect 创建矩形对象 rect = pygame.Rect(80, 160, 160, 120) # 坐标为(80,160) 160 × 120 像素 可以通过rect.() 来查看它的方法 """ """ surface对象在窗口的位置通过blit()方法的参数dest确定 """ # 渲染字体 autoSurf = BASICFONT.render('自 动', True, BTTEXTCOLOR, BTCOLOR) autoRect = autoSurf.get_rect() # 获取矩阵属性 autoRect.x = WINWIDTH - autoRect.width - 10 # 重设横坐标 autoRect.y = WINHEIGHT - autoRect.height - 10 # 重设纵坐标 WINSET.blit(autoSurf, autoRect) # 绘制字体
6.动态效果
本游戏的方块由矩形和文本组成,其中文本用的是font模块的Font()函数、render()方法以及Surface类的blit()方法绘制,矩形使用pygame中draw模块的rect()函数绘制。 So,实现方块的移动需要实现:
①绘制矩形方块
rect(Surface,color,Rect,width=0) -> Rect
Rect接收一个矩形对象
# 创建矩形 blockRect = pygame.Rect(0.5 * (WINWIDTH - BLOCKSIZE), 0.5 * (WINHEIGHT - BLOCKSIZE), BLOCKSIZE, BLOCKSIZE) pygame.draw.rect(WINSET, BTCOLOR, blockRect) # 绘制矩形
②绘制数字
数字应该位于矩形中心,矩形对象的左上角坐标代表矩形的位置,目前上面绘制的矩形在屏幕的中心,假设数字的矩形对象为numRect,则其在屏幕中的x,y坐标分别如下:
numRect.x = blockRect.x + 0.5 * (BLOCKSIZE-numRect.width)
numRect.y = blockRect.y + 0.5 * (BLOCKSIZE-numRect.height)
③移动方块
移动通过在不同但连续的位置绘制同一个surface对象。 推盘中的方块由方块图像blockSurf和numSurf组成。移动过程在for循环中实现
# 在背景的不同位置绘制方块,制造移动效果。方块向右移动 BLOCKSIZE+2 for i in range(0, BLOCKSIZE, 2): FPSCLOCK.tick(FPS) # 循环帧率控制 # ----绘制---- pygame.draw.rect(WINSET, BTCOLOR, blockRect) WINSET.blit(numSurf, numRect) pygame.display.update() # ----位置更改,实现向右移动---- blockRect.x += 10 # 修改方块横坐标 numRect.x += 10 # 修改数字横坐标
以上方块只是简单的做了一个平移的操作,很显然不符合游戏的设定。于是改用surface类中的copy方法
# 准备背景 baseSurf = WINSET.copy() # 创建矩形 ... # ----位置更改,实现向右移动---- blockRect.x += 10 # 修改方块横坐标 numRect.x += 10 # 修改数字横坐标 WINSET.blit(baseSurf, (0, 0)) # 使用备份baseSurf覆盖WINSET
7.时间与事件处理
pygame常见事件列表:
""" KEYDOWN 键盘被按下 unicode,key,mod KEYUP 键盘被放开 key,mod 参数 unicode:记录按键的unicode值 key:按下或放开的键的键值 mod:包含组合键信息 """ """ MOUSEMOTION 鼠标移动 pos,rel,button MOUSEBUTTONDOWN 鼠标按下 pos,button MOUSEBUTTONUP 鼠标松开 pos,button pos:鼠标操作的位置,包含x和y是一个元祖 rel:当前位置与上次产生鼠标事件时鼠标指针位置间的距离 buttons:一个含有3个数字的元祖,(1,0,0)--三个数字分别对应左键、滚轮、右键 button: 整形数值, 1-->单击鼠标左键 2-->单击滚轮 3-->单击右键 4-->向上滑动滚轮 5-->向下滑动滚轮 """
# 创建窗体,即创建爱你surface对象 WINSET = pygame.display.set_mode((WINWIDTH, WINHEIGHT)) WINSET.fill() # 填充背景颜色 pygame.display.set_caption('数字推盘') # 设置窗口标题 image = pygame.image.load('bg.jpg') # 加载背景图片 WINSET.blit(image, (0, 0)) # 绘制背景图片 msgSurf = BASICFONT.render('初始化...', True, MSGCOLOR, MSGBGCOLOR) # 渲染 # 渲染字体 autoSurf = BASICFONT.render('自 动', True, BTTEXTCOLOR, BTCOLOR) autoRect = autoSurf.get_rect() # 获取矩阵属性 autoRect.x = WINWIDTH - autoRect.width - 10 # 重设横坐标 autoRect.y = WINHEIGHT - autoRect.height - 10 # 重设纵坐标 WINSET.blit(autoSurf, autoRect) # 绘制字体 WINSET.blit(msgSurf, (0, 0)) WINSET.blit(image, (0, 0)) # 绘制图片 # 准备背景 baseSurf = WINSET.copy() # 创建矩形 blockRect = pygame.Rect(0.5 * (WINWIDTH - BLOCKSIZE), 0.5 * (WINHEIGHT - BLOCKSIZE), BLOCKSIZE, BLOCKSIZE) pygame.draw.rect(WINSET, BTCOLOR, blockRect) # 绘制矩形 # 绘制数字 numSurf = BASICFONT.render('5', True, BTTEXTCOLOR, BTCOLOR) numRect = numSurf.get_rect() numRect.x = blockRect.x + 0.5 * (BLOCKSIZE - numRect.width) numRect.y = blockRect.y + 0.5 * (BLOCKSIZE - numRect.height) # 获取点击事件,rect.collodepoint(),判断点击位置 while True: FPSCLOCK.tick(FPS) # 循环帧率控制 for event in pygame.event.get(): if event.type == MOUSEBUTTONUP: # 鼠标放开事件 if blockRect.collidepoint(event.pos): # 点击的是方块 print('点击方块') # 在背景的不同位置绘制方块,制造移动效果。方块向右移动 BLOCKSIZE+2 for i in range(0, BLOCKSIZE, 2): FPSCLOCK.tick(FPS) # 循环帧率控制 # ----绘制---- pygame.draw.rect(WINSET, BTCOLOR, blockRect) WINSET.blit(numSurf, numRect) pygame.display.update() # ----位置更改,实现向右移动---- blockRect.x += 10 # 修改方块横坐标 numRect.x += 10 # 修改数字横坐标 WINSET.blit(baseSurf, (0, 0)) # 使用备份baseSurf覆盖WINSET # pygame.display.update() # 刷新窗口 pygame.quit() # 卸载所有模块
上面只是简单的介绍了一下pygame的一些简单的使用,后面具体的设计需要用到MVC设计模式(即模型-视图-控制器)
大致流程为:
绘制静态页面->生成推盘序列->打乱推盘->在循环中绘制动态页面并更新,判断程序是否退出,最后接收用户输入并进行处理
主程序如下:
def main(): global FPSCLOCK, WINSET, STATICSURF, BASICFONT global NEW_SURF, NEW_RECT global SOLVEDBOARD '''游戏流程,游戏的框架先放进去,然后填充''' pygame.init() # 初始化所有模块 FPSCLOCK = pygame.time.Clock() # 创建clock模块 BASICFONT = pygame.font.Font('hua_wen_xing_kai.ttf', 25) # 创建字体对象 # 初始化 initBorad = getStartingBoard() print(initBorad) WINSET, NEW_SURF, NEW_RECT = drawStaticWin() STATICSURF = WINSET.copy() mainBoard = generateNewPuzzle(AUTOMOVE) msg = None while True: FPSCLOCK.tick(FPS) drawBoard(mainBoard, msg) # 根据初始拼图信息与提示信息,绘制游戏界面 pygame.display.update() # 判断是否结束游戏 checkForQuit() # 判断是否接收到终止信息 userInput = getInput(mainBoard) # 获取用户输入 mainBoard, msg = processing(userInput, mainBoard, msg)
具体模块见源代码
需要准备的就是背景图片以及字体 游戏界面如下:
8.源代码
推盘.py
9.打包游戏
先安装工具pyinstaller
pip install pyinstaller # 查看已安装工具 pip list # 打包 game.py是主程序的名称 # 注意需要到游戏的主目录下执行以下命令 pyinstaller -F -w game.py
打包安装成功
执行完上述~~三个命令 ~~ (实际只需要两个)后,会新增build和dist文件夹
.exe可执行文件存放在dist文件夹中,需要将引用的背景'bg.png'和字体放在.exe目录之下