3 安装pygame模块
在VisualStudioCode的顶部菜单【Terminal-New Teminal】打开命令行终端,然后输入命令python -m pip install --upgrade pip,回车,等待完成。然后同样输入命令pip install pygame,等待完成安装,可能须要几分钟 二、创建项目
<meta charset="utf-8">
- 将下面的代码粘贴到右侧`main.py`文件中。
import pygameimport syspygame.display.set_mode([600,400])while 1: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit()
运行代码。
仍旧【Terminal-New terminal】终端中输入命令`python main.py`,这将运行我们上面的代码,看到弹出一个玄色窗口。

image
image
pip install ...安装命令太慢。Windows用户,可以从上面的网盘中下载pip.ini文件,然后在【C盘-用户-用户名】文件夹下面创建pip文件夹,再把下载的pip.ini文件拷贝进去,此后再运行pip install ...安装速率就会快很多。对付苹果用户就麻烦很多。先在终端实行cd ~切换到用户文件夹,然后实行mkdir .pip创建.pip文件夹,它是隐身的,我们打开访达,从菜单实行【前往-前往文件夹...】,前往~/.test目录,把下载的pip.conf文件粘贴进去,搞定。pip.ini或者pip.conf文件是把原来pip默认从国外下载安装改成了从海内下载,以是速率会变快很多。
个中import是导入我们要利用的外部代码模块,pygame当然是必须的,sys是system系统的简写,由于我们的游戏要运行在系统(windows或者苹果macOS)上面,以是我们会用到系统的一些命令,比如下面的sys.exit()这个命令。pyagme.display.set_mode([600,400]),这里的[600,400]是一对数字组合在一起的,叫二元数组,这里它表示宽600,高400的一个矩形。整句话便是设置要弹出的窗口的大小,display显示,set设置,mode模式。while 1:...当是1的时候,就...,1在代码里面表示精确的、真的、存在的,相反,0表示缺点、假的、不存在的。while 1:do something那么something就会做,如果while 0: do something那么就不会做了。for ... sys.exit()这一段暂时可以不穷究,只是固定格式。只要知道它表示游戏程序运行结束的时候系统把窗口也关掉,清理好打算机不要留痕迹,exit退出。游戏开拓的思路游戏开拓都有固定的套路,无论是打地鼠、愤怒的小鸟,还是西瓜忍者,乃至是王者光彩这样的大型游戏,他们大致都遵照下面几个思路:
创建一个舆图场景,上面可能有些道具。 比如几个地鼠洞,一些可以放小猪的木盒子,乃至非常繁芜的山谷地形,上面还有很多野怪。这些舆图上的元素一样平常都是被动的,便是你不去靠近或招惹野怪的话,它们不会相互打起来自相残杀,同样,小鸟还没发射的时候,木盒子也不会自己倒塌。创建至少一个玩家可以掌握的元素,它可以和舆图场景发生交互。 这个可以被掌握的元素我们称为玩家角色。在打地鼠游戏中这个角色便是一个锤子,愤怒的小鸟中这个角色实在是弹弓,弹出的小鸟实在是个道具,在王者光彩游戏中玩家的角色便是自己的英雄。必须要有评判标准,用来衡量输赢胜败。 玩家掌握的角色和舆图场景进行交互,发生反应,对应的也必须要有一个评判标准,比如打算3分钟内击中地鼠的次数,或者打算砸去世的绿猪的数量,或者是打野怪得到的履历,这些规则一定要清晰而且不能相互抵牾。大多数游戏都有输赢胜败,而胜败每每实质上只是谁的积分首先达到某个临界点。可以是某个关键道具的变革,比如对战游戏中塔被摧毁,也可以是玩家角色的属性变革,比如格斗游戏中被击杀;也可以只是纯粹的某项积分评比,用排行榜代替输赢。游戏开拓的技能点要能够在窗口内绘制图形。 可以是直接用代码绘制几何图形,也可以是载入图片显示内容。要能用代码掌握每个元素(道具和角色)的动画。 动画便是一组图片一直地轮番变革。要能用代码掌握播放和停滞每个元素的动画,还能在不同动画之间快速切换。能够吸收用户的掌握,并借此影响游戏中的元素。 知道用户什么时候按了键盘,什么时候点了鼠标,按了哪个按键,鼠标左键还是右键?我们常常把这些操作称之为交互事宜。能够对游戏中各种元素产生的有效数据进行打算和管理。 玩家角色一刀砍下去,怪物的血量减少了100点,这个便是数据,而且是很有用的数据,没有这个数据的话怪物可能永久砍不去世了。有时候这些数据要保存好,让用户下一次打开游戏的时候仍旧看到自己的等级和装备都还存在。有些时候这些数据要及时清理,比如新的一局又开始了,舆图上的道具和角色都要恢复原样。打地鼠游戏我们可以把经典的打地鼠游戏简化概括为:
舆图和道具:随机位置涌现地鼠图形交互角色:掌握锤子图形,点击地鼠图形使其消逝积分输赢:限定韶光内击中地鼠图形的次数核心玩法简化成一句话便是:点击随机涌现图形。
绘制地鼠我们用一个蓝色的圆形代表地鼠。那怎么在窗口中绘制一个圆形呢?
可以百度【pygame 画圆圈】类似的关键字,可以查到要利用pygame.draw.circle语句,它的详细语法可以从官方解释文档中找到,英文版详细解释点这里。
我们查到它的语法是:
pygame.draw.circle()circle(surface, color, center, radius) -> Rect
这表示draw.circle()须要四个参数,分别是surface表面,color颜色,center中央点,radius半径。
我们连续看surface参数的解释:
surface (Surface) -- surface to draw on
听上去像是画布,——先要有个画布才能在上面画圆。点击Surface链接,找到更进一步解释:
Surface((width, height), flags=0, depth=0, masks=None) -> Surface
结尾的->Surface表示Surface((width....)这句话可以天生一个Surface表面,我们可以用下面的语句捕捉到这个天生的表面:
sur=pygame.Surface((600, 400)
这样,sur便是我们天生的表面了。
颜色和位置再返回来看color参数:
color (Color or int or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a tuple (RGB[A])
很明显它是表示画什么颜色的圆。tuple(int, int, int, [int])表示这里须要三个整数int一起表示颜色,RGB是指red红,green绿,blue蓝,alpha透明度:
clr=(0,0,255) #蓝色
对付center中央位置我们也可以用同样的方法得到,这里的Vector2表示二元向量,及横向x和竖向y的位置:
pos=pygame.vector2(300,200) #窗口中心
绘制圆形
参数都具备了,那么就可以开始画圆了。运行下面的代码:
import pygameimport syspygame.init() # 初始化window = pygame.display.set_mode([600, 400]) # 设定窗口sur = pygame.Surface([600, 400]) # 绘制背景容器clr = (0, 0, 255)pos = (300,200)rad = 100while 1: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() # 每帧循环实行的代码 pygame.draw.circle(sur, clr, pos, 100# 绘制圆 # 刷新画面 window.blit(sur, (0, 0)) pygame.display.flip()
把稳这里最底部刷新画面的两行,个中window.blit(sur, (0, 0))表示把我们绘制好的表面sur刷新到window窗口中;pygame.display.flip()表示进行窗口刷新。
随机涌现随机涌现便是随机位置,我们必须确保每一次花圆的pos位置都不同,而且该当是固定的几个地鼠洞位置。——别忘了我们要做打地鼠游戏。
假设有6个地鼠位置pos分别是[200,200],[300,200],[400,200],[200,300],[300,300],[400,300],那么如何随机取到6个中一个呢?也便是如何随机取到1~6个中的一个数字即可。
我们可以百度【python 随机数】查到须要利用random模块,这是python自带的模块,不须要再重新pip install。如果搜索【python random document】可以查找到官方的语法解释,如下:
random.randint(a, b)Return a random integer N such that a <= N <= b. Alias for randrange(a, b+1).
这是说可以随机天生a和b之间的一个数字。也可以从中文的菜鸟教程网学习到这个知识。
新建一个test.py文件,我们进行测试:
import randoma = random.randint(0, 5)print(a)
每次运行都能天生不同的数字。
连续测试:
import randoma = random.randint(0, 6)pos6=[[200,200],[300,200],[400,200],[200,300],[300,300],[400,300]]print(pos6[a])
这里的pos6[a]表示pos6的六个位置中的第a个。运行这个代码就会每次天生不同的位置。
测试成功之后我们把它拷贝到刚才的画圆代码中,得到:
import pygameimport sysimport randompygame.init() # 初始化window = pygame.display.set_mode([600, 400]) # 设定窗口sur = pygame.Surface([600, 400]) # 绘制背景容器clr = (0, 0, 255)pos6 = [[200, 200], [300, 200], [400, 200], [ 200, 300], [300, 300], [400, 300]] # !!六个位置rad = 100while 1: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() # 每帧循环实行的代码 sur.fill((0, 0, 0)) # !!用玄色覆盖前一帧的画面,实现刷新 a = random.randint(0, 5) # !!随机0到5 pygame.draw.circle(sur, clr, pos6[a], 100) # !!利用随机位置 # 刷新画面 window.blit(sur, (0, 0)) pygame.display.flip()
把稳新增了sur.fill...一行,这是用玄色(0,0,0)来清理掉上一帧的内容,避免涌现多个圆。
隔n帧刷新上面的代码运行之后会看到蓝色的圆四处乱跳,太快了,我们希望改变位置之后能停一下,等我们锤它。
我们须要画面的圆每隔n帧再随机变换一次,而不是现在的每帧都随机变。思路是这样的:我们设定一个计数器,开始是0,每帧都给它增加1,便是0,1,2,3,4...直到它增到到超过50,这时候我们就改变圆的位置并同时把计数看重置为0。
代码如下:
import pygameimport sysimport randompygame.init() # 初始化window = pygame.display.set_mode([600, 400]) # 设定窗口sur = pygame.Surface([600, 400]) # 绘制背景容器clr = (0, 0, 255)pos6 = [[200, 200], [300, 200], [400, 200], [ 200, 300], [300, 300], [400, 300]] # 六个位置rad = 100tick=0 #!!计数器while 1: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() # 每帧循环实行的代码 if tick>50: #每50次刷新变换一次 sur.fill((0, 0, 0)) # 用玄色覆盖前一帧的画面,实现刷新 a = random.randint(0, 5) # 随机0到5 pygame.draw.circle(sur, clr, pos6[a], 100) # 利用随机位置 tick=0 else: #!!不刷新变换的时候 tick=tick+1 #!!增加计数器 # 刷新画面 window.blit(sur, (0, 0)) pygame.display.flip()
增加交互点击
当用户点击画面的时候,我们要知道它点击了哪里,是否点击到了我们画的圆上面。
百度搜索【pygame 点击】可以找到干系资源,也可以直接在官方解释文档中找到。
思路是我们添加对event.type事宜类型的实时监测,一旦创造点击事宜就获取位置坐标。代码如下:
import pygameimport sysimport randomfrom pygame.locals import # 引入鼠标事宜类型pygame.init() # 初始化window = pygame.display.set_mode([600, 400]) # 设定窗口sur = pygame.Surface([600, 400]) # 绘制背景容器clr = (0, 0, 255)pos6 = [[200, 200], [300, 200], [400, 200], [ 200, 300], [300, 300], [400, 300]] # 六个位置rad = 100tick = 0 # !!计数器pos = pos6[0] # !!在表面记录圆的位置while 1: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == MOUSEBUTTONDOWN: # !
!
如果是鼠标按下事宜 mpos = pygame.mouse.get_pos() # !
!
获取鼠标位置 print(mpos) # 每帧循环实行的代码 if tick > 50: # 每50次刷新变换一次 sur.fill((0, 0, 0)) # 用玄色覆盖前一帧的画面,实现刷新 a = random.randint(0, 5) # 随机0到5 pos = pos6[a] # !!更新外部记录的圆的位置 pygame.draw.circle(sur, clr, pos, 100) # !!利用随机位置 tick = 0 # 重置计数器 else: # !!不刷新变换的时候 tick = tick+1 # !!增加计数器 # 刷新画面 window.blit(sur, (0, 0)) pygame.display.flip()
运行这个代码,任意点击屏幕上的时候就会打印出档期鼠标点击的位置。
间隔丈量知道当前圆的位置pos,也知道当前点击的位置mpos,这样我们就可以打算出两点之间的间隔,间隔大于圆半径的便是没有点到地鼠,间隔小于半径的便是点到地鼠了。
百度搜索【pygame 两点间隔】可以搜到一些打算间隔的方法,我们这里利用pygame官方供应的方法,测试下面代码:
import pygamea=pygame.math.Vector2.length(pygame.math.Vector2(3,4))print(a)
它会输出5(勾三股四玄五)。这里的(3,4)是pos和mpos相减得到的差。把这个思路带入原来的代码,得到:
import pygameimport sysimport randomfrom pygame.locals import # 引入鼠标事宜类型pygame.init() # 初始化window = pygame.display.set_mode([600, 400]) # 设定窗口sur = pygame.Surface([600, 400]) # 绘制背景容器clr = (0, 0, 255)pos6 = [[200, 200], [300, 200], [400, 200], [ 200, 300], [300, 300], [400, 300]] # 六个位置rad = 50tick = 0 # 计数器pos = pos6[0] # 表面记录圆的位置while 1: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == MOUSEBUTTONDOWN: # 如果是鼠标按下事宜 mpos = pygame.mouse.get_pos() # 获取鼠标位置 dis = pygame.math.Vector2( mpos[0]-pos[0], mpos[1]-pos[1]) # !!打算坐标差 len = pygame.math.Vector2.length(dis) # !!打算间隔 if len < rad: tick = 51 # !!立即变换位置 # 每帧循环实行的代码 if tick > 50: # 每50次刷新变换一次 sur.fill((0, 0, 0)) # 用玄色覆盖前一帧的画面,实现刷新 a = random.randint(0, 5) # 随机0到5 pos = pos6[a] # 更新外部记录的圆的位置 pygame.draw.circle(sur, clr, pos, 100) # 利用随机位置 tick = 0 # 重置计数器 else: # 不刷新变换的时候 tick = tick+1 # 增加计数器 # 刷新画面 window.blit(sur, (0, 0)) pygame.display.flip()
在这里我们设定如果间隔长度len小于圆半径rad,那么就立即设置tick=51使它大于50,立即进行随机位置变换。
截止到这里运行上面的代码,可以实现随机涌现地鼠(圆)并能够点击使它消逝,这也实现了游戏的最基本逻辑功能。后续我们将进一步编写更多内容,让它更完善一些。
记录分数打算数字增加很随意马虎,设定一个score=0,然后击中地鼠的时候增加1就可以了。但是,如何把它显示到屏幕上呢?
可以百度搜索【pygame 显示笔墨】然后就可以找到大致方法,我们前辈行一些测试:
import pygamepygame.init() # 初始化window = pygame.display.set_mode([600, 400]) # 设定窗口# 显示笔墨pygame.font.init() # !
!
初始化笔墨font = pygame.font.SysFont('微软雅黑', 30) # !
!
设定字体和字号sur = font.render("Hello World!!{}".format(999), False, (255, 0, 0)) # !
!
天生w笔墨表面while 1: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() window.blit(sur, (200, 10)) # !
!
增加分数表面 pygame.display.flip()
这段代码中可以看到pygame绘制笔墨分三步:
pygame.font.init()先要初始化pygame.font.SysFont('微软雅黑', 30)设定字体和字号大小font.render("Hello World!!{}".format(999), False, (255, 0, 0))天生一个Surface表面当然,末了别忘了把表面放到窗口里window.blit(sur, (200, 10))运行上面的代码得到一个窗口如下:
image
我们根据这个履历改进的代码:
import pygameimport sysimport randomfrom pygame.locals import # 引入鼠标事宜类型pygame.init() # 初始化window = pygame.display.set_mode([600, 400]) # 设定窗口sur = pygame.Surface([600, 400]) # 绘制背景容器clr = (0, 0, 255)pos6 = [[200, 200], [300, 200], [400, 200], [ 200, 300], [300, 300], [400, 300]] # 六个位置rad = 50tick = 0 # 计数器pos = pos6[0] # 表面记录圆的位置# 分数score = 0 # !
!
分数计数pygame.font.init() # !
!
初始化笔墨score_font = pygame.font.SysFont('微软雅黑', 30) # !
!
设定字体和字号score_sur = score_font.render(str(score), False, (255, 0, 0)) # !
!
天生计数表面while 1: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == MOUSEBUTTONDOWN: # 如果是鼠标按下事宜 mpos = pygame.mouse.get_pos() # 获取鼠标位置 dis = pygame.math.Vector2( mpos[0]-pos[0], mpos[1]-pos[1]) # 打算坐标差 len = pygame.math.Vector2.length(dis) # 打算间隔 if len < rad: tick = 1000 # 立即变换位置 score = score+1 # 计分增加 # 每帧循环实行的代码 if tick > 50: # 每50次刷新变换一次 score_sur = score_font.render( str(score), False, (255, 0, 0)) # !
!
重新天生分数笔墨表面 sur.fill((0, 0, 0)) # 用玄色覆盖前一帧的画面,实现刷新 a = random.randint(0, 5) # 随机0到5 pos = pos6[a] # 更新外部记录的圆的位置 pygame.draw.circle(sur, clr, pos, 50) # 利用随机位置 tick = 0 # 重置计数器 else: # 不刷新变换的时候 tick = tick+1 # 增加计数器 # 刷新画面 window.blit(sur, (0, 0)) window.blit(score_sur, (200, 10)) # !
!
增加分数表面 pygame.display.flip()
运行上面的代码,可以用鼠标点击跳动的蓝色圆,每次击中就能得到1分,实时显示在顶部。
关于笔墨的更多内容可以参考官方文档解释。
鼠标指针变锤子现在窗口中显示的仍旧是鼠标,而不是锤子,下面我们来看如何把鼠标变为一个特定的图形。
pygame关于鼠标掌握的模块是pygame.mouse,官方解释文档看这里。
我们可以用pygame.mouse.set_visible(False)来隐蔽鼠标,但这样一来我们就看不到鼠标无法操作了。
不过不要紧,我们之前还记得当鼠标点击的时候有一个mpos = pygame.mouse.get_pos()可以获取当前鼠标的位置,同样我们可以在鼠标移动的时候获取鼠标的位置,然后在这个位置上画一个赤色圆圈代表鼠标。
测试下面的代码:
import pygamefrom pygame.locals import pygame.init()window = pygame.display.set_mode([600, 400])pygame.mouse.set_visible(False) # 隐蔽鼠标sur = pygame.Surface([600, 400])mpos = [300, 200] # 记录鼠标位置while 1: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == MOUSEMOTION: # 当鼠标移动的时候 mpos = pygame.mouse.get_pos() # 更新鼠标位置 sur.fill((0, 0, 0)) # 添补玄色 pygame.draw.circle(sur, (255, 0, 0), mpos, 10) # 在鼠标位置画赤色圆 window.blit(sur, (0, 0)) pygame.display.flip()
运行这个代码将,当鼠标划到窗口上面的时候就会有一个红点随着鼠标移动,红点代替了原来的指针。
我们把这个红点鼠标代码放入到游戏中,得到下面的代码:
import pygameimport sysimport randomfrom pygame.locals import # 引入鼠标事宜类型pygame.init() # 初始化window = pygame.display.set_mode([600, 400]) # 设定窗口sur = pygame.Surface([600, 400]) # 绘制背景容器clr = (0, 0, 255)pos6 = [[200, 200], [300, 200], [400, 200], [ 200, 300], [300, 300], [400, 300]] # 六个位置rad = 50tick = 0 # 计数器pos = pos6[0] # 表面记录圆的位置# 分数score = 0 # 分数计数pygame.font.init() # 初始化笔墨score_font = pygame.font.SysFont('微软雅黑', 30) # !
!
设定字体和字号score_sur = score_font.render(str(score), False, (255, 0, 0)) # !
!
天生计数表面# 鼠标pygame.mouse.set_visible(False) # !!隐蔽鼠标mpos = [300, 200] # !!记录鼠标位置while 1: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == MOUSEBUTTONDOWN: # 如果是鼠标按下事宜 mpos = pygame.mouse.get_pos() # 获取鼠标位置 dis = pygame.math.Vector2( mpos[0]-pos[0], mpos[1]-pos[1]) # 打算坐标差 len = pygame.math.Vector2.length(dis) # 打算间隔 if len < rad: tick = 1000 # 立即变换位置 score = score+1 # 计分增加 elif event.type == MOUSEMOTION: # !!当鼠标移动的时候 mpos = pygame.mouse.get_pos() # !!更新鼠标位置 # 每帧循环实行的代码 if tick > 50: # 每50次刷新变换一次 score_sur = score_font.render( str(score), False, (255, 0, 0)) # 重新天生分数笔墨表面 a = random.randint(0, 5) # 随机0到5 pos = pos6[a] # 更新外部记录的圆的位置 tick = 0 # 重置计数器 else: # 不刷新变换的时候 tick = tick+1 # 增加计数器 # 绘制鼠标 sur.fill((0, 0, 0)) # !用玄色覆盖前一帧的画面,实现刷新 pygame.draw.circle(sur, clr, pos, 50) # !利用随机位置画地鼠 pygame.draw.circle(sur, (255, 0, 0), mpos, 10) # !!在鼠标位置画赤色圆 # 刷新画面 window.blit(sur, (0, 0)) window.blit(score_sur, (200, 10)) # 增加分数表面 pygame.display.flip()
主义者了把sur.fill和原来画地鼠蓝圆的代码移到了下面,和画鼠标红点的代码放在了一起,这样把绘图内容放在一起更加合理。
限定每局韶光我们有很多办法限定每局的长度,比如计时限定1分钟,或者限定地鼠跳出总计100次。我们这里利用第二种限定,跳出100次就结束并统计分数。
添加一个计数器times=0,然后每次随机位置都给它增加1,当times>100的时候,我们就结束游戏并显示结束画面统计战果。
详细的代码没有新的内容,不多阐明,直接上结果:
import pygameimport sysimport randomfrom pygame.locals import # 引入鼠标事宜类型pygame.init() # 初始化window = pygame.display.set_mode([600, 400]) # 设定窗口sur = pygame.Surface([600, 400]) # 绘制背景容器clr = (0, 0, 255)pos6 = [[200, 200], [300, 200], [400, 200], [ 200, 300], [300, 300], [400, 300]] # 六个位置rad = 50tick = 0 # 计数器pos = pos6[0] # 表面记录圆的位置# 分数score = 0 # 分数计数pygame.font.init() # 初始化笔墨score_font = pygame.font.SysFont('微软雅黑', 30) # !
!
设定字体和字号score_sur = score_font.render(str(score), False, (255, 0, 0)) # !
!
天生计数表面# 鼠标pygame.mouse.set_visible(False) # !!隐蔽鼠标mpos = [300, 200] # !!记录鼠标位置times = 0 # 地鼠跳出的次数times_max=10 #最多次数tick_max=15 #地鼠每次跳多少帧while 1: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == MOUSEBUTTONDOWN: # 如果是鼠标按下事宜 mpos = pygame.mouse.get_pos() # 获取鼠标位置 dis = pygame.math.Vector2( mpos[0]-pos[0], mpos[1]-pos[1]) # 打算坐标差 len = pygame.math.Vector2.length(dis) # 打算间隔 if len < rad: tick = 1000 # 立即变换位置 score = score+1 # 计分增加 elif event.type == MOUSEMOTION: # !!当鼠标移动的时候 mpos = pygame.mouse.get_pos() # !!更新鼠标位置 if times > times_max: # 显示结束画面 sur.fill((0, 0, 0)) pygame.mouse.set_visible(True) sur.fill((0, 0, 0)) end_font = pygame.font.SysFont('微软雅黑', 80) # !
!
设定字体和字号 end_sur = score_font.render("Your Score is:{}/{}!
".format(score,times_max), False, (255, 0, 0)) # !
!
天生计数表面 window.blit(sur, (0, 0)) window.blit(end_sur, (100, 100)) # 增加分数表面 pygame.display.flip() else: # 每帧循环实行的代码 if tick > tick_max: # 每50次刷新变换一次 times=times+1 #增加计次 score_sur = score_font.render( str(score), False, (255, 0, 0)) # 重新天生分数笔墨表面 a = random.randint(0, 5) # 随机0到5 pos = pos6[a] # 更新外部记录的圆的位置 tick = 0 # 重置计数器 else: # 不刷新变换的时候 tick = tick+1 # 增加计数器 # 绘制鼠标 sur.fill((0, 0, 0)) # !用玄色覆盖前一帧的画面,实现刷新 pygame.draw.circle(sur, clr, pos, 50) # !利用随机位置画地鼠 pygame.draw.circle(sur, (255, 0, 0), mpos, 10) # !!在鼠标位置画赤色圆 # 刷新画面 window.blit(sur, (0, 0)) window.blit(score_sur, (200, 10)) # 增加分数表面 pygame.display.flip()
运行这个代码,用鼠标点击蓝圆,蓝圆跳动10次之后结束,然后显示击中的次数。你可以通过调度tick_max的数字让圆跳动的更快或更慢,调度times_max=100来让地鼠跳动100次后再结束。
现在我们的地鼠游戏已经有些样子容貌了,但还都是蓝色赤色的圆圈和圆点,下一篇我们来改变成为图片。
中笔墨体在上一节中我们只利用了英笔墨体,怎么显示中笔墨体呢?
直接下载网盘里面的文件,放在你的main.py一起,将原来的
score_font = pygame.font.SysFont('微软雅黑', 30)
修正为:
score_font = pygame.font.Font('MicrosoftYaqiHeiLight-2.ttf', 30)
然后在render里面利用中文就可以正常显示了:
end_sur = score_font.render("你的得分:{}/{}!
".format(score,times_max), False, (255, 0, 0))
image
其余,也可以利用系统的中笔墨体,但是我们不清楚系统里面到底装了哪些字体,可以用print(pygame.font.get_fonts())将所有系统字体都打印出来,然后只能从名字猜出哪些是中笔墨体了,把稳系统字体还是要用font.SysFont而不但是font.Font。
显示背景图片这是我们的背景图片dds-map.jpg:
image
我们可以用map=pygame.image.load('dds-map.jpg')把图片读取到代码里面。更多官方关于图片的操作解释看这里把稳pygame.image.load()得到的是一个表面surface,我们可以直接把它blit到窗口wind,也可以把它blit到。
这里是完全代码:
import pygameimport sysimport randomfrom pygame.locals import # 引入鼠标事宜类型pygame.init() # 初始化window = pygame.display.set_mode([600, 400]) # 设定窗口sur = pygame.Surface([600, 400]) # 绘制背景容器clr = (0, 0, 255)posAll = [[100, 150], [300, 150], [500, 150], [ 200, 300], [400, 300]] # 六个位置rad = 50tick = 0 # 计数器pos = posAll[0] # 表面记录圆的位置# 分数score = 0 # 分数计数pygame.font.init() # 初始化笔墨score_font = pygame.font.Font('MicrosoftYaqiHeiLight-2.ttf', 30) # !
!
设定字体和字号score_sur = score_font.render(str(score), False, (255, 0, 0)) # !
!
天生计数表面# 鼠标pygame.mouse.set_visible(False) # !!隐蔽鼠标mpos = [300, 200] # !!记录鼠标位置times = 0 # 地鼠跳出的次数times_max=10 #最多次数tick_max=30 #地鼠每次跳多少帧map=pygame.image.load('dds-map.jpg')#!
!
读取图片while 1: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == MOUSEBUTTONDOWN: # 如果是鼠标按下事宜 dis = pygame.math.Vector2( mpos[0]-pos[0], mpos[1]-pos[1]) # 打算坐标差 len = pygame.math.Vector2.length(dis) # 打算间隔 if len < rad: tick = 1000 # 立即变换位置 score = score+1 # 计分增加 elif event.type == MOUSEMOTION: # 当鼠标移动的时候 mpos = pygame.mouse.get_pos() # 更新鼠标位置 if times >= times_max: # 显示结束画面 sur.fill((0, 0, 0)) #!
!
结束时候仍旧用玄色清空画面 pygame.mouse.set_visible(True) end_font = pygame.font.Font('MicrosoftYaqiHeiLight-2.ttf',48) # !
!
设定字体和字号 end_sur = score_font.render("你的分数是:{}/{}!
".format(score,times_max), True, (255, 0, 0)) # !
!
天生计数表面 window.blit(sur, (0, 0)) window.blit(end_sur, (100, 100)) # 增加分数表面 else: sur.blit(map, (0, 0)) #!
!
添加背景图片 # 每帧循环实行的代码 if tick > tick_max: # 每50次刷新变换一次 times=times+1 #增加计次 score_sur = score_font.render( "分数:{}/{}!
".format(score,times), False, (255, 0, 0)) # 重新天生分数笔墨表面 a = random.randint(0, 4) # 随机0到4 pos = posAll[a] # 更新外部记录的圆的位置 tick = 0 # 重置计数器 else: # 不刷新变换的时候 tick = tick+1 # 增加计数器 # 绘制鼠标 pygame.draw.circle(sur, clr, pos, 50) # 利用随机位置画地鼠 pygame.draw.circle(sur, (255, 0, 0), mpos, 10) # !在鼠标位置画赤色圆 # 刷新画面 window.blit(sur, (0, 0)) window.blit(score_sur, (200, 10)) # 增加分数表面 pygame.display.flip() #刷新画面
把稳我们先把图片读取,然后在每帧里面决定是否利用。运行后如下图:
image
利用动态图片地鼠和锤子各有两个状态,正常的地鼠和被击打的地鼠,正常的锤子和砸下的锤子,如下图所示(下图无法直策应用,请从网盘下载):
image
我们可以先把四个图片都load读取进来成为rat1,rat2,ham1,ham2,然后我们利用ratsur和hamsur表示真正要利用的表面,当鼠标按下的时候我们设定hamsur=ham2是砸下图片,当鼠标点击位置间隔地鼠小于地鼠半径的时候我们利用ratsur=rat2被砸中的图片。末了我们再分别把地鼠和锤头blit到sur上面。
改造后的代码如下:
import pygameimport sysimport randomfrom pygame.locals import # 引入鼠标事宜类型import timepygame.init() # 初始化window = pygame.display.set_mode([600, 400]) # 设定窗口sur = pygame.Surface([600, 400]) # 绘制背景容器clr = (0, 0, 255)posAll = [[100, 150], [300, 150], [500, 150], [ 200, 300], [400, 300]] # 六个位置rad = 50tick = 0 # 计数器pos = posAll[0] # 表面记录圆的位置# 分数score = 0 # 分数计数pygame.font.init() # 初始化笔墨score_font = pygame.font.Font('MicrosoftYaqiHeiLight-2.ttf', 30) # !
!
设定字体和字号score_sur = score_font.render(str(score), False, (255, 0, 0)) # !
!
天生计数表面# 鼠标pygame.mouse.set_visible(False) # !!隐蔽鼠标mpos = [300, 200] # !!记录鼠标位置times = 0 # 地鼠跳出的次数times_max=10 #最多次数tick_max=30 #地鼠每次跳多少帧map=pygame.image.load('dds-map.jpg')#!
!
读取图片rat1=pygame.image.load('rat1.png')#!
!
读取地鼠图片rat2=pygame.image.load('rat2.png')#!
!
读取被砸地鼠图片ham1=pygame.image.load('hammer1.png')#!
!
读取锤子图片ham2=pygame.image.load('hammer2.png')#!
!
读取砸下锤子图片while 1: hamsur=ham1 ratsur=rat1 for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == MOUSEBUTTONDOWN: # 如果是鼠标按下事宜 hamsur=ham2 #!
!
利用着落锤子 mpos = pygame.mouse.get_pos() # 获取鼠标位置 dis = pygame.math.Vector2( mpos[0]-pos[0], mpos[1]-pos[1]) # 打算坐标差 len = pygame.math.Vector2.length(dis) # 打算间隔 if len < rad: tick = 1000 # 立即变换位置 score = score+1 # 计分增加 ratsur=rat2 #!
!
利用被砸地鼠 elif event.type == MOUSEMOTION: # 当鼠标移动的时候 mpos = pygame.mouse.get_pos() # 更新鼠标位置 if times >= times_max: # 显示结束画面 sur.fill((0, 0, 0)) #结束时候仍旧用玄色清空画面 pygame.mouse.set_visible(True) end_font = pygame.font.Font('MicrosoftYaqiHeiLight-2.ttf',48) # !
!
设定字体和字号 end_sur = score_font.render("你的分数是:{}/{}!
".format(score,times_max), True, (255, 0, 0)) # !
!
天生计数表面 window.blit(sur, (0, 0)) window.blit(end_sur, (100, 100)) # 增加分数表面 else: sur.blit(map, (0, 0)) #添加背景图片 # 每帧循环实行的代码 if tick > tick_max: # 每50次刷新变换一次 times=times+1 #增加计次 score_sur = score_font.render( "分数:{}/{}!
".format(score,times), False, (255, 0, 0)) # 重新天生分数笔墨表面 a = random.randint(0, 4) # 随机0到4 pos = posAll[a] # 更新外部记录的圆的位置 tick = 0 # 重置计数器 else: # 不刷新变换的时候 tick = tick+1 # 增加计数器 sur.blit(ratsur,(pos[0]-50,pos[1]-70)) #绘制地鼠 sur.blit(hamsur,(mpos[0]-50,mpos[1]-100)) #绘制锤头 # 刷新画面 window.blit(sur, (0, 0)) window.blit(score_sur, (200, 10)) # 增加分数表面 pygame.display.flip() #刷新画面 time.sleep(0.04) #!
!
保持画面一点韶光
把稳这里的import time和time.sleep(0.04)这是让每一帧勾留一点点韶光,0.04秒,每秒25帧(假设每帧画图不须要韶光的话)。其余我们再blit的时候利用了(pos[0]-50,pos[1]-50)这样的偏移,由于图片总是用左上角作为位置的出发点,这样偏移之后就变到了图片中央,实际上我们又故意让地鼠和锤子更高一些,就利用了(pos[0]-50,pos[1]-70)。
运行之后的样子如下图:
image
让游戏重新开始每次显示终极成绩之后,能不能让游戏3秒后重新开始呢?
我们设定一个gameover=0,游戏结束后每帧都增加这个数字,如果gameover>100,便是过了100帧,那么我们就重新开始。重新开始必须意味着各种数据(分数,计时什么的)和画面都要重置到原来的状态。修正后的整体代码如下:
import pygameimport sysimport randomfrom pygame.locals import # 引入鼠标事宜类型import timepygame.init() # 初始化window = pygame.display.set_mode([600, 400]) # 设定窗口sur = pygame.Surface([600, 400]) # 绘制背景容器clr = (0, 0, 255)posAll = [[100, 150], [300, 150], [500, 150], [200, 300], [400, 300]] # 六个位置rad = 50tick = 0 # 计数器pos = posAll[0] # 表面记录圆的位置# 分数score = 0 # 分数计数pygame.font.init() # 初始化笔墨score_font = pygame.font.Font("MicrosoftYaqiHeiLight-2.ttf", 30) # !
!
设定字体和字号score_sur = score_font.render(str(score), False, (255, 0, 0)) # !
!
天生计数表面# 鼠标pygame.mouse.set_visible(False) # !!隐蔽鼠标mpos = [300, 200] # !!记录鼠标位置times = 0 # 地鼠跳出的次数times_max = 10 # 最多次数tick_max = 30 # 地鼠每次跳多少帧map = pygame.image.load("dds-map.jpg") # !
!
读取图片rat1 = pygame.image.load("rat1.png") # !
!
读取地鼠图片rat2 = pygame.image.load("rat2.png") # !
!
读取被砸地鼠图片ham1 = pygame.image.load("hammer1.png") # !
!
读取锤子图片ham2 = pygame.image.load("hammer2.png") # !
!
读取砸下锤子图片gameover = 0 #!
!
结束计时gameover_max = 100 #!
!
结束计时最大值,超过这个值就重新开始while 1: hamsur = ham1 ratsur = rat1 for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == MOUSEBUTTONDOWN: # 如果是鼠标按下事宜 hamsur = ham2 # !
!
利用着落锤子 mpos = pygame.mouse.get_pos() # 获取鼠标位置 dis = pygame.math.Vector2(mpos[0] - pos[0], mpos[1] - pos[1]) # 打算坐标差 len = pygame.math.Vector2.length(dis) # 打算间隔 if len < rad: tick = 1000 # 立即变换位置 score = score + 1 # 计分增加 ratsur = rat2 # !
!
利用被砸地鼠 elif event.type == MOUSEMOTION: # 当鼠标移动的时候 mpos = pygame.mouse.get_pos() # 更新鼠标位置 if times >= times_max: # 显示结束画面 sur.fill((0, 0, 0)) # 结束时候仍旧用玄色清空画面 pygame.mouse.set_visible(True) end_font = pygame.font.Font("MicrosoftYaqiHeiLight-2.ttf", 48) # !
!
设定字体和字号 end_sur = score_font.render( "你的分数是:{}/{}!
".format(score, times_max), True, (255, 0, 0) ) # !
!
天生计数表面 sur.blit(end_sur, (100, 150)) cd = int((gameover_max - gameover) / 10) cd_sur = score_font.render( "重新开始倒计时{}".format(cd), True, (255, 0, 0) ) # !
!
天生计数表面 sur.blit(cd_sur, (100, 200)) # 增加分数表面 gameover = gameover + 1 #!
!
增加结束计时 else: sur.blit(map, (0, 0)) # 添加背景图片 score_sur = score_font.render( "分数:{}/{}!
".format(score, times + 1), False, (255, 0, 0) ) # 重新天生分数笔墨表面 sur.blit(score_sur, (200, 10)) # 增加分数表面 if tick > tick_max: # 每50次刷新变换一次 times = times + 1 # 增加计次 a = random.randint(0, 4) # 随机0到4 pos = posAll[a] # 更新外部记录的圆的位置 tick = 0 # 重置计数器 else: # 不刷新变换的时候 tick = tick + 1 # 增加计数器 if tick > 5: # 开始几帧不显示地鼠 sur.blit(ratsur, (pos[0] - 50, pos[1] - 70)) # 绘制地鼠 sur.blit(hamsur, (mpos[0] - 50, mpos[1] - 100)) # 绘制锤头 # 刷新画面 window.blit(sur, (0, 0)) pygame.display.flip() # 刷新画面 time.sleep(0.04) # !
!
保持画面一点韶光 # !
!
重置游戏 if gameover > gameover_max: pygame.mouse.set_visible(False) times = 0 score = 0 gameover = 0
运行这个代码就能反复玩游戏了。到这里游戏看上去好了很多,但是还没有背景音乐,打地鼠的时候也没有音效,下一节我们连续添加声音。
添加音效游戏里面的声音分为两种,一种叫音乐music,另一种叫音效sound。背景音乐是music,游戏里面的击打声点击声都是音效。同一韶光播放的音乐一样平常只有一个,但音效可以有很多个同时播放。
pygame可以利用pygame.mixer.music.load('bg.mp3')来载入foo.mp3音乐,然后pygame.mixer.music.play(0)就可以播放,这里0表示播放1次,如果要无限次的播放则要改为-1.
但是如果要播放音效sound,那么pygame里面只能利用wav格式(并且不支持32位深,只支持16位深)。载入音效的方法是sd=pygame.mixer.Sound("hit.wav"),播放是sd.play(0),这里0也是1次,一样平常音效不须要连续播放。
我们在游戏一开始就可以播放背景音乐了,但只有在点击鼠标event.type == MOUSEBUTTONDOWN的时候才播放锤子的声音,只有在击中地鼠的时候才播放地鼠的叫声。
修正之后的代码如下:
import pygameimport sysimport randomfrom pygame.locals import # 引入鼠标事宜类型import timepygame.init() # 初始化window = pygame.display.set_mode([600, 400]) # 设定窗口sur = pygame.Surface([600, 400]) # 绘制背景容器clr = (0, 0, 255)posAll = [[100, 150], [300, 150], [500, 150], [200, 300], [400, 300]] # 六个位置rad = 50tick = 0 # 计数器pos = posAll[0] # 表面记录圆的位置# 分数score = 0 # 分数计数pygame.font.init() # 初始化笔墨score_font = pygame.font.Font("MicrosoftYaqiHeiLight-2.ttf", 30) # !
!
设定字体和字号score_sur = score_font.render(str(score), False, (255, 0, 0)) # !
!
天生计数表面# 鼠标pygame.mouse.set_visible(False) # !!隐蔽鼠标mpos = [300, 200] # !!记录鼠标位置times = 0 # 地鼠跳出的次数times_max = 10 # 最多次数tick_max = 30 # 地鼠每次跳多少帧map = pygame.image.load("dds-map.jpg") # !
!
读取图片rat1 = pygame.image.load("rat1.png") # !
!
读取地鼠图片rat2 = pygame.image.load("rat2.png") # !
!
读取被砸地鼠图片ham1 = pygame.image.load("hammer1.png") # !
!
读取锤子图片ham2 = pygame.image.load("hammer2.png") # !
!
读取砸下锤子图片gameover = 0 # !
!
结束计时gameover_max = 100 # !
!
结束计时最大值,超过这个值就重新开始# 音乐和音效pygame.mixer.music.load("bg.mp3") # !
!
载入背景音乐pygame.mixer.music.play(-1) # !
!
无限播放背景音乐hitsound = pygame.mixer.Sound("hit.wav") # !
!
载入击打声音hurtsound = pygame.mixer.Sound("aiyo2.wav") # !
!
载入地鼠叫声while 1: hamsur = ham1 ratsur = rat1 for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == MOUSEBUTTONDOWN: # 如果是鼠标按下事宜 hamsur = ham2 # 利用着落锤子 hitsound.play() # !
!
播放击打声音 mpos = pygame.mouse.get_pos() # 获取鼠标位置 dis = pygame.math.Vector2(mpos[0] - pos[0], mpos[1] - pos[1]) # 打算坐标差 len = pygame.math.Vector2.length(dis) # 打算间隔 if len < rad: tick = 1000 # 立即变换位置 score = score + 1 # 计分增加 ratsur = rat2 # 利用被砸地鼠 hurtsound.play() # !
!
播放地鼠声音 elif event.type == MOUSEMOTION: # 当鼠标移动的时候 mpos = pygame.mouse.get_pos() # 更新鼠标位置 if times >= times_max: # 显示结束画面 sur.fill((0, 0, 0)) # 结束时候仍旧用玄色清空画面 pygame.mouse.set_visible(True) end_font = pygame.font.Font("MicrosoftYaqiHeiLight-2.ttf", 48) # 设定字体和字号 end_sur = score_font.render( "你的分数是:{}/{}!
".format(score, times_max), True, (255, 0, 0) ) # 天生计数表面 sur.blit(end_sur, (100, 150)) cd = int((gameover_max - gameover) / 10) cd_sur = score_font.render( "重新开始倒计时{}".format(cd), True, (255, 0, 0) ) # 天生计数表面 sur.blit(cd_sur, (100, 200)) # 增加分数表面 gameover = gameover + 1 # !
!
增加结束计时 else: sur.blit(map, (0, 0)) # 添加背景图片 score_sur = score_font.render( "分数:{}/{}!
".format(score, times + 1), False, (255, 0, 0) ) # 重新天生分数笔墨表面 sur.blit(score_sur, (200, 10)) # 增加分数表面 if tick > tick_max: # 每50次刷新变换一次 times = times + 1 # 增加计次 a = random.randint(0, 4) # 随机0到4 pos = posAll[a] # 更新外部记录的圆的位置 tick = 0 # 重置计数器 else: # 不刷新变换的时候 tick = tick + 1 # 增加计数器 if tick > 5: # 开始几帧不显示地鼠 sur.blit(ratsur, (pos[0] - 50, pos[1] - 70)) # 绘制地鼠 sur.blit(hamsur, (mpos[0] - 50, mpos[1] - 100)) # 绘制锤头 # 刷新画面 window.blit(sur, (0, 0)) pygame.display.flip() # 刷新画面 time.sleep(0.04) # 保持画面一点韶光 # 重置游戏 if gameover > gameover_max: pygame.mouse.set_visible(False) times = 0 score = 0 gameover = 0
运行上面的代码,可以听到欢畅的背景音乐,点击鼠标时候会有捶地声音,打中地鼠会有哎呦的叫声。
发布软件我们写的代码目前只能在自己的电脑上运行,由于我们先要安装python,然后还要安装pygame才行,这和我们平常下载的软件不同,下载的软件可以直接运行(或者安装自身后运行)。
Python给我们供应了自动把代码打包成软件的工具,Windows下推举利用auto-py-to-exe工具。同样先安装pip install auto-py-to-exe,然后只要实行auto-py-to-exe就会打开一个窗口。
基本设置如下:
image
把稳几个地方:
Script Location要指向你的紧张.py文件,这里是main.pyOnefile选One Directory,这会把生产的所有文件放在一个文件夹中Console Window选Console Based,由于我们的pygame是基于掌握台的Icon图标,你可以在网高下载.ico文件,比如easyicon有很多,网盘里面有一个地鼠图标icon.icoAdditional Files附加文件,点击Add Files按钮要把全部用到的字体、图片、声音都选择CONVERT .PY TO .EXE点击这个按钮进行天生,天生后会变为两个蓝色按钮image
点击OPEN OUTPUT FOLDER打开生产的软件目录(默认在你的代码文件夹下面的output文件夹内),找到那个和你的Script Location同名的文件,点击它就可以运行游戏了。
image
也可以把这个MAIN.exe复制然后在桌面上粘贴快捷办法,往后只要点这个快捷办法就可以了。
image
在网盘文件中包含一个main.rar文件,下载它然后解压就可以得到我打包天生的软件了。
关于Mac苹果电脑下面天生软件的方法暂时碰着一点麻烦,搞定之后再更新,敬请关注。
第一个小游戏彷佛开拓完成了,但是还有很多内容,我们的代码也有很多不合理的地方,下一篇我们一起来回顾和整理,并且连续先容更多小游戏的开拓方法。
添加音效游戏里面的声音分为两种,一种叫音乐music,另一种叫音效sound。背景音乐是music,游戏里面的击打声点击声都是音效。同一韶光播放的音乐一样平常只有一个,但音效可以有很多个同时播放。
本文的笔墨及图片来源于网络加上自己的想法,仅供学习、互换利用,不具有任何商业用场,版权归原作者所有,如有问题请及时联系我们以作处理。