• 0
  • 0
分享

如果想尝试着用python做一款简单好玩的小游戏"飞行的小鸟",那就得用到pygame这个模块,让我们先简单了解一下pygame吧。

pygame是一个利用SDL库(全名Simple DirectMedia Layer)写就的游戏库。安装好python3环境以后,可以用pip3 install pygame命令来安装pygame。pygame有很多的模块,我们这个游戏会用到以下模块:

  • pygame:主模块,一些通用的控制

  • pygame.display:用来访问显示设备

  • pygame.draw:绘制形状,线和点

  • pygame.rect:管理矩形区域

  • pygame.init:初始化的一些定义

  • pygame.font:使用字体

  •  pygame.time:管理时间和帧信息

另外因为游戏需要用到很多随机数,所以还需要random模块,也可以通过pip3命令安装。

既然是实现"飞行的小鸟"游戏,首先要有鸟和管子,这里我想通过类来分别定义小鸟和管子。小鸟和管子还要在屏幕上显示,所以这个屏幕的显示也是要定义的。首先看看这个屏幕的定义吧,下面是屏幕定义的代码和一些注释:

pygame.init()
# 定义颜色
PIPE = (0,0,255)
SKY = (135,206,250)
BIRD = (220,20,60)
GROUND = (245,245,220)
# 设置游戏幕布大小
size = (800, 650)
screen = pygame.display.set_mode(size)
# 标题设置
pygame.display.set_caption("Flappy Block")
#字体设置
arial18 = pygame.font.SysFont('arial',18, False, False)
# 游戏未结束
done = False
# 时钟
clock = pygame.time.Clock()
# 游戏初始状态
gameState = 1 #未开始
pipes = []#定义管子的list

pygame.init函数,初始化pygame模块,好让我们可以利用pygame的那些模块。比如pygame.font,pygame.draw等(上面列举到的模块)。

然后程序里定义各个对象的颜色,包括小鸟、管子、天空、背景,完了再设置游戏的屏幕大小。幕布左上角坐标是(0,0)设置了游戏的显示标题,还有字体。默认游戏是未开始的状态。gameState=1,代表游戏初始未开始。pipes=[],管子是有序的,所以用list定义。

现在来用类定义小鸟。python是强制缩进的,所以可以很清楚的看到代码块,一个代码块实现一定的逻辑。

# 定义小鸟
class Bird():
def __init__(self):
self.x = 250  # 小鸟x坐标
self.y = 250  # 小鸟y坐标
self.yV = 0   # 小鸟的位置初始化
# 定义小鸟的下降振幅
def flap(self):
self.yV = -5  # 每次下降的位移
# 定义小鸟的上升振幅和y周的上下边界
def update(self):
self.yV += 0.3  # 小鸟上升速度
self.y += self.yV  # y轴位置等于原位置加yV振幅
# 定义小鸟的飞行
def draw(self):
pygame.draw.rect(screen, BIRD, (self.x, self.y, 40, 40))#参数为(幕布,颜色,坐标,大小)
# 重置小鸟
def reset(self):
self.x = 250
self.y = 250
self.yV = 0
bird = Bird()# 实例一个小鸟

类class Bird():定义了小鸟。__init(self)__方法初始化了小鸟的位置等信息。注意这个self,在python语言里,类的方法,会有一个默认的参数,一般通用的都是用self表示,这个self是代表类的自身。flap方法定义了小鸟每次下降的位移。update方法定义了小鸟的上升。draw方法通过调用pygame.draw.rect实现了小鸟的飞行。reset方法重置小鸟的位置。bird=Bird()是小鸟类的实例化。

下面来定义管子:

# 定义管子
class Pipe():
def __init__(self):
self.centerY = random.randrange(180, 520)  # 管子的y轴中间值范围
(大数上面管子长,小数下面管子长)
self.x = 800  # 管子的初始x轴位置
self.size = 150  # 上下两个管子之间的空间宽度的一半
# 更新管子
def update(self):
# 几个全局变量
global pipes
global bird
global gameState
self.x -= 4  # 管子的移动速度,因为小鸟其实没有动x轴的位移,小鸟其实是不前进的,只是上下跳动
# 管子的初始位置
if self.x == 300:
pipes.append(Pipe())  # 显示一个新管子
if self.x <= -100:
del pipes[0]  # 删除一个不再显示的管子
# 小鸟撞到管子,游戏结束,第一个条件是撞到下面的管子,第二个条件是撞到上面的管子(小鸟位置固定,管子在x轴运动)
#小鸟的y轴位移小于管子的y轴范围减去中间空的部分
#或者小鸟的y轴位移+40大于管子的y轴范围加上中间空的部分,40是小鸟的长度
#则小鸟撞到管子,游戏结束
if self.x >= 170 and self.x <= 290 and bird.y <= (self.centerY - self.size) \
or self.x >= 170 and self.x <= 290 and (bird.y + 40) >= (self.centerY + self.size):
gameState = 3  # 结束
# 小鸟飞过管子,游戏继续,两个75等于size的150
if self.x == 168 and bird.y > (self.centerY - 75) and bird.y < (self.centerY + 75):
gameState = 2
# 小鸟撞到地面,游戏结束
if bird.y >= 610:
gameState = 3
# 定义管子的显示
def draw(self):
# 定义上面管子的显示(幕布,颜色,坐标,宽=80,长)
pygame.draw.rect(screen, PIPE, (self.x, 0, 80, (self.centerY - self.size)))
# 定义下面管子的显示
pygame.draw.rect(screen, PIPE, (self.x, (self.centerY + self.size), 80, (548 - self.centerY)))
# 实例化管子,显示新管子
pipes.append(Pipe())

