「Python」数字推盘游戏
推盘游戏代码见右边👉目录源代码处
要从0开始游戏设计,请往下看📢:
🎮数字推盘游戏
前面知识只是简单的对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.源代码
9.打包游戏
先安装工具pyinstaller
pip install pyinstaller
# 查看已安装工具
pip list
# 打包 game.py是主程序的名称
# 注意需要到游戏的主目录下执行以下命令
pyinstaller -F -w game.py
打包安装成功
执行完上述~~三个命令 ~~
(实际只需要两个)后,会新增build和dist文件夹
.exe可执行文件存放在dist文件夹中,需要将引用的背景'bg.png'和字体放在.exe目录之下
机智的我去玩了几局,最终终于赢了!!!
转载自:https://juejin.cn/post/7150463832639406111