/SuperMario_Qt_Pku

A Qt Project for Programming Practice

Primary LanguageC++

项目概述

  • 小组名:Debug先疯队
  • 组长:寿晨宸
  • 组员:刘沛雨
  • 项目名:SuperMario
  • 项目简介:经典的超级马里奥游戏,玩家可以操纵Mario移动和跳跃,顶碎砖块,踩扁怪物,最终到达城堡,赢得游戏。
  • 开发工具:Github,Qt Creator

项目分工

  • 寿晨宸:项目整体设计和实现
  • 刘沛雨:项目音效设计和关卡设计

项目功能介绍

浮窗

进入游戏,首先弹出SuperMario的浮窗,浮窗悬停0.5秒后隐藏,显示游戏开始页面,并播放游戏开始音效。

游戏开始界面

游戏开始界面中包含三个按钮,分别为Start开始按钮,Exit退出按钮和关于按钮。在接下来的进程中,点击各按钮后都会播放音效和动画。

  • Exit按钮

    • 点击Exit按钮,弹出对话框,询问是否退出游戏:其中点击Yes退出游戏,点击No则返回游戏。

  • 关于按钮

    • 点击关于按钮会显示aboutScene的界面。该界面包含游戏指南和返回按钮,点击返回按钮则可回到开始界面。

  • Start按钮

    • 点击Start开始按钮进入游戏主界面,并播放游戏背景音乐。

游戏主界面

进入游戏界面后,自动播放游戏背景音乐,并实时显示游戏数据。玩家可以通过键盘操纵Mario移动,并通过按钮控制游戏。

游戏数据

在游戏主界面的左上角会实时显示游戏的相应数据。包含游戏进行的时间,Mario所剩的生命值,Mario在本局游戏中所得的分数和Mario在本局游戏中得到的金币总数。

游戏按钮

在游戏主界面的右下角有三个按钮,分别为音乐控制按钮,暂停按钮和返回按钮。

  • 音乐控制按钮。可以控制游戏主界面音乐的播放或静音。

  • 暂停按钮。点击暂停按钮,弹出暂停菜单。游戏停止计时,Mario和Monster暂停移动,游戏静音。暂停菜单包含两个按钮,分别为Exit和Continue。

    • 点击Exit按钮,弹出对话框,询问是否退出游戏:其中点击yes退出游戏,点击no则返回游戏。

    • 点击Continue按钮,继续游戏。

  • 返回按钮。点击返回按钮,返回初始页面。在此过程中游戏暂停,音乐设置和游戏进程保留。

游戏控制与游玩

玩家可以通过键盘控制Mario的移动。

  • 使用方向键控制Mario左右移动。
  • 使用空格键跳跃。
  • 使用k键加速。