管子的这个类,我们说说和小鸟不一样的地方。update方法实现了管子的更新显示。注意global,global使参数全局化。管子的移动是self.x=4,说明管子是从右向左运动,速率是4。(所以这个游戏里,其实是管子在左右动,而小鸟其实只是上下动,没有进行x轴的运动)。

pipes.append(Pipe())是列表调用类,列表的append方法,是给列表里插入一个新的元素。这里代表显示(插入)一个新管子。del pipes[0],列表中0代表第一个元素的位置,也就是删掉第一个管子(管子不再显示)。

小鸟碰到管子

if self.x >= 170 and self.x <= 290 \ #管子的位置在120-290之间
and bird.y <= (self.centerY - self.size) \#并且小鸟的身体碰到了上面的管子
or self.x >= 170 and self.x <= 290 and (bird.y + 40) >= (self.centerY + self.size):#小鸟的身体碰到了下面的管子
gameState = 3  # 结束

小鸟飞过管子

# 小鸟飞过管子,游戏继续,两个75等于self.size的150
if self.x == 168 and bird.y > (self.centerY - 75) and bird.y < (self.centerY + 75):
gameState = 2

管子的x轴位置168,表示穿过了。而且小鸟刚好在两个管子的空间self.size里。

实现管子的显示

# 定义管子的显示
def draw(self):
# 定义上面管子的显示(幕布,颜色,坐标,宽=80,长)
pygame.draw.rect(screen, PIPE, (self.x, 0, 80, (self.centerY - self.size)))
# 定义下面管子的显示
pygame.draw.rect(screen, PIPE, (self.x, (self.centerY + self.size), 80, (548 - self.centerY)))
# 实例化管子,显示新管子
pipes.append(Pipe())

现在看一下游戏的具体实现。

游戏要有控制键,设置为空格键控制。游戏结束要退出,用QUIT方法。游戏有三个状态:

1:未开始;2:进行中;3:结束

首先游戏未开始时,点击空格键可以开始游戏,游戏结束以后,可以重新开始游戏,这需要重置小鸟和管子。游戏运行中的小鸟和管子,就是刷新显示小鸟和管子。

还需要定义一下游戏开始的按钮显示

#定义游戏开始键
#参数为显示的地方,颜色,面板的位置和大小
pygame.draw.rect(screen,GROUND,(300,300,200,100))#开始键的面板,
#参数为显示的文字,是否显示,颜色
text = arial18.render("Press space to play",True,SKY)#文字
#文字的位置设置
textX = text.get_rect().width
textY = text.get_rect().height
screen.blit(text,((400 - (textX / 2)),(350 - (textY / 2))))#字的填充位置

同样还要设置游戏结束的按钮,只是文案稍微加上gameover。

然后要考虑到整个页面的刷新,用pygame.display.flip方法。画面刷新时间控制由pygame.timeClock.tick控制。

以下是游戏运行的主要函数:

# -------- Main Program Loop -----------
#当游戏没结束
while not done:
# --- Main event loop
# pygame的event方法
for event in pygame.event.get():
if event.type == pygame.QUIT:  # 退出游戏
done = True
# 游戏键位设置
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:  # 设置为空格键
if gameState == 1:  # 游戏未开始状态为1
gameState = 2  # 游戏中状态为2
elif gameState == 3:  # 游戏结束状态为3
bird.reset()  # 小鸟重置
# 管子list重置
pipes = []
pipes.append(Pipe())
# 游戏中
gameState = 2
else:  # 没有管子的时候,小鸟飞行
bird.flap()
screen.fill(SKY)  # 屏幕填色
if gameState == 1: #游戏未开始时
#定义游戏开始键
pygame.draw.rect(screen,GROUND,(300,300,200,100))#开始键的面板,参数为xy轴位置,xy方向的大小
text = arial18.render("Press space to play",True,SKY)#文字
#文字的位置设置
textX = text.get_rect().width
textY = text.get_rect().height
screen.blit(text,((400 - (textX / 2)),(350 - (textY / 2))))#字的填充位置
# 当游戏运行中
if gameState == 2:
# 小鸟的飞行更新
bird.update()
bird.draw()
# 管子的更新显示
for pipe in pipes:
pipe.update()
pipe.draw()
# 当游戏结束
if gameState == 3:
for pipe in pipes:
pipe.draw()
bird.draw()
pygame.draw.rect(screen,GROUND,(300,300,250,100))#开始键的面板
text = arial18.render("Game Over,Press space to play",True,SKY)#文字
#文字的位置设置
textX = text.get_rect().width
textY = text.get_rect().height
screen.blit(text,((420 - (textX / 2)),(350 - (textY / 2))))#字的填充位置
# 刷新页面
pygame.display.flip()
# 画面更新时间,单位:秒
clock.tick(50)
pygame.quit()

