若是你没有任何编程经验,并且想尝试一下学习编程开发,这个系列教程必定适合你,它将带你学习最基本的Python语法,并让你掌握小游戏的开发技巧。你所须要的,就是付出一些时间和耐心来尝试这些代码和操做。
@[top]html
1 下载安装 python
2 下载安装VS code
编辑器
安装时,要注意勾选 添加到path
3 安装pygame模块python
Terminal-New Teminal
】打开命令行终端,而后输入命令python -m pip install --upgrade pip
,回车,等待完成。而后一样输入命令pip install pygame,等待完成安装,可能须要几分钟
编程
在桌面上建立一个文件夹mygame
,而后在VSCode中使用菜单【File-Open Folder】,选择mygame
文件夹,VSCode左侧将会出现EXPLORER导航栏。windows
在左侧导航栏中,【右键-New File】建立文件main.py
。数组
- 将下面的代码粘贴到右侧`main.py`文件中。
import pygame import sys pygame.display.set_mode([600,400]) while 1: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit()
在这里我仍是要说一下,文中素材以及可执行代码能够加群:456926667,获取,这个是我建立的一个针对0基础的伙伴一个交流群,下个文章我会更新关于pycharm版本的打地鼠。dom
* 仍然【Terminal-New terminal】终端中输入命令`python main.py`,这将运行咱们上面的代码,看到弹出一个黑色窗口。
执行上面的操做的时候,VSCode的右下角会常常弹出一些提示,若是有【Install】字样,能够放心的点击它进行安装更多内容。编辑器
也能够从左侧栏点击图标打开【EXTENSIONS】,而后搜索@id:ms-python.python
,点击找到的结果,右侧再点击【Install】按钮进行安装。安装以后main.py
文件的右上角就会出现三角形运行按钮,点击它一样能够运行代码,至关于终端中输入python main.py
。工具
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 pygame import sys pygame.init() # 初始化 window = pygame.display.set_mode([600, 400]) # 设定窗口 sur = pygame.Surface([600, 400]) # 绘制背景容器 clr = (0, 0, 255) pos = (300,200) rad = 100 while 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 random a = random.randint(0, 5) print(a)
每次运行都能生成不一样的数字。
继续测试:
import random a = 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 pygame import sys import random 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 = 100 while 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帧再随机变换一次,而不是如今的每帧都随机变。思路是这样的:咱们设定一个计数器,开始是0,每帧都给它增长1,就是0,1,2,3,4...
直到它增到到超过50,这时候咱们就改变圆的位置并同时把计数器重置为0。
代码以下:
import pygame import sys import random 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 = 100 tick=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 pygame import sys import random from 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 = 100 tick = 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 pygame a=pygame.math.Vector2.length(pygame.math.Vector2(3,4)) print(a)
它会输出5(勾三股四玄五)。这里的(3,4)
是pos
和mpos
相减获得的差。
把这个思路带入原来的代码,获得:
import pygame import sys import random from 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 = 50 tick = 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 pygame pygame.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))
运行上面的代码获得一个窗口以下:
咱们根据这个经验改进的代码:
import pygame import sys import random from 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 = 50 tick = 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 pygame from 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 pygame import sys import random from 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 = 50 tick = 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 pygame import sys import random from 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 = 50 tick = 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))
另外,也可使用系统的中文字体,可是咱们不清楚系统里面到底装了哪些字体,能够用
print(pygame.font.get_fonts())
将全部系统字体都打印出来,而后只能从名字猜出哪些是中文字体了,注意系统字体仍是要用font.SysFont
而不仅是font.Font
。
这是咱们的背景图片dds-map.jpg
:
咱们能够用map=pygame.image.load('dds-map.jpg')
把图片读取到代码里面。
更多官方关于图片的操做说明看这里
注意pygame.image.load()
获得的是一个表面surface
,咱们能够直接把它blit
到窗口wind
,也能够把它blit
到。
这里是完整代码:
import pygame import sys import random from 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 = 50 tick = 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() #刷新画面
注意咱们先把图片读取,而后在每帧里面决定是否使用。运行后以下图:
地鼠和锤子各有两个状态,正常的地鼠和被击打的地鼠,正常的锤子和砸下的锤子,以下图所示(下图没法直接使用,请从网盘下载):
咱们能够先把四个图片都load
读取进来成为rat1,rat2,ham1,ham2
,而后咱们使用ratsur
和hamsur
表示真正要使用的表面,当鼠标按下的时候咱们设定hamsur=ham2
是砸下图片,当鼠标点击位置距离地鼠小于地鼠半径的时候咱们使用ratsur=rat2
被砸中的图片。最后咱们再分别把地鼠和锤头blit
到sur
上面。
改造后的代码以下:
import pygame import sys import random from pygame.locals import * # 引入鼠标事件类型 import time 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 = 50 tick = 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)
。
运行以后的样子以下图:
每次显示最终成绩以后,能不能让游戏3秒后从新开始呢?
咱们设定一个gameover=0
,游戏结束后每帧都增长这个数字,若是gameover>100
,就是过了100帧,那么咱们就从新开始。
从新开始必须意味着各类数据(分数,计时什么的)和画面都要重置到原来的状态。
修改后的总体代码以下:
import pygame import sys import random from pygame.locals import * # 引入鼠标事件类型 import time 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 = 50 tick = 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 pygame import sys import random from pygame.locals import * # 引入鼠标事件类型 import time 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 = 50 tick = 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
就会打开一个窗口。
基本设置以下:
注意几个地方:
main.py
.ico
文件,好比easyicon有不少,网盘里面有一个地鼠图标icon.ico
点击OPEN OUTPUT FOLDER打开生产的软件目录(默认在你的代码文件夹下面的output文件夹内),找到那个和你的Script Location同名的文件,点击它就能够运行游戏了。
也能够把这个MAIN.exe复制而后在桌面上粘贴快捷方式,之后只要点这个快捷方式就能够了。
在网盘文件中包含一个main.rar文件,下载它而后解压就能够获得我打包生成的软件了。
关于Mac苹果电脑下面生成软件的方法暂时遇到一点麻烦,搞定以后再更新,敬请关注。
第一个小游戏彷佛开发完成了,可是还有不少内容,咱们的代码也有不少不合理的地方,下一篇咱们一块儿来回顾和整理,而且继续介绍更多小游戏的开发方法。
游戏里面的声音分为两种,一种叫音乐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 pygame import sys import random from pygame.locals import * # 引入鼠标事件类型 import time 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 = 50 tick = 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
运行上面的代码,能够听到欢快的背景音乐,点击鼠标时候会有捶地声音,打中地鼠会有哎呦的叫声。