Mario可以与游戏内各元素进行交互。游戏内元素有:地面,普通砖块,不含金币的问号砖块,含金币的问号砖块,水管,怪物和城堡。

  • 地面。屏幕最下方存在地面。Mario和怪物可以在地面上行走。Mario行走时,游戏会显示Mario和地面的相对运动。

  • 普通砖块。Mario和怪物无法穿过普通砖块。Mario可以顶碎普通砖块。顶碎普通砖块后,Mario将获得5分,而砖块将不复存在。Mairo顶碎普通砖块时会播放相应音效。

  • 问号砖块。Mario可以顶破问号砖块,如果问号砖块中含有金币,则会播放金币跳跃的动画,并获得10分;如果问号砖块中不含金币,则Mario获得5分。当问号砖块尚未被Mario顶破时,问号砖上播放问号动画;顶破后,问号砖变为棕色的不可摧毁的砖块。Mario顶碎含金币和不含金币的问号砖块时皆会播放相应的音效。

  • 水管。水管分为长水管和短水管。Mario和怪物无法摧毁亦无法穿过水管。Mario可以在水管顶部行走或停留。

  • 怪物。怪物只在地面上运动。遇到砖块、水管和地图边界会折返。

    • Mario若在行走过程中触碰到怪物,则Mario生命值减1。若Mario生命值未归零,则Mario闪烁,进入无敌状态一段时间。若Mario生命值归零,则播放游戏失败音乐,弹出游戏失败界面,关闭游戏背景音乐,停止游戏进程。游戏失败界面包含一段文字和两个按钮。

      • 文字:"You Lost!Sorry!"
      • Restart按钮:重新开始这局游戏。游戏复原为初始状态,各项数据清零。
      • Exit按钮:出现退出游戏的对话框。
    • Mario若在下落过程中触碰到怪物,则怪物被踩扁、死亡,Mario获得15分。

    • Mario击杀怪物或被怪物击杀时皆会播放相应音效。

  • 城堡。Mario若抵达城堡,则弹出游戏胜利界面,播放游戏胜利音乐,关闭游戏背景音乐,停止游戏进程。游戏胜利界面包含一段文字和两个按钮。

    • 文字:祝贺玩家顺利通关,并显示玩家通关耗费的时间和得到的分数。
    • Restart按钮:重新开始这局游戏。游戏复原为初始状态,各项数据清零。
    • Exit按钮:出现退出游戏的对话框。

项目各模块与类设计细节

游戏包含多个模块和类,这些模块和类相互独立又相互关联,构建了游戏的框架和运行逻辑。

  • MyButton

    • 封装的控件,游戏内的各按钮皆由基于QPushButton的MyButton类实现。
      • 使按钮控件在点击时具备动画效果。
      • 在使用按钮控件时可以轻松地设置其图像和样式。
  • GameBeginWindow

    • 游戏初始界面
      • 内部封装有三个按钮及信号和槽响应机制。具体运行逻辑见上文。
      • 重写了paintEvent事件,绘制界面背景图。
      • 包含有MainScene成员变量。
  • AboutScene

    • 关于界面。
      • 可以通过返回按钮返回游戏初始界面。具体运行逻辑见上文。
  • Music

    • 音乐
      • 载入游戏使用的主要音效素材。
      • 记录整体游戏的静音状态。
  • Brick

    • 砖块。实现游戏中的普通砖块和特殊砖块
      • 记录砖块的坐标,种类和状态等信息。
      • BrickStateChange函数:改变砖块的状态。
  • Castle

    • 城堡
      • 记录城堡的坐标。
  • Pipe

    • 水管。实现游戏中的长水管和短水管。
      • 记录水管的坐标、种类、长度和宽度。
  • Monster

    • 怪物
      • 内部包含Brick,Mario,Pipe指针,实时获取游戏信息。
      • 记录monster的坐标和状态。
      • MonsterMove函数:实现monster的移动,碰撞检测和与Mario的交互(击杀和被击杀)。
  • Mario

    • 马里奥
      • 记录Mario的各项信息。
      • MarioJump函数:实现Mario的弹跳。
      • MarioMove函数:实现Mario的水平移动。
      • MarioDie函数:实现Mario的死亡动画,设置Mario的死亡状态。
      • InvicibleSet函数:实现Mario死亡后的无敌帧。
  • MainScene

    • 游戏主界面
      • 记录游戏进程和信息。包含Brick,Castle,Mario,Monster,Pipe等类的成员。
      • paintEvent事件:重写绘图事件。载入游戏图片素材,实现主界面各个要素的绘制。
      • timerEvent事件:重写计时事件。通过一快一慢两个计时器动态更新游戏状态,实现动画效果。
      • keyPressEventkeyReleaseEvent事件:重写键盘事件。监控键盘输入(各按键的按下与松开)以改变游戏内各成员的状态。
      • SetPauseScene函数:设置暂停界面。运行逻辑见上文。
      • SetButton函数:实现主界面的各个按钮。运行逻辑见上文。
      • SetWholeGame函数:实现游戏的初始化。
      • CollisionCheckJumpUp函数:Mario跳跃上升时的碰撞检测。
      • CollisionCheckJumpDown:Mario落下时的碰撞检测。
      • CollisionCheckMove:Mario水平移动时的碰撞检测。
      • GameOver函数:实现游戏胜利界面和失败界面的弹出。
      • SetGameOverScene函数:设置游戏胜利界面和失败界面,并实现各按钮的运行逻辑。具体效果见上文。
  • PauseScene

    • 游戏暂停界面
  • GameOverScene

    • 游戏胜利界面和失败界面

