手把手教你使用Python开发飞机大战小游戏,4万字超详细讲解!

时间:2022-07-22
本文章向大家介绍手把手教你使用Python开发飞机大战小游戏,4万字超详细讲解!,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
使用Python开发飞机大战游戏,本文目录如下

这次用Python中的pygame模块来完成一个飞机大战的小游戏;基本思路是通过方向键来控制飞机的左右移动射击飞船。先来看下最后的效果

为了新手也能完成,本文记录了编写的全部流程,也就是每次修改的代码也包括在内,并且给大多数代码都加上了能看懂的注释,看一下最终的的统计字数

一共敲了4万个字符,希望能帮到感兴趣的读者!

制作小飞机

搞起来

目标:创建一个可以左右移动的小飞机,用户可以通过空格space键来控制飞机发射子弹。

创建背景

创建一个空背景

首先编写一个空的pygame窗口,文件名为plane_war.py

display.set_mode返回的是一个Surface数据类型

效果图

创建设置类

一个游戏通常有n多个设置,如果每次想改变其中的某一个值的话在主文件中寻找容易眼花缭乱,现在创建一个新的文件settings.py,专门用来存储这些信息

添加小飞机

这里用到的小飞机

绘制小飞机

现在图像也有了,来创建一个plane.py模块,其中有一个Plane类,来存储飞机的各种行为

get_rect会返回Surface的矩形的区域,.centerx.bottom是其两个属性

改写plane_war.py将小飞机绘制在屏幕上

效果图

创建一个存储运行函数的模块

为了不使plane_war.py太长而影响阅读,来创建一个名为game_func.py的模块,用其飞机大战运行的函数,使其逻辑更容易理解

check_events函数用来完成窗口不会关闭的功能,update_screen用来完成更新图像的功能,有3个形参,Surface对象、背景图像、小飞机函数

因为check_events完成了退出游戏的操作,所以plane_war.py就不需要sys模块了,更新后的plane_war.py如下

控制小飞机

通过修改小飞机的坐标来完成移动,在用户按下方向键的时候小飞机的坐标进行有规律的变化

控制小飞机移动

当用户按键时,都会在pygame中注册一个事件,任何一个事件都是通过pygame.event.get()获取的,因此可以在函数体内,为每个按键都注册一个KEYDOWN事件。

现在将check_events函数改写,通过检测按下键位,来对小飞机进行移动

现在按一下小飞机移动一个像素,一般的游戏都是通过按下不送则一直移动,Pygame中的pygame.KEYUP可以检测用户是否松开按键现在结合KEYDOWNKEYUP来完成一个持续移动

控制小飞机持续移动

来定义一个标志位,来判断用户是否按下按键,默认为Flase一旦检测到用户按下俺家则为True,小飞机就可以持续移动

由于小飞机是通过plane.py文件来控制的,对这个文件进行改写

update方法是标志位为True时,小飞机就开始移动

改写game_func.py中的check_events函数

最后只要在plane_war.py中调用update方法就可以完成持续移动的操作

完成左右移动

用同样的方法完成向左移动

改写后的plane.py文件

改写后的game_func.py中的check_events函数

调整速度

现在的小飞机一次是按1px来移动的,那速度是相当的缓慢,修改一下小飞机的移动速度

首先在setting.py中添加一行

现在对plane.py做修改

plane_war.py中的plane增加一个属性

限制小飞机的活动范围

现在小飞机已经可以飞呀飞,但是没有东西限制他,很容易就飞出了屏幕。现在将其限制在屏幕中,避免飞出去。

只需要修改plane.py中的update方法

重构game_func.py中的check_events函数

随着小飞机的功能愈来愈多,现在将check_events重构为3个函数,捕捉用户按键和用户松开键分别定义两个函数

重构后的check_events

效果图

完成射击功能

通过玩家按下空格来发射子弹(一小小小的矩形)

添加子弹的设置

settings.py中的__init__方法中添加以下数据

创建Bullet类

创建存储子弹的Bullet类的bullet.py文件

Bullet类继承于pygame.sprite中的Sprite类,此类可以将游戏中的元素进行编组,可以同时操作编组中的所有元素

将子弹存储到编组中

首先在plane_war.py中创建一个编组,用于存储所有有效的子弹,以便能够管理发射出去的子弹;这个编组是pygame.sprite.Group类的一个实例;pygame.sprite.Group类类似于列表,但是提供了有助于开发游戏的额外功能。在主循环中,我们将使用这个编组在屏幕上绘制子弹,以及更新没颗子弹的位置。

开火

通过修改game_func.py中的函数来完成发射子弹的操作

用户按下空格之后会创建一个子弹(一个名为new_bullet的Bullet实例),并使用add追加到编组中方法bullets.sprites返回一个列表,包含了编组中的所有精灵,遍历编组中的精灵,并通过draw_bullet()绘制到屏幕上

