本项目为飞机大战,在主页面中一共有四个按钮,分别对应无尽模式
,boss模式
,历史记录
和退出游戏
四个功能。
技术栈: python3.11
mysql 8.0.36-0ubuntu0.22.04.1
玩家可选择无尽模式或者boss模式进行游戏。
无尽模式会记录玩家分数,记录游戏数据并存到数据库中。
boss模式下,玩家需要击败boss的两种形态才能通关。
历史记录中,玩家可以查看最近的无尽模式游戏记录。
- 该模式的界面上会随机出现迷你敌机、小敌机、中敌机、大敌机四种敌机,并进行随机移动和不同子弹的发射,玩家需要对敌机及其发射的子弹进行躲避,并发射子弹击落敌机,获得相应的得分。敌机越大,其生命值和子弹威力就越强,相应地,玩家击落获得的分数也会更高。
- 游戏过程中,补给会有较小概率掉落,玩家拾取到补给后,攻击力会加强,发射两条弹道,一段时间后,超过补给有效期,发射的子弹会恢复成一条弹道。
- 玩家具有一定的生命值,当被子弹击中或者与敌机造成碰撞,都会造成生命值的减少,当生命值减少到为0时,玩家飞机被摧毁,游戏结束,弹出文字提示,并在3秒后自动退出该游戏模式,并记录游戏的分数,保存本次游戏信息到mysql数据库中。
- Boss会有两种形态,在第一形态中,Boss1会发射两种子弹,玩家需要对Boss1进行子弹发射,使其血量减少(界面上的白色血条为其血量的可视化)。当血量为0,即白色血条消失时,屏幕会出现几秒的warning!警告,预示更强的Boss2形态即将到来,提醒玩家做好准备。
- Boss2的血量更高,子弹威力更强其子弹有3种,前两种和Boss1形态的子弹差别不大,就是飞行速度更快,威力更强一些,第三种子弹是Boss2更强的手段——跟踪核弹,会在发射前根据玩家的位置进行定位跟踪,最后再发射出去,其威力明显大于其他类别的子弹。
- 不过,玩家在该boss模式下获得补给后,会获得不断的子弹强化,与无尽模式的强化效果不同,玩家一旦获得补给,其强化效果不但不会消失,还会随着更多补给的获得而增强自身弹道和子弹威力,从而帮助玩家更好地战胜更强形态的boss。当玩家将boss1和boss2都击败后,游戏胜利,显示提示文字的同时会在3秒后自动退出该游戏模式,返回到主界面。
历史记录模块利用到mysql数据库的存储。
先打开wsl子系统的mysql数据库,通过连接其中的pygame_db数据库来对里面的表score_table进行数据访问,查询最近5条数据并返回,显示在页面上。
按下退出游戏按钮,清空pygame资源并执行exit() 函数退出游戏。
- 由于游戏中创建了大量的类和对象,比如飞机类,子弹类等以及相应类的多个对象,因此创建一个myclass.py文件,在其中定义好可复用的类。并在两种游戏模式中进行相关类的使用,并根据适当需求进行类的继承和方法重写。
- 定义玩家飞机Player类和飞机子弹Bullet类,包含飞机坐标,矩形对象,飞机按下键盘实现上下左右移动和发射子弹的功能,在发射子弹时,会将子弹加载到一个精灵组里面,在动态update更新时会将子弹显示到界面上。在子弹类中,除了定义矩形对象,坐标与飞机位置相关联之外,还要设置自动移动的方法,确保在更新页面时能够呈现出子弹向上移动的效果。
- 定义敌机Enemy类和敌机子弹EnemyBullet类,同样包含敌机坐标,矩形对象,子弹移动等属性和方法。与玩家飞机和子弹不同,敌机的移动是随机移动,子弹是随机自动发射,而不受玩家的键盘行为控制。此外,玩家飞机只有一种,不用重写,而敌机和子弹跟据不同模式会有不同类型,需要在对应的模块重写定义子类来继承此处的敌机Enemy类和敌机子弹EnemyBullet类。
- 以上这四个类都需要继承pygame.sprite.Sprite这个精灵类,这个是pygame提供的类,提供了rect矩形属性,可以感知时间的流逝等功能。继承它将便于我们后续进行获取游戏元素对象的矩形位置,定时器的使用,飞机碰撞判定等操作。
- 定义背景类,包含三张图片,需要子类重写,传递其所需的图片文件名。为了实现背景不断下降,来达到飞机相对往前飞行的效果,背景图片的首尾需要能无缝衔接。因此在方法中,我设置两张背景上下相邻排列,在界面更新时固定向下移动2个单位,通过背景的向下移动呈现出玩家飞机向前飞行的效果。当第二张图片的顶部即将离开界面的顶部时,更新图片位置为最开始的位置,从而实现图片的无缝衔接并继续向下移动,循环往复,实现背景永远不断向下移动的效果。
- 定义爆炸类,当敌机或玩家的飞机被摧毁时会触发爆炸效果,在此类中,定义了爆炸的音效,同时用列表推导式加载了爆炸飞机的四张爆炸图片,更新界面时会逐步展示这4张照片,从而呈现爆炸的动画效果。爆炸的4张图片需要先根据碰撞获取到被摧毁的飞机对象,根据飞机类型来传递不同文件名到爆炸对象中,呈现不同爆炸效果。(飞机爆炸图片的命名方式为“飞机类名+down+图片数字”,从而方便参数的传递)。
- 定义补给类,生成随机数,设置一个较小的概率来生成补给,比如随机数的范围是1-20,每秒补给定时器触发时产生一个随机数。只有当定时器触发且随机数为1时,才会创建补给对象,放入补给的精灵组里,进而能在页面中呈现出来。补给的移动方式和敌机子弹类似,都是从上方生成并不断下落,只有当补给与玩家敌机发生碰撞或移出屏幕时才会销毁该对象。
- 对敌机类进行继承,创建出迷你敌机、小敌机、中敌机、大敌机四种敌机子类,同时其对应的四种子弹也是继承于myclass的子弹类,重写了子弹图片,移动速度等属性。
- 定义音乐类,加载游戏背景音乐和爆炸音效,继承背景类,设置该模式下的游戏动态背景。
- 在Manager管理类中,定义多个绘制文字和矩形的方法,用于在游戏界面上动态展示分数、血量条、文字提示等元素。文字利用drawText( )函数生成对应样式,包括字体,颜色,显示位置大小等属性的设置,外部通过调用传参可快速实现在界面上绘制文字的操作。血量条本质上是一个带颜色的矩形绘制,其中矩形的宽度跟玩家或boss敌机的血量呈线性关系:满血时血量条最长,之后逐渐缩短,血量降为0时血条消失。
- 将main方法定义在Manager管理类中,当用户在主页面点击无尽模式的按钮时调用Manager.main()方法来执行程序,进入while循环,并在游戏结束时break退出循环,结束main()方法从而退出该游戏模式,体现面向对象思想。
- 在主函数main()中,会先播放音乐,创建玩家飞机对象以及敌机和补给的定时器。之后是一个while循环,在循环每秒中都会执行一次定时器操作,创建一个敌机放入精灵组,同时有较小概率创建补给。背景会不断移动,页面上的文字,如分数等会在循环中不断调用函数来绘制,当相关变量发生改变后即可实时在游戏界面中进行动态更新。随后重点是不同元素:如玩家与敌机,子弹与敌机之间的碰撞判断。每次循环都会进行多次元素的判断,如果判断碰撞为true,那么将获取到碰撞的两个对象执行相关逻辑,比如玩家扣血,敌机对象删除,定时器的开启等。这些逻辑有用相关的函数进行封装,想要在正确的时刻调用合适的函数,需要加上标记,比如定时器的开关标记,变量的相关记录等,当循环中的event.type捕获到当前的事件发生改变时会根据事件情况来调用相关函数。若涉及到定时器操作,在这些函数里可能还需要对定时器进行关闭操作。
- 当玩家生命值减到0后,会开启失败的定时器,显示游戏结束,播放飞机被摧毁的爆炸音效并倒计时3秒,之后自动退出游戏。退出游戏前,还会将游戏的分数和当前时间进行记录,并存入数据库的score分数表中。
- Boss1和Boss2都继承于myclass的敌机类,重写了敌机的移动方式、开火子弹类型等,同时Boss1和Boss2一共5种子弹都继承于myclass的子弹类,对其相应图片,子弹发射速度等属性进行了重新规定。
- 定义音乐类,加载游戏背景音乐和爆炸音效,继承背景类,设置该模式下的游戏动态背景。
- 在Manager管理类中,定义多个绘制文字和矩形的方法,用于在游戏界面上动态展示分数、血量条、文字提示等元素。
- 同理,将main方法定义在Manager管理类中,当用户在主页面点击Boss模式的按钮时调用Manager.main()方法进行游戏,并在游戏结束时break退出循环,结束main()方法从而退出该游戏模式。
- 与无尽模式同理,在main()方法中,同样有播放背景音乐,创建玩家飞机对象,while循环和碰撞判断等操作。此外,在该模式中,还设计Boss形态切换的过渡页面设计。当Boss1被摧毁时,不是直接结束游戏,而是另外开启一个过渡定时器,设置为5秒,动态显示warning的警告信息。之后创建Boss2对象缓慢移动进入页面,进行Boss2阶段的游戏逻辑。在此阶段中,还有激光预警和跟踪核弹的游戏逻辑。Boss2有较高几率进行跟踪核弹的发射,其速度快,威力大。为了提高游戏合理性和交互效果,我增加了一个激光预警,即跟踪导弹不立即创建,而是先开一个定时器倒计时2秒,在前1.2秒时会根据玩家的位置来在界面上显示红色激光,警告敌机跟踪核弹即将发射。倒计时结束后关闭定时器,敌机核弹加入精灵组,从而在界面上方发射并迅速下降,玩家需进行及时反应并躲避。这样在给游戏增加难度,带来紧张刺激感的同时,也提高了游戏的合理性和可玩性。
- 当玩家胜利时,会开启胜利的定时器,显示胜利信息,播放胜利音效并倒计时3秒,之后自动退出游戏。反之,当玩家生命值减到0,则会开启失败的定时器,显示游戏结束,播放飞机被摧毁的爆炸音效并倒计时3秒,之后自动退出游戏。
- 定义一个mysqlTool的工具类,对数据库的连接,游标创建,语句提交等进行封装,使得外部在执行sql语句时直接调用该类的方法就行,不用频繁写游标的开和关,try-catch捕获错误等语句。
- 在history.py模块中,创建MysqlTool()对象并执行查表的sql语句,遍历查询到的数据,找出历史最高分并进行显示,同时倒序遍历score表的最后5条记录,展示用户最近五次游玩无尽模式的记录:包括游玩时间和分数,展示在界面上。
本项目创建了多个类和对象,通过继承的方式能让代码的逻辑层次分明,结构清晰。
在myclass.py模块中,定义了多个父类,如:飞机,子弹,敌机,背景类等。
在无尽模式和boss模式中都对这些父类进行继承,在子类重写了具体的属性和方法,来实现相似场景的不同具体功能。
此外,若要创建实现新的游戏功能,还可以继续继承父类,重用里面的一些属性和方法,使得代码复用性强,程序可扩展性好。
子类的def __init__
中要注意先写super.init()
调用父类构造函数,继承父类的方法和属性。
在敌机的创建,Boss切换时的过渡时间段,以及激光发射等,都使用到了定时器。
比如无尽模式中,创建一个敌机定时器,使每秒产生一个敌机;
Boss1被击败,Boss2来临前也用到了定时器,5秒倒计时中动态展示warning警告条;
在boss2发射核弹前,使用定时器,倒计时2秒后发射核弹,其中在倒计时的前1.2秒会根据玩家位置绘制激光,提示跟踪核弹即将到来,倒计时的后0.8秒激光消失,表示核弹即将发射,2秒倒计时完全结束后,将核弹加入到Boss2的子弹组里,根据玩家飞机x坐标初始化核弹位置并发射。
将游戏记录存储于数据库中,可确保数据不会因当前程序的结束而丢失。同时,玩家在玩无尽模式时还能看到历史最高分,可知道当前分数是否破纪录,提高玩家游戏体验。
除此之外,若将来游戏功能增加,需要存储更多数据,比如用户信息,其他游戏功能的游戏数据等,都可用数据库来存储,利于提高游戏功能的实现效果。
- 增加一些额外的游戏模式,比如关卡功能,双人对战等。
- 在关卡功能中,玩家需通关前面的关卡,才可解锁下一关,关卡难度会逐渐增加,为了提高游戏的可玩性和丰富性,还可在该模式中添加剧情等设定,比如在银河危机背景下,对外来入侵者的抵御与进攻之类的。关卡中的敌机和无尽模式的类似,不过每一关卡的敌机数量有限,玩家在规定时间内击败敌机且保证自身存活,即可通关并解锁下一关和相关剧情。
- 在双人对战中,需要在main函数中多创建一个玩家飞机对象,其中可设置玩家1通过WASD四个按键控制飞机移动,空格发射子弹;玩家2通过上下左右四个箭头按键来控制飞机移动,按Enter发射子弹,其他代码逻辑其实和一个飞机的模式差不多。
- 玩家飞机可以升级,可以有多种飞机可以选择或者切换飞机形态,可以有僚机,增强飞机子弹武器等,让游戏具有养成模式。并且在一个界面上显示这些飞机,武器等数值信息。这些飞机和僚机本质上都是飞机,也可以继承父类Player来实现,至于武器,则可以继承父类Bullet子弹类来实现,其他飞机武器的升级等数值信息则可以用字典、列表等形式存储,复杂的话可考虑将数据放入数据库中。
- 增加登录注册功能,可以让不同玩家使用这种游戏,并在数据库中分表存放不同玩家的信息,保证玩家间数据的相互独立性。
本项目为个人的python期末大作业,整个项目相对其他普通的飞机大战来说加了更多功能和UI设计,定时器等逻辑判断较多,但从整体上看还是属于一个比较基础的项目。适合有需要完成课设或者想巩固python基础的小伙伴们学习。
如果对你有帮助的话,能帮忙点个star⭐吗,谢谢啦🤩~