游戏的实现效果是这样的:用方块来代替小鸟。

14982672_201804280948252HUEj.jpg

以上就是这个小游戏的实现过程了,大家可以自己研究加上小鸟穿过管子后的计分功能,也可以把小鸟美化一下,或者给游戏设置由易到难的玩法,可以各种尝试。大家一起试试吧!


版权声明:本文出自51Testing原创,51Testing软件测试网及相关内容提供者拥有内容的全部版权,未经明确的书面许可,任何人或单位不得对本网站内容复制、转载或进行镜像,否则将追究法律责任。

  • 【留下美好印记】
    赞赏支持
登录 后发表评论
+ 关注

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          •   苹果公司CEO蒂姆?库克在接受《早安美国》节目的采访时表示,他使用了ChatGPT这款聊天机器人,并对其感到兴奋。他还透露,苹果正在密切关注这项技术,并有一些独特的应用场景。  ChatGPT是由OpenAI开发的一款基于生成式人工智能(generativeAI)的聊天机器人,可以与人类进行自然的对话。据报道,今年早些时候,苹果公司出于隐私方面的考虑,限制了员工使用ChatGPT。  当被问及是否使用OpenAI的聊天机器人时,库克称:“哦,我当然使用它。是的,我对它很兴奋。我认为它有一些独特的应用,你可以相信这是我们正在密切关注的东西。”  库克对人工智能和生成式人工智能持谨慎态度,而其...
            0 0 532
            分享
          • 我发现,在OO和UML几乎一统天下的今天,仍有很多系统分析员对OO和UML一知半解,甚至包括很多已经使用了很久UML的系统分析员。于是打算写一个系列文章,将多年来的工作经验做一个总结。对初学者起个启蒙作用,也希望抛砖引喻,与各路大虾共同探讨,共同提高。这个系列文章将以我对OO和系统分析的理解为主,从UML基础开始,阐述面向对象的需求分析方法,过程,并以RUP为例,阐述如何将OO过程与软件过程有机结合在一起,做一个真正OO应用。好了,今天是第一篇。想得很远,不知能否坚持下去,呵呵:lol:用例是什么?其原始英文是usecase,直译过来就成了用例。这也是一个比较贴切的叫法了,从字面的直接理解就是...
            13 14 1165
            分享
          •   大家测试过程中经常用的等价类划分、边界值分析、场景法等,并不能覆盖所有的需求,下面就来讲一种不经常用到但又非常重要的测试用例编写方法。  因果图  应用场景:页面上有多个控件(输入),控件(输入)之间存在不同的组合关系,不同组合之间又可以产生不同的输出结果,符合这个条件的页面可以使用因果图法。  通过应用场景我们发现,一个手机壳外形选择页面的用例就可以按照这种方法编写。  我们假设我们手机,品牌有品牌1和品牌2,品牌1对应的型号有型号1、型号2,品牌2对应的型号有型号3、型号4,我们所有的手机外形有外形1,外形2,但是外形1只能给品牌1的手机使用,外形2品牌2的手机使用;除固定选择外,还有...
            0 0 660
            分享
          • 岁月流逝,万物轮回依旧,人生苦短,酸甜苦辣咸,构造丰富多彩人生。也曾失落彷徨,也曾泪水流淌,也曾过度失望!但内心那颗不骄不躁,不卑不亢的心一直在挣扎徘徊。我不否认我是一个患得患失,多愁善感的人。即便如此,骨子里流淌着的不乏那一种不安于现状,不妥协沉望的劲头。一辈子很长也很短,有时候长的让人浮想联翩,有时候短的让人一蹴而就,似乎一转眼生命就到了尽头。好吧,我不想引申这方面。总之一句话,人生苦短,干!目前从事测试工程师职位,说起来也是不可思议。行伍出身的我,在退伍复员后,没有明确追求,机缘巧合,加入到测试大军中去。这一个转身,简直没谁了。外表强壮的我,说话谈吐硬汉腔调的我,怎么也跟戴眼镜穿格子衫的...
            0 0 5266
            分享
          • jmeter可以用来测接口和性能,由于水平有限,只能大概谈一谈接口。(接口文档跟开发要。)解压好后打开bin目录,里面有个jmeter.bat,运行就打开了。页面挺简单的,就不一一介绍了(实际是不会介绍,上来就干活吧。)这是页面,右击测试计划-->添加-->Threads(Users)-->线程组接下来右击线程组-->Sampler-->HTTP请求再添加响应断言,断言结果,查看结果树什么的,监听器里面的中文基本都可以添加看看,(英文再研究研究)添加完成这种效果,点击http请求,开始在里面填内容,接口在这里就简单模拟一下,抓一个登录接口。URL里的http是协议...
            0 0 859
            分享
      • 51testing软件测试圈微信