效果图

现在已经完成基本的射击功能了,虽然子弹到达屏幕顶端后消失了,这仅仅是因为pygame无法绘制屏幕外面的东西,这些子弹实际还是存在的,他们的y坐标为负数且越来越少,会继续消耗内存

删除已经消失的子弹

这里通过.copy进行浅拷贝,然后检测子弹是否消失,然后再将其删除

plane_war.py中的while语句中添加下面这一句

注意:在fg.update_screen之前进行添加

限制子弹的数量

为了不使这个小游戏跟开挂似得,肯定要限制一下发射子弹的数量,在settings.py中添加一行

check_keydown_events函数体中增加一个判断即可

简化plane_war.py中的while语句

将发射子弹移步到game_func.py文件中并创建一个update_bullets

此时的while语句中就4行代码

小飞机添加完毕的效果

制作飞船

现在小飞机也创建完成了,现在就该创建小飞机的敌人了,同样通过一个类来控制其所有行为,先来看看这个卡哇伊的飞船

目标:创建好非常让其随意移动,可以射杀飞船、当飞船碰到小飞机GAMEOVER,飞船碰到地面也GAMEOVER

创建飞船

创建Spaceship

创建一个名为spaceship.py的文件来存储Spaceship

这里除了位置基本与Plane类相同

实例化Spaceship

plane_war.py中添加Spaceship实例

这里导入了一下新创建的Spaceship类,在while循环外创建一个实例,给update_screen传递一个飞船的实例

让飞船出现在屏幕上

修改update_screen函数

注意其顺序

现在这个好看的小飞船已经出现在了屏幕的左上角

创建一群小飞船

要绘制一群小飞船,需要确定一行能容纳多少个飞船以及要绘制多少行飞船。

确定一行可以容纳多少个飞船

确定一行可以容纳多少个外星人,需要看一下可以用的水平空间有多大。我们的游戏的屏幕宽度在settings.py中的screen.width存储,但需要在屏幕两遍都留下一定的边距,把它设置为小飞船的宽度。由于有两个边距,可以放置飞船的的水平空间为屏幕的宽度减去飞船宽度的2倍

公式为

根据这些公式来创建飞船

创建一行飞船

为了创建一行飞船,首先在plane_war.py中创建一个spaceships的空编组用来存储全部的飞船,在调用game_func.py中创建飞船群的函数

改造game.func.py文件并编写创建飞船群函数create_fleet

效果图

因为一个飞船的宽度是占两个的位置,所以最后的空隙有点大,后期反正这个飞船是动起来的,这里先暂时忽略

create_fleet改写一下,拆分为三个函数体

添加多行小飞船

添加多行就跟一行添加多个是类似的,同样用屏幕的高度减去飞船高度的2倍,这里需要注意的是为了不让小飞机死的很快下面留两倍的高度,还要减去小飞机的高度

game.func.py中进行改写

这个写的话游戏刚开始我们的飞机就死掉了,现在来做一下修改

首先修改`spaceship.py

由于其高度进行了改变,原来的公式也要进行相应的改变

available_space_y = setting.screen_heitght - 7 * spaceship_height - plane_height # 由之前的3变为7(因为高缩小了一般)

效果图

让飞船动起来

首先在settings.py中增加小飞船相应的设置

spaceship.py中增加判断是否位于边缘的方法和移动的方法

game_func.py中对spaceship.py方法实例化

最后在主文件的while语句中增加

射击飞船

现在子弹和飞船碰撞在一起飞船并不会消失,而是从飞船上穿了过去,并没有达到射击飞船的效果,现在我们将完成这种效果

在这里我们使用game.sprite.groupcollide()方法,此方法检测两个rect是否有元素重叠,并返回一个字典

检测子弹与飞船碰撞

子弹击中飞船后飞船需要马上消失,所以需要在更新子弹的位置后面检测碰撞

方法game.sprite.groupcollide()将每个子弹的rect和每个飞船的rect进行比较,返回一个字典,其中包含了发证碰撞的子弹和飞船。这个字典中每个键都是射中飞船的一颗子弹,相应的值为被击中的飞船

在函数update_bullets()中来检测碰撞

修改plane_war.py中的fg.update_bullets为其增加一个参数

生成新的飞船

当把所有的飞船非射击完毕以后,其不会生成新的飞船

这里需要在update_bullets()之后来判断其长度是否为0,如果为0则调用create_fleet

测试效果

我这里为了测试我将子弹的宽度给修改了自己写的游戏想怎么改就怎么改,游戏意思,哈哈~

总结

游戏结束

当然了,这么玩就失去了游戏的乐趣了,肯定是不可以啊。

现在就增加难度,当飞船碰到飞机、飞船到达地面时就要搞点事情了,不过也不能不给小飞机机会