先添上最终完成效果图
Github代码仓库链接
https://github.com/happyte/plane, 这个是飞机大战的代码仓库,不足之处希望大家指出。
基础类的构建
导弹类
- 1.导弹是从飞机上发射的(无论是玩家的飞机还是敌机),导弹的位置需要根据飞机的位置确定,还需要根据是玩家飞机还是敌机确定导弹的图片名和发射方向,因此需要传入图片名和位置参数。
pygame
框架加载图片为图像函数为:
pygame.image.load(image).convert()
传入的参数是图片的相对路径
- 2.描绘出导弹的位置,导弹并且需要在初始化的
self.x
和self.y
基础上移动位置,位置是在屏幕上描绘的,需要传入屏幕参数。
pygame
显示图片函数为:screen.blit(self.image,(self.x,self.y)) pygame.display.update()
第一个参数为加载的图像,第二个参数为左上角坐标。两个函数是配合使用的,需要第二个函数去刷新界面。
## 飞机类
- 1.`Plane`类是接下来要创建的玩家类`Hero`和敌机类`Enemy`的基类。基类把两者共同的属性和方法定义出来,方便子类继承。飞机要发射导弹,有一定的发射间隔,因此定义一个对象属性`self.bulletSleepTime`。还需要一个列表存储导弹,定义一个对象属性为空列表`self.bulletList`。
![](http://upload-images.jianshu.io/upload_images/4300291-7b20c8aebfb3415c?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
`time.time()`可以用来确定当前时间,按照一定的格式可以转换
- 2.在初始化的时候我们定义了导弹的发射间隔时间,大于间隔时间的话我们就往定义的列表中添加导弹对象,因为我现在只想让玩家飞机发射子弹,因此初始化导弹对象特意往`self.x`加了`36(是玩家飞机72x72图片宽度的一半)`,让导弹在玩家飞机的正中间开始显示。
![](http://upload-images.jianshu.io/upload_images/4300291-6bd1343aff885c70?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- 3.描绘出飞机的位置
![](http://upload-images.jianshu.io/upload_images/4300291-45446eedba25a1ab?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
# 继承类的构建
##玩家飞机类
- 1.在飞机基类中我们定义了一些共同的对象属性,不同的对象属性有图像和原始位置,而且玩家飞机类对象还想拥有基类对象的属性,所以需要调用`Plane.__init__(self)`函数,通过这个函数就拥有了`Plane`基类的对象属性`bulletSleepTime`、`lastShootTime`、`bulletList`。
![](http://upload-images.jianshu.io/upload_images/4300291-f394984937086b2c?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- 2.玩家飞机通过键盘的上下左右控制飞机的位置
![](http://upload-images.jianshu.io/upload_images/4300291-dc488d254669804a?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
##敌人飞机类
- 1.敌人飞机类中还多了速度对象属性,考虑到随着游戏难度的增加,敌人飞机速度越来越快,这个参数需要外界传入。而且敌人飞机有小中大三种类型,是随机的,起始的位置`x`轴也是随机的,`y`轴固定从最上方开始。
![](http://upload-images.jianshu.io/upload_images/4300291-a4d66500742b5332?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
用到了随机数函数,需要导入`random`模块
```objc
random.randint(1,3)
其中用到了super(Enemy,self).__init__()
与玩家类中的Plane.__init__(self)
效果是相同的。direction
对象属性可以忽略,现在没有用到。
- 2.敌人的飞机不断往下掉,改变
self.y
,其实不用判断,direction
没有用到
游戏初始化类(封装功能)
- 1.
GameInit
类创建了几个类属性,g_enemyList=[]
列表用于存储敌人飞机对象,初始化玩家对象hero=object
,object
是元类,和用于统计玩家分数的属性score
。
- 2.接下来定义了几个类方法和静态方法,用于封装功能,在主函数里调用的都是这些类方法和静态方法
-
往敌机列表中添加敌机对象,忽略下我的代码英语好像打错了
-
创建玩家飞机对象
-
游戏初始化
-
玩家飞机对象处理键盘操作,在玩家飞机类中已经定义了键盘处理函数,这里再封装一层
-
更新敌人飞机位置,敌人飞机对象都在
g_enemyList
列表中
-
有3种类型的对象需要描绘,玩家飞机对象,敌人飞机对象和导弹,这个函数就是用来描绘这些对象,其中导弹和敌机需要判断哪些对象超出屏幕从列表中删除,这里用了
del
函数,记录下索引值并从列表中删除,同样也可以用pop
函数,这里的j
为索引值
-
玩家飞机对象发射子弹,同时也要判断打中了敌机就让敌机对象和和子弹对象同时从列表中删除。通过
pygame.Rect(self.image.get_rect())
获得矩形的值,但是只获得了图像的width
和height
两个属性,前两个属性left
和top
都为0,因此还需要设置这两个属性,然后通过collidetect
判断两个矩形是否有相交处,其中索引值enemyIndex
和bulletIndex
需要仔细分析下
-
判断玩家飞机是否与敌机相撞判断游戏是否结束
- 3.几个静态方法,静态方法不需要
cls
这个参数,通过类和实例都可以调用
-
退出整个程序
-
进入游戏后可以按
space
键停止游戏,其实就是就是个死循坏,按键按下后跳出函数
-
游戏开始后和结束后把分数显示出来,第一个参数是分数,第二个参数是通过
pygame
的字体库创建出来的,例如font = pygame.font.SysFont(None,64)
,参数分别为字体样式和大小,可以选择字体样式例如arial
、simsun(宋体)
,第三个参数是屏幕,第四和第五个参数是字体显示的left
和top
值。
主函数
- 1.运行一个模块,有
if __name__ == 'main':
标识,会直接运行里面的代码。第一步初始化pygame
库,调用pygame.init()
,第二步创建一个窗口与背景图片一样大:screen = pygame.display.set_mode((ScreenWidth,ScreenHeight),0,32)
,然后可以设置窗口标题:pygame.display.set_caption('飞机大战')
,第三步做一些初始化常量设置。其中纪录了游戏开始的时间,因为按照我的思想游戏开始后难度会逐渐增加,我是通过时间来增加难度的
启动时显示start图片,直到Enter
键按下才进入游戏 - 2.进入
while
循坏后,调用游戏初始化类封装好的函数,通过时间间隔interval
选定游戏困难模式,通过改变敌机刷新的时间和敌机的速度增加难度,游戏结束后,再次按下Enter
按键退出程序。这里存在一个bug
,一旦游戏进行过程中按下Space
暂停游戏,interval
时间间隔仍然再计算(按道理应该让时间暂停),再次按下Space
恢复游戏后,当前模式设定时间减少了或者进入更困难模式了。
总结
- 1.我用的版本是
python3.5
,不知道为什么无法导入音乐,提示我打不开音乐文件,目前还没试过其它版本,猜测是否是因为版本的原因 - 2.接下来修复
bug
,目前完成了基本功能,下一步加入敌机爆炸效果和大型敌机是需要好几发子弹才能击毁 - 3.在运行程序前安装
pygame
库,我是在windows电脑上写的,可以用pip list
查看安装了哪些三方库