admin 管理员组文章数量: 1086019
2024年3月1日发(作者:easyx中inputbox函数怎么用)
基于python的飞机大战游戏设计
摘要: 基于Python软件的面向对象编程思想设计飞机大战游戏, 玩家操作飞机发射子弹, 通过左右移动来躲避子弹; 敌机位于屏幕顶部左右匀速移动, 并且随机向玩家飞机发射子弹。 实践表明, 该游戏操作简单灵活, 具有趣味性。
关键字:Pyrthon; 飞机大战游戏; Pygame
Design of Ai rcraft War Game Based on Python
Absrtact: Based on the object-oriented programming idea of Python software,
the aircraft war game is designed. Players operate the aircraft to fire bullets,
and avoid bullets by moving left and right; the enemy aircraft is located at
the top of the screen, moving left and right at a constant speed, and randomly
fire bullets at the player's aircraft. Practice shows that the game is simple,
flexible and interesting.
Keywords: Pyron; airplane war game; pyGame
目 录
一、飞机大战游戏总体设计……………………………………………………………2
(一)总体设计原则……………………………………………1
(二)系统总体设计…………………………………………………2
(三)准备工作……………………………………………………2
二、飞机大战游戏功能实现………………………………………………3
(一)显示玩家飞机……………………………………………………………3
(二)玩家飞机发射子弹…………………………………………………………………3
(三)敌人飞机………………………………………………3
三、优化程序代码………………………………………………………………………4
(一)抽取子弹基类………………………………………………………4
2
(二)抽取飞机基类…………………………………………………………………4
结语………………………………………………………………………………………20
参考文献 ………………………………………………………………………………22
Python是一种开源的简单易学的高级语言,应用场景涉及到Web应用开发、 操作系统管理、科学计算、 游戏等领域。 飞机大战是一款飞行射击类游戏, 游戏方法是玩家操作飞机与敌机在空中战斗。 本文主要介绍用Python软件实现飞机大战游戏。游戏的整个界面是一张背景图片, 游戏中用到的其他角色同样都对应着相应的图片, 这些图片需要借助Pygame模块搭载窗口以显示¨ J 。 在窗口中, 对象显示的位置通过坐标标注。 其中, 窗口的左上角坐标为( 0, 0) , 石轴向右延伸坐标数值增大, y轴向下延伸坐标数值增大。 所有的游戏元素都参考这个坐标系, 对象在窗口的移动就是坐标位置的变化。
1飞机大战游戏总体设计
1.1总体设计原则
主要设计原则如下: ( 1) 简单性。 在实现软件的功能的同时, 尽量让软件操作简单易懂; ( 2)针对性。 基于Python软件, 实现飞机大战游戏的各种要求; ( 3)
一致性。 类型、 变量和其他元素的命名规则保持一致; 完成同样的功能应该尽量使用同样的元素; 界面元素的外观风格、 摆放位置在同一个界面和不同界面之间是一致的。
1.2系统总体设计
系统中只有玩家一种用户, 不必进行身份验证等操作。 玩家点击应用图标直接进入开始界面。 整个游戏的操作包括: 显示玩家飞机、 控制移动方向; 显示玩家发射子弹( 子弹移动) ; 显示敌人飞机, 控制敌人飞机移动、 敌人飞机发射子弹。
1.3准备工作
1. 3. 1添加pygame模块
pygame是一套用来开发游戏的Python模块,该模块允许在Python程序中创建功能丰富的游戏和多媒体程序。 Pycha珊作为一款开发Python的编辑器, 它不仅
可以帮助开发人员提高开发效率, 而且包含了像pygame这样功能丰富的第三方模块。在PyCharm中添加pygame模块, 在程序中导人pygame模块进行测试, 编译器编译通过, 就证明成功导入了模块。
1. 3. 2搭建游戏界面
飞机大战游戏的整个场景都需要一个窗口作为载体, 展示游戏中的画面。 为了让整个游戏的角色和背景的风格统一, 准备了一张背景图片。在开发中, 导入pyg砌e模块, 就能直接调用模块中的方法。
1. 3. 3检查键盘的输入
当敌人飞机发射子弹的时候, 玩家飞机需要使用键盘适时地调整位置, 以躲避子弹的攻击。在Python程序中, 移动鼠标、 敲击键盘等人机交互的动作属于事件,
它交由pygame的event模块进行控制。 event模块采用列表形式存储的事件,可以通过get函数来获取。 如果要获取键盘和鼠标产生的事件, 就使用for循环遍历事件列表, 取出每个事件与event. type( 事件的类型) 进行对比。 如果event. type的值为Qui t, 说明用户使用鼠标点击了窗口右上角的关闭按钮, 此时就要退出程序; 如果event. type的值为Keydown, 说明用户使用了键盘, 此时就要明确按下的是哪个键。在whi l e循环中, 已经显示了游戏的背景图片。 这时, 在程序中需要检测是否有事件发生, 比如按下键盘等。 如果没有事件发生, 就执行更新操作, 如果有事件发生, 就先处理键盘事件以后再更新。
2飞机大战游戏功能实现
2. 1显示玩家飞机, 控制移动方向在窗口中要显示玩家飞机, 可以根据玩家飞机图片的名称创建图像, 再把这些图像显示到屏幕上设定的位置。 玩家飞机左右移动功能, 可以通过改变坐标戈的值实现, 飞机向左移动减小坐标石的值, 反之则增大戈的值。
新建一个Python Fi l e, 取名为“ pl ane” . 在pl ane. py文件中, 导入pygame模块, 之后定义一个表示玩家飞机的类Her0Pl ane。程序设计中, 定义为di spl ay、 move—l eft和move—ri ght三种方法。 其中, di spl ay用于在默认的位置显示玩家飞机; movel eft用于让飞机向左移动; moveri 曲t用于让飞机向右移动。 在stan函数中创建飞机对象, 并且显示到窗口中。 在whi l e
tme语句中, 根据玩家按下的按键来调用相应的方法, 以控制飞机移动的方向。当按“ 卜” 键或者“ A” 键时, 控制玩家的飞机向左移动, 当按“ _+” 或者“ DI,
键时, 控制玩家的飞机向右移动。
2. 2玩家飞机发射子弹
2. 2. 1
显示子弹当按空格键时, 代表玩家飞机要发射一枚子弹, 此时需要在玩家飞机的头部位置生成一颗子弹对象。 飞机左右移动到任意位置, 只要按空格键, 子弹生成的初始位置永远会位于玩家飞机的头部。
新建一个Python Fi l e, 取名“ buⅡet” 。 在bul -1et. py文件中, 导人模块, 之后定义一个表示子弹的类。 代码如下:
cl ass
Bul l et( obj ect) :
def—i ni t一( sel f, x, y, 8creen) :
seⅡ. x=x+40
sem y=y一20
seⅡ. screen=screen
sem i 砌ge=pygame. i mage. 10ad( “ . / fei j ∥ bul kt一3.
班” ) . convert( )
def. di spl ay( sel f) :
sem screen. bl i t( sel f. i amge, ( sem x, sel f. y) )
按空格键发射子弹, 代码如下:
hemPl aIl e. 1auncn- buUet( )
运行程序, 按下空格键以后, 玩家飞机的头部显示了待发射的子弹。 此时, 无论飞机移动到哪个位置, 生成的新的子弹永远会位于其顶部。
2. 2. 2子弹移动
每执行一次whi l e循环, 就会调用一次di s—pl ay方法, 让子弹再次显示到屏幕上。 由于屏幕刷新的速度特别快, 肉眼是无法捕捉到的。 利用程序的这个特点, 每刷新一次屏幕, 就让子弹显示的位置上移几个单位, 从而形成向上发射子弹的动画效果。如果无限制地往列表中添加子弹对象, 终究会耗尽设备的内存, 所以, 一旦子弹离开屏幕可视范围时, 就把子弹对象从列表中删除。在Bul l et类
中添加一个j udge方法, 用于反馈子弹是否发射到屏幕以外的情况, 若子弹图像的y值小于0, 则表示子弹移出了屏幕, 返回Tme; 反之则返回Fal se。
在HeroPl ane类的di spl ay方法中, 定义一个存放待删除子弹对象的列表。 从列表中取出每个带删除的子弹对象进行判断, 如果子弹对象已经发射到屏幕的外面,
就添加到刚定义的列表中,然后清空列表中所有被删除的子弹对象。 具体代码如下:
def
di spl ay( sel f) :
sel f. screen. bl i t( semi mage, ( sem x, sel f. y) )
neen—del 一1i st=[ ]
for i tem i n
se璩bul l 吼一l i st:
i “ tem. j udge( ) :
need—del —l i st. append( i tem)
fj f del —i tem i n
need—del 一l i st:
sel f. buU吼一l i st. remove( del —i tem)
for buⅡet i n sem buⅡel —l i st:
bul l et. di spl ay( )
bul l et. move( )
2. 3敌人飞机
2. 3. 1
显示敌人飞机跟玩家飞机类似, 在pl ane. py文件中定义一个表示敌人飞机的EnemyPl ane类。 敌人飞机应该有默认的位置、 呈现图像的窗口、 存放子弹的列表这些属性。 然后来到mai n函数的whi l e循环语句中, 在创建Her0Pl ane类对象的后面, 创建表示敌人飞机的对象。 在显示玩家飞机的代码后面,调用di spl
ay方法来显示敌人飞机。
2. 3. 2控制敌人飞机移动
当程序启动以后, 敌人的飞机开始在窗口的顶部做直线运动, 直到碰到屏幕的边缘后向反方向做直线运行。 可以为敌人飞机类添加一个移动的方法, 由于敌人的飞机是不停地运动的, 所以放到whi l e语句中最为合适口J 。飞机碰到左侧的屏幕边缘时, 移动方向变化为向右移动, 飞机碰到右侧的屏幕边缘时, 移动方向变为向左移动。 因此, 在EnemyPl ane类的一i m一( ) 方法中增加一个di recti on属性, 用于记录飞机的初始运动方向:seⅡ. di recti on=“ d曲t”然后定义一个move方法, 根据飞机移动的方向改变石对应的坐标值, 再根据菇的值限定敌人飞机移动的范围, 只要超过屏幕的宽度范围, 就改变飞机运动的方向。在mai n. py文件的whi l e语句中, 调用di spl ay( ) 方法显示敌人飞机, 调用move方法实现敌人飞机一直左右移动的效果。运行程序, 敌人飞机在屏幕顶部移动的速度非常快。 产生这种情况, 主要因为屏幕刷新的速度太快, 导致敌人飞机移动的速率过快, 并且占用了程序过多的内存, 因此, 需要使用ti me模块来降低程序执行的效率。
2. 3. 3敌人飞机发射子弹
敌人飞机发射子弹的功能与玩家飞机发射子弹的功能基本一样, 不同的是子弹反射的方向及发射的个数。 为此, 在bul l et. py文件中, 新建一个表示敌人飞机发射的子弹的EnemyBul l et类, 直接复制Bul l et类的代码到EnemyBul l et类中, 然后再对发射子弹的功能代码进行局部调整。 在mai n. py文件的循环语句中, 调用move方法的后, 调用敌人发射子弹的方法为:Enemy—pl ane. 1auncn-
buuet( )运行程序, 由于敌人飞机发射子弹的速度太快了, 使得子弹形成了一条斜线。 所以, 在Enen.myPl ane类的l auncn—bul l et( 发射子弹) 方法中,设置发射子弹的数量是随机的, 这样可以降低子
弹发射的频率, 代码如下:
def l auncn_buUet( 8el f) :
nuInber=random. randi nt( 1, 100)
i f肌Ⅱl ber==88:
new—bul l et=Ene皿甲Bul l et( sel f. x, sel f. y, sel f.
scI eenl
sel f. bul l et一1i st. 印pend( new- bul l et)
上述方法实现了敌人飞机发射子弹的功能,首先使用函数获取了从1到100的随机整数, 然
后使用i f语句判断随机数的值是否与88相等, 只有这两个值相等, 才会创建要发射的子弹对象, 通过这种随机数的方式, 使得敌人发射子弹的数量变为原来的百分之一。 由于使用了random模块的函数, 所以导入random模块‘ 3|, 代码为:I mport random
3优化程序代码
在前面的程序代码中, 表示敌人飞机的类( EnemyPl ane) 和表示玩家飞机的类( HeroPl ane)
中有很多功能相似的代码, 除此之外, 表示子弹的两个类中有着很多重复的代码,
这些重复的代码不仅使程序显得过于臃肿, 而且没有清晰的结构。可以利用继承的技巧H] , 对所有类的代码进行优化, 以明确程序的结构。
3. 1抽取子弹基类
玩家飞机发射的子弹和敌人飞机发射的子弹这两大类的功能几乎相同, 出现了
很多重复的代
码, 使得整个程序的结构过于臃肿。 可以定义这两个类的公共类Publ i cBul l et¨
J , 在这个类中既能抽取出它们共同拥有的功能, 又能区分它们的不同情况。定义一个表示子弹的公共类Publ i cBul l et, 把示玩家飞机子弹类的代码复制到Publ
i cBul l et类中, 再根据两个子弹类不同的地方进行调整。由于Publ i cBul l et类已经合并了EnemyBul l et类和Bul l et类的功能, 并对它们各自不用的地方进行了处理, 所以创建EnemyBul l et类和Bul l et类对象时, 可以替换为创建Publ
i cBul l et类对象:
New—buⅡet=Publ i cBuUet( sel f. x, sel f. y, sel f. screen,
“ enemy” )
同样在Her0P1ane类的l auncn—bul l et方法中, 把创建Bul l et类对象的代码改为创建Pub—
l i cBul l et类的对象:
New- buⅡet=Publ i cBul l et( sel f. x, sem y, seⅡ. screen,
“ hero” )
运行程序, 界面依然显示了跟以前一样的效果, 这证明代码抽取成功。
EnemyBul l et类和Bul —l et类现在对程序没有起任何作用, 可以直接删除。
3. 2抽取飞机基类
进一步抽取EnemyPl ane和HeroPl ane两个类中功能相似的代码。 由于这两个类中实现的功能较多, 如果依然使用抽取公共类的技巧, 就需要频繁地使用i f—el se语句来区分不同飞机的情况。因此, 需要把EnemyPl ane和Her0Pl ane类中相同的功能放到基类中, 再让这两个类继承基类后单独调整。通过比较EnemyPl ane和HeroPl ane类中的代码, 发现EnemyPl ane类中的一i m一、 di spl ay和she—Bul l et方法与HeroPl ane类中的一i m一、 di spl ay和sheBul l et方法功能非常相似。 为此, 需要把这三个方法的代码提取到基类中, 子类EnemyPl ane和HeroPl ane继承基类以后, 会拥有这三个方法, 可以根据自己的要求重写这些方法。
3. 2~一i ni t一( ) 方法
通过比较两个飞机类的代码发现, Enemy—P1ane类的一i n“ 一( ) 方法比HeroPl ane类的一i n“ 一( ) 方法中多一个属性, 所以需要把HeroPl ane类的
一i n“ 一( ) 方法粘贴到新创建的基类Pl ane中, 具体如下:
Cl ass
Pl aIl e( obj ect) :
def—i ni t一( sel f, screen) :
sel f. x=230
sem y=600
sel f. scI een=scI een
sel f. i mage—n棚e=” . / fei j ∥ hem. gi f, ’
sel f. i mage=pygame. i mage. 10ad( seH i mage—
name) . convert( )
seM bul l 吼一1i st=[ ]
让HeroPl ane类继承Pl ane类, 这样HeroPl ane类就拥有了从父类Pl ane继承来的一i m一( ) 方法。此时, 可以删除类HeroPl ane中一i m一( ) 方法。
同样让EnemyPl ane类继承自Pl ane类, Pl ane类就拥有了从父类继承而来的一i
m一( ) 方法。 不过, Ene—myPl ane类需要增加一个表示方向的属性, 为此需要重写父类的一i nt一( ) 方法, 具体如下:
def—i ni t一( sel f, screen) :
super( ) . 一i nI一( screen)
seIf. di recti on=” ri ght”
3. 2. 2
di spl ay方法
通过比较EnemyPl ane类和HeroPl ane类的di spl ay方法发现, 它们的功能是一样的。 因此,可以在Pl ane类中沿用EnemyPl ane类的di spl ay方法代码。由于EnemyPl ane类和HemPl ane类都已经继承了Pl ane类, 所以就拥有了di spl ay方法, 而且它们的功能没有任何变化, 直接删除它们每个类中的di spl ay方法就行了∞1。
3. 2. 3
l aunch- bul l et方法为了能区分是哪架飞机要发射子弹, 在创建飞机对象构造方法的参数列表中, 增加一个表示飞机名称的字符串。 虽然这样能区分飞机的名称, 但是方法参数中直接使用字符串扩展性不是很好。 因此, 在Pl ane类的一i
n“ 一方法中, 添加表示飞机名称的name属性, 使得EnemyPl ane类和HemPl ane类创建对象时就有了名字。在EnemyPl ane类重写的方法中, 增加name参数。 在类的方法中, 把创建Publ i cBul l et类对象的参数列表中的最后一个参数改为sel f. name。改完以后, 把整个l auncn- bul l et方法剪切到P1ane类中。 代码如下:
def
1auncⅡ- bul l et( sel f) :
new—bul l et=Publ i cBul l et( sel f. x, sel f. y, sel f. 8creen,
sel f. name、
sel f. bul l e【一l i st. 印pend( new- bul l et)
EnemyPl ane类中的l auncn—bul l et方法, 与从父类直接继承的l auncn—bul l et方法在功能上存在着一些差异。 为此, EnemyPl ane类需要重写从父类继承的l auncn—bul l et方法。 在Pl ane类的一i m一( ) 方法中, 由于图片素材的名称、 戈值和y值是变化的, 每个子类需要单独进行调整, 所以在Pl ane类中, 把这三个属性移动到子类HeroPl ane重写的一i m一( ) 方法中。 在EnemyPl
ane类的一i m一( ) 方法中, 同样增加这三个属性的设置。
这表示抽取成功。 此时, 程序中几个类的结构,
4结论
本文围绕面向对象的编程思想, 开发了飞机大战游戏的部分功能, 包括搭建游戏界面, 创建玩家飞机和敌人飞机类, 飞机发射子弹等, 并且利用继承的技巧优化了代码。 模块以对象划分, 有界面模块、 Hero模块、 子弹模块、 Enemy模块、
游戏控制模块; 难点在于多架战机同时出动情况下, 判断发生碰撞的算法设计。 整个软件按照预期目标大致实现了飞机大战游戏的功能。 整个游戏还存在一些不足。
比如, 怎么动态及时地显示积分数,怎么能够让各种敌机在不同的时间点以不同速度飞行且不发生碰撞; 还有如何在多人联网下共同作战, 及时分享自己的战绩等,
都需要进一步研究。
参考文献:
[ 1] 吴玑震. 飞机大战游戏软件中的数据结构和策略分
析[ J ] . 信息与电脑, 2016( 7) : 145一154.
[ 2] 杨大生. 基于symbi an平台飞机大战游戏设计[ J ] .
福建电脑, 2010( 7) : 140—167.
[ 3] 李智鹏. 基于Uni ty3D引擎的空中战机游戏设计与
实现[ D] . 长春: 吉林大学, 2016.
[ 4] 黑马程序员. Python快速编程入门[ M] . 北京: 人民
邮电出版社, 2018.
[ 5] 雷丽娟, 郑永彬. 使用J ava制作贪吃蛇游戏[ J ] . 科
技视界, 2013( 4) : 139—140.
[ 6] 仇宾. 基于J ava的“ 连连看” 游戏[ J ] . 电脑编程技
巧与维护, 2013( 11) : 72—77.
版权声明:本文标题:基于python的飞机大战游戏设计 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/p/1709285302a542028.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论