Python的强大超出你的认知,Python的功能不止于可以做网络爬虫,数据分析,Python完全可以进行后端开发,AI,Python也可进行游戏开发,本文将会详细介绍Python使用pygame模块来开发一个名为“合金弹头”的游戏
本文将会介绍一款经典的射击类游戏:合金弹头,合金弹头游戏要求玩家控制自己的角色不断前行,并发射子弹去射击沿途遇到的各种怪物,同时还要躲避怪物发射的子弹。当然,由于完整的合金弹头游戏涉及的地图场景很多,而且怪物种类也很多,因此本文对该游戏进行了适当的简化。本游戏只实现了一个地图场景,并将之设置为无限地图,并且只实现了3种类型的怪物,但只要读者真正掌握了本文的内容,当然也就能从一个地图扩展为多个地图;也可以从3种类型的怪物扩展出多种类型的怪物了。
对于Python学习者来说,学习开发这个小程序难度适中,而且能很好地培养学习者的学习乐趣。开发者需要从程序员的角度来看待玩家面对的游戏界面,游戏界面上的每个怪物、每个角色、每颗子弹、每个能与玩家交互的东西,都应该在程序中通过类的形式来定义它们,这样才能更好地用面向对象的方式来解决问题。
本文将会介绍Python的一个游戏包:pygame,这个游戏包简化了游戏界面开发的计时器、多线程等复杂处理,因此使用pygame来开发游戏会更加简便。
合金弹头游戏简介
合金弹头是一款早期风靡一时的射击类游戏,这款游戏的节奏感非常强,让大部分男同胞充满童年回忆。图1显示了合金弹头的游戏界面。
图1 合金弹头
这款游戏的玩法很简单,玩家控制角色不断地向右前进,角色可通过跳跃来躲避敌人(也可统称为怪物)发射的子弹和地上的炸弹,玩家也可控制角色发射子弹来打死右边的各种敌人。对于完整的合金弹头游戏,它会包含很多“关卡”,每个关卡都是一种地图,每个关卡都包含了大量不同的怪物。但本文由于篇幅关系,只做了一种地图,而且这种地图是“无限循环”的—也就是说,玩家只能一直向前去消灭不同的怪物,无法实现“通关”。
提示
如果读者有兴趣把这款游戏改成包含很多关卡的游戏,那就需要准备大量的背景图片。然后为不同的地图加载不同的背景图片,让地图不要无限循环即可,并为不同地图使用不同的怪物。
pygame是一个成熟的Python游戏包,下面简单介绍一下pygame相关的知识。
安装pygame包与安装其他Python包没有什么区别,同样可使用pip来安装。
启动命令行窗口,在命令行窗口中输入如下命令:
pip install pygame
上面命令将会自动安装pygame包的最新版本。运行上面命令会先看到程序先下载pygame包,然后可看到pygame安装成功的提示。
Installing collected packages: pygameSuccessfully installed pygame-1.9.4
提示
pip其实也是Python的一个模块,如果命令行窗口提示找不到pip命令,也则可通过python命令运行pip模块来安装pygame。例如通过如下命令来安装pygame包。
python -m pip install pygame
成功安装pygame包之后,可通过pydoc来查看pygame的相关文档。在命令行窗口输入如下命令:
python -m pydoc -p 8899
运行上面命令之后,打开浏览器查看http://localhost:8899/页面,可在Python安装目录的lib\site-packages下看到pygame包的文档,如图2所示。
图2 pygame的文档
如果单击图2所示页面上的“pygame(package)”链接,将可看到3所示的API页面。
图3 pygame包的内容
通过3所示的页面即可查看pygame包下的函数和类。
pygame常用的游戏API
从图3可以看出,pygame包中包含了大量的内容,比如image模块可用于读取和保存文件,transform模块可对图片执行变换等。下面简单介绍pygame包下常用的游戏API。
调用pygame.image模块的load()函数可读取图片,该函数返回一个包含图片的Surface,Surface的格式和原来的文件相同(包括颜色格式、透明色和alpha透明)。
例如如下代码。
img = pygame.image.load(filename)
pygame.image.load()函数用于读取文件名为filename的图像文件,pygame会自动确定图片文件的类型(比如GIF或PNG等),该方法说支持JPG、PNG、GIF(非动画)、BMP、PCX、TGA (未压缩图片)、TIF、LBM、PBM (及PGM、PPM)、XPM等。
调用pygame.image模块的save()函数可保存图片,该函数的第一个参数是一个包含图片的Surface,第二个参数是要保存图片的文件。
例如如下代码。
pygame.image.save(img, filename)
该函数用于将img代表的Surface的内容保存为filename指定的图像文件中,filename可指定图片文件的扩展名,pygame会自动根据文件扩展名来确定图片的格式。如果pygame不能识别文件扩展名代表的图片格式,则默认保存为TGA格式(GA和BMP格式都是非压缩的文件)
此外,还有pygame.image还提供了tostring()、fromstring()、frombuffer()函数来完成图像序列化操作:也就是用于将图像保存到字符串、或从字符串中读取图像。
使用pygame.transform模块flip()函数可对图像执行水平或垂直镜像。该函数的第一个参数用于指定需要执行变换的原图像,第二个参数指定是否对图像执行垂直镜像,第三个参数指定是否对图像执行水平镜像。该函数不会改变原来的图像、它返回变换成功之后的图像。
例如如下代码对图像执行垂直镜像。
newimg = pygame.transform.flip(img, True, False)
如下代码对图像执行水平镜像。
newimg = pygame.transform.flip(img, False, True)
使用pygame.transform模块的scale()可以对图像进行缩放,该函数的第一个参数用于指定需要执行变换的原图像,第二个参数指定缩放之后的图像大小。该函数不会改变原来的图像、它返回变换成功之后的图像。
例如如下代码将原图像缩放到宽1200,高600
newimg = pygame.transform.resize(img, (1200, 600))
使用pygame.transform模块的scale2x()可以将图像放大到原来的2倍,该函数相当于resize()函数的便利化版本。
例如如下代码将原图像放大的原来的2倍。
newimg = pygame.transform.scale2x(img)
使用pygame.transform模块的rotate()可以对图像进行旋转,该函数的第一个参数用于指定需要执行变换的原图像,第二个参数指定旋转的角度,正值为逆时针旋转,负值是顺时针旋转。该函数不会改变原来的图像、它返回变换成功之后的图像。
例如如下代码将原图像逆时针旋转30度。
newimg = pygame.transform.rotate(img, 30.0)
需要说明的是,图像旋转之后可能比原来的图像更大,新图像空出来的部分补上透明色或原图像左上角第一个点的颜色。
使用pygame.transform模块的rotozoom()可以对图像进行缩放并旋转,该函数的第一个参数用于指定需要执行变换的原图像;第二个参数指定旋转的角度,正值为逆时针旋转,负值是顺时针旋转;第三个参数指定缩放比。该函数不会改变原来的图像、它返回变换成功之后的图像。
例如如下代码将原图像逆时针旋转30度、并放大到原来的2倍。
newimg = pygame.transform.rotozoom(img, 30.0, 2.0)
rotozoom()函数会对图像进行滤波处理,因此图像效果会更好,但是速度会慢一些。
使用pygame.transform模块的chop()可以对图像进行裁切,该函数的第一个参数用于指定需要执行裁切的原图像;第二个参数指定裁切的区域。该函数不会改变原来的图像、它返回变换成功之后的图像。
例如如下代码从原图像中“挖出”(50, 50, 100, 100)区域的一块。
newimg = pygame.transform.chop(img, (50, 50, 100, 100))
使用Surface的blit()方法可将图片绘制在该Surface表面。该方法完整形式为blit(source, dest, area=None, special_flags = 0),该方法第一个参数指定要绘制的图片,dest参数指定将source图片的绘制位置;area参数指定将只绘制source图片的指定区域。
例如如下代码可用于绘制游戏的背景图。
screen.blit(view_manager.map, (0, 0))
上面代码将map图片绘制到screen的(0,0)位置处,上面代码并未指定area参数,因此该代码会将map整张图片绘制在screen的(0,0)位置处。
下面代码同样同样用于绘制游戏的背景图。
screen.blit(self.map, (0, 0), (-player.shift(), 0, width, self.map.get_height()))
上面代码指定了area参数,该参数定义一个矩形,代表只将map图片的指定区域绘制在screen上。
如果要绘制几何图形,则可用pygame.draw模块所提供的相关函数。
rect(Surface, color, Rect, width=0) -> Rect:该函数在Surface上使用color绘制一个矩形。
polygon(Surface, color, pointlist, width=0) -> Rect:该函数在Surface上使用color绘制一个多边形,其中pointlist指定多边形的多个顶点。
line(Surface, color, start_pos, end_pos, width=1) -> Rect:该函数在Surface上使用color绘制一条线段,其中startpos指定线段的起点,end_pos指定线段的终点。
aaline(Surface, color, startpos, endpos, blend=1) -> Rect:该函数与line()函数基本相似,只是该函数用于绘制去锯齿的线段。
circle(Surface, color, pos, radius, width=0) -> Rect:该函数用于在Surface上使用color绘制一个圆。其中pos指定该圆的圆心,而radius指定圆的半径。
ellipse(Surface, color, Rect, width=0) -> Rect:该函数用于在Surface上使用color绘制一个椭圆。其中Rect参数用于指定该椭圆的外切矩形。
arc(Surface, color, Rect, start_angle, stop_angle, width=1) -> Rect:该函数用于在Surface上使用color绘制一个弧,其中start_angle参数指定该弧的起始角度,stop_angle指定该弧的结束角度。
lines(Surface, color, closed, pointlist, width=1):该函数在Surface上使用color绘制多条连续的线段,其中pointlist参数指定多个线段的多个断点。
aalines(Surface, color, closed, pointlist, blend=1):该函数与lines()函数基本相似,只是该函数用于绘制多条连续的去锯齿线段。
这些API是不是让你有点懵?不过不用担心,反正这些后面用到时会再次解释的。
大致熟悉pygame提供的以上API之后,下面将会调用上面API来开发游戏界面组件。
另外本人还开设了个人公众号:JiandaoStudio ,会在公众号内定期发布行业信息,以及各类免费代码、书籍、大师课程资源。
扫码关注本人微信公众号,有惊喜奥!公众号每天定时发送精致文章!回复关键词可获得海量各类编程开发学习资料!
例如:想获得Python入门至精通学习资料,请回复关键词Python即可。