[内附完整源码和文档] 基于Qt实现的植物大战僵尸游戏

1.总体介绍
本次大作业,用面向对象的思想和方法,在实现了所有基本功能以外,还实现了许多其他的附加功能。

3.植物与僵尸的设计
3.1 植物的设计
本次大作业实现了三种植物,向日葵(sunflower)、豌豆射手(pea)、坚果墙(wallnut),均继承自父类 plant 类。

3.1.1 植物类(plant)
plant 类是所有植物的父类,其成员变量为所有植物共同的属性,life(生命值),price(消耗阳光值),coolingtime(冷却时间),row、col(所在的行和列数),mediaPlayer_plant(种植时的声音),plantSwingMovie(植物不在攻击状态时的动画)等等。

在构造函数里,初始化了 mediaPlayer_plant,保证每种一个植物时会有对应的音效播放。

3.1.2 向日葵类(sunflower)
除了继承自父类的成员变量外,自己的成员变量全部和生产阳光有关。另外还有一个 slot : slot_produceSunshine() ,这个slot 的功能是让每个向日葵每段时间(10 秒)自动产生一个阳光。

在构造函数里,初始化了向日葵的动画、自己的时间器、和阳光。

3.1.3 坚果类(wallNut)
因为坚果只有挨吃这一项功能,所以除了继承自父类的成员变量外,并没有自己的成员变量。只是在构造函数里将冷却时间和价格初始化了。

3.1.4 豌豆射手(pea)
除了继承自父类的成员变量外,另外还有 attackNumber(攻击力),shootingTriggerTimer(控制射击的时间器),bulletList(子弹的list)。

在构造函数里,初始化了自己的成员变量,并且将子弹射击的间隔设置成了 1.4 秒,结合 pea 类自己的 slot:slot_shootingbullet 就可以实现自动射击。

3.2 僵尸的设计(zoobie)
本次大作业实现了三种僵尸,普通僵尸(zoobie),铁桶僵尸(bucketZoobie),撑杆跳僵尸(poleVaultingZoobie),后两种僵尸均继承自普通僵尸。

注:我在一开始命名时将僵尸的英文 zombie 打成了 zoobie,由于发觉过来时程序基本已经写完了,想改回来已有心无力,请谅解这个低级的拼写错误。

3.2.1 普通僵尸(zoobie)
zoobie 类有所有僵尸的共同属性,生命值(life)、移动速度(movingSpeed)、攻击力(damagenumber)、所在行(row)、是否正在吃植物(isEatingPlants)、自己的计时器( zoobietimer )、 走 路 和 吃东西 时 的 两 个 动 作(zoobieMoveMovie、zoobieEatingMovie)。还定义了两个slot , slot_zoobiePositionChange( 僵 尸 位 置 改 变 ) 、slot_zoobieActionChange(僵尸动作改变)。在构造函数里,将吃东西的声音、僵尸的动作初始化。

3.2.2 铁桶僵尸(bucketZoobie)
继承自 zoobie 类,由于铁桶僵尸和普通僵尸除了血厚一点没有其他优势,所以它除了继承自父类的成员变量外,没有自己的成员变量。在构造函数里,将成员变量初始化。

3.2.3 撑杆跳僵尸(poleVaultingZoobie)
继承自 zoobie 类。因为有撑杆跳这个功能,所以这个类除了继承自父类的成员变量外,还有为撑杆跳专门设置的成员变量,isToVault(是否将要跳)、hasVaulted(是否已经跳过了)等等,重写了2 个 slot : slot_zoobieActionChange 和slot_zoobiePositionChange. 以下表格体现了一个撑杆跳僵尸从开始出现到越过一个植物后吃东西的完整的实现逻辑。

各个状态 hasVaulted isToVault isEatingPlants
走路(没遇到植物) false false false
第一次遇到植物 后,(还没跳) false True false
第一次遇到植物 后,已经跳了 true false false
第一次遇到植物 后,正常走路 true false false
第一次遇到植物 后,吃东西 true false true
每个僵尸均有自己的 timer,每隔 20ms 检查一遍僵尸的状态参数是否变化,发生变化后就执行 slot 里不同的 case。实现了程序接口和实现的分离。

4.游戏逻辑
4.1 摆放的植物自动根据特性攻击僵尸
gamewindow 里实现了修改植物和僵尸状态的 slot:slot_change_P_and_Z_state(),一旦僵尸出现在游戏画面中,这个 slot 会遍历所有植物并检查是否符合条件,一个符合条件则修改植物和僵尸各自的 flag 标记。植物和僵尸自己的 slot 一旦检测到 flag 变化,则会触发相应的动作。简单运用了老师在课上讲的观察者模式,实现了接口和实现的分离。

4.2 僵尸在屏幕上出现,前进并攻击植物
gamewindow 这个类里有三个 slot 来实现每隔一段时间自动刷新僵尸,分别是slot_produceZoobie, slot_produceBucketZoobie, slot_producePoleVaultingZobie,并且随着游戏进程的推进,产生僵尸的概率将会越来越高。增加游戏的难度。

前进并攻击植物的实现也是通过 3.1 里所描述的方法 , 在slot_change_P_and_Z_state()里改变 flag,僵尸自己一旦检测到 flag 有变化机会触发相应的动作。由此实现了接口与实现的分离。

4.3 游戏结束
4.3.1 游戏胜利
gamewindow 下的 slot:slot_checkGameWin 负责游戏胜利的判断。游戏胜利需要满足以下两个条件:

每个僵尸出现的轮数 >= 上限

存储僵尸的 list 判定为空

满足之后这两个条件后触发函数 func_gameWin,播放胜利动画和音效,暂停所有计时器。

4.3.2 游戏失败
gamewindow 下的 slot:slot_checkGameLose 负责游戏失败的判断。这个 slot 对每一种僵尸 list 里的每一个僵尸进行判断,如果它的 x 坐标小于一定的值,则触发函数 func_gameLose,播放失败动画和音效,暂停所有计时器。

4.4 删除死亡的僵尸和植物
gamewindow 下的 slot_deleteDeadZoobie 和 slot_deleteDeadPlant 负责删除死亡的僵尸和植物。对每一个僵尸和植物进行遍历,如果生命值(life)<= 0, 则在相应的 list 中删除它。

在这里插入图片描述
在这里插入图片描述

完整的源码和详细的文档,上传到了 WRITE-BUG技术共享平台 上,需要的请自取:

https://www.write-bug.com/article/3100.html

你可能感兴趣的:([内附完整源码和文档] 基于Qt实现的植物大战僵尸游戏)