项目反思

该项目基于C++,利用Qt提供的ui界面,主要通过代码方式尝试复原了经典游戏《超级玛丽》。通过本次游戏项目设计,我们初步了解了Qt的基本内容与游戏开发设计的基本流程,巩固了面向对象程序设计的有关知识,提升了项目代码能力与合作能力。当然在完成本次大作业的过程中我们也遇到了诸多问题,最终的游戏效果也并非完美无瑕,以下将详细列举并阐述。

游戏在不同操作系统下的兼容性不高

本组大作业由两位同学合作完成,其中项目整体框架的搭建在macOS系统中下进行并成功运行,初步实现了游戏的基本功能。但当相同的代码在Windows系统下编译时出现了错误,导致在Windows系统下无法调试代码。后经过修改程序编译成功,但进入游戏界面后出现了许多bug,如静音按钮失灵、角色无法移动、音效延迟很高等问题。这使得游戏在Windows系统下无法正常运行,也给游戏的设计过程带来了不少麻烦。初步考虑原因,一方面可能由于两位同学的Qt版本并不完全相同,部分函数功能在不同版本下有所偏差;另一方面也可能因为Qt5在不同系统的适配性不佳,导致出现了一些意料之外的bug。

游戏功能尚有所欠缺,仍有改善空间

开始界面未配备“继续”按钮,“START”按钮兼具开始游戏与继续游戏的功能。缺点在于无法在不退出游戏的条件下重新开始一轮游戏,如果在游戏进行中想重新开始游戏则必须完全退出游戏后重新打开游戏。除此之外,音效控制按钮只在游戏主界面中存在,无法在游戏初始界面控制音量。同时,音效控制按钮只有静音与不静音两种选项,未能做到加入音量控制条精确控制音量大小。游戏的主体功能较为完备,但在细节上仍有许多可改进之处。

游戏窗口无法调整大小

游戏在开始时设计为固定大小的窗口,由于游戏本身主要由代码实现,并未过多使用Qt提供的ui设计界面,且游戏场景布置时坐标以数值方式计算得出而非根据窗口比例设计各个控件的相对位置关系,因此在后续试图改进为可调窗口大小时遇到许多麻烦。在以后的Qt程序设计中应当更多使用ui设计界面,更加高效快捷地设计控件的相对位置关系。

地图设计较为单调,关卡数不足

该项目主要以复原经典为主,在ui设计、游戏玩法等方面均以原版《超级玛丽》为参考。由于时间原因,仅设计了一个关卡,且关卡中地图设计稍显单一。地图主要由三种砖块、两种水管以及怪兽构成,未加入可以奖励生命值的蘑菇,对新玩法的开发设计也有所欠缺,没有在原版游戏的基础上加以创新,在可玩度上提升不大。

项目总结

总的来看,本次大作业是一个锻炼在短时间内学习并运用编程工具完成项目的能力的机会,提升了我们对于代码项目的了解以及一些具体工具的运用能力。在完成本次大作业的过程中,了解到了头文件与源文件的具体关系以及C++程序的简要编译过程,感受到了面向对象程序设计在多人合作完成项目时极佳的代码可读性与参与感,提升了对编程的兴趣。在以后的程序设计中应当注重总体规划与设计,提升项目的使用体验与功能的完备性,最大限度保证快速有效地完成项目要求;同时也应注意项目在不同系统中的适配性与兼容性,提高项目的可用范围。