[Qt] 迷宫随机生成和自动寻路算法、布局管理器、动态效果、界面切换、播放音频【迷宫、魔塔、超级玛丽】 -C++课程设计:Qt实现的迷宫与地牢游戏

基于QT的迷宫与地牢小游戏开发

首先贴出链接

  • 完整Qt源码:点击进入https://download.csdn.net/download/qq_43365825/11852112
  • 发布可执行程序:点击进入https://download.csdn.net/download/qq_43365825/11852139
  • 视频介绍:点击进入https://www.bilibili.com/video/av70867935/

1. 系统结构及实现

程序结构图

  • 游戏中有迷宫模式和地牢模式两种游戏模式,主要由5个类组成。主界面类包含其它4个类。迷宫类maze主要实现迷宫模式中,迷宫地图的随机生成,寻路算法存储的路径;地牢类Dungeon主要实现地牢地图的生成,初始化地图贴图资源字符串,地牢中角色信息的初始化,战斗伤害的计算;开始界面类interface主要实现开始界面的设置;商店类StoreWidget主要实现地牢模式中的商店功能。下面来详细介绍各个类的实现。

1.1 迷宫类maze

迷宫类中的自动寻路算法autoFindPath的实现

  • 在生成迷宫时,将可以走的路标记为1,不能走的墙标记为0。自动寻路时,从当前位置开始每次都从4个方向,按照左、下、右、上的顺序来检测前方是路还是墙(标记是1还是0),一旦找到一个方向上的路是可以走的,则将此方向上的路的座标存储到路径栈PathStack中,并且标记已经走过的路,防止走回头路陷入死循环。如果探测后4个方向都找不到可以走的路,则将路径栈中栈顶元素出栈,回退到上一个路径点重新探测,跳过被标记为走过的路,如果4个方向依然找不到可以走的路,则重复上述步骤,将当前路径栈栈顶元素出栈,回退到上一个路径点重新探测,一直重复上述步骤,直到探测到可以走的路才将此方向上的路压入到路径栈中,并继续向前探测。生成的迷宫地图必有一条通路,所以总能找到一条通往出口的路径。

自动寻路算法

1.2 地牢类Dungeon

  • 地牢类中初始化地牢地图initialMap的实现
void Dungeon::initialMap()
{
    floor=1;
    MAX_HP=100;
    isPre=false;
    isNext=false;
    x=11;
    y=8;
    initialrole();
    int num=1;
    while(1)
    {

        if(num==1)
        {
            int tempmap[12][16]={
                15,1,1,3,3,3,1,1,1,1,1,1,1,1,1,1,
                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
                0,8,1,1,1,3,17,1,17,1,1,22,2,5,0,1,
                0,1,1,11,1,1,0,1,0,1,1,23,2,20,0,1,
                0,0,0,17,0,0,0,1,0,0,0,0,17,0,0,1,
                0,20,1,1,1,1,0,1,0,1,3,2,4,1,0,1,
                0,20,1,11,1,1,0,1,17,3,2,4,10,1,0,1,
                0,0,0,17,0,0,0,1,0,0,0,0,0,0,0,1,
                0,1,1,2,1,1,0,1,1,1,1,1,1,1,1,1,
                0,8,2,2,2,5,0,0,17,0,0,0,17,0,0,0,
                0,8,2,2,2,5,0,20,2,2,0,1,1,4,1,0,
                0,2,2,2,2,2,0,2,1,2,0,1,3,10,3,0

            };
            for(int i=0;i<12;i++)
            {
                for(int j=0;j<16;j++)
                {
                    map[num-1][i][j]=tempmap[i][j];
                }
            }
        }
       if(num==2)
        {
           int tempmap[12][16]={
               14,1,18,1,1,1,1,1,1,1,1,1,1,1,1,0,
               1,1,0,0,0,0,19,4,20,4,21,0,0,0,0,0,
               1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
               1,0,20,20,5,5,0,1,1,1,0,12,5,2,2,0,
               1,0,19,20,5,5,16,1,1,1,16,12,5,2,19,0,
               1,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
               1,16,5,5,12,5,0,1,1,1,0,12,8,19,2,0,
               1,0,5,5,12,19,0,1,1,1,0,12,9,20,22,0,
               1,0,0,0,0,0,0,1,1,1,16,12,10,21,23,0,
               1,0,19,2,2,2,0,1,1,1,0,0,0,0,0,0,
               1,0,5,5,10,10,0,1,1,1,0,2,2,2,2,0,
               15,0,5,5,10,12,16,1,1,1,16,2,2,2,2,0
           };
           for(int i=0;i<12;i++)
           {
               for(int j=0;j<16;j++)
               {
                   map[num-1][i][j]=tempmap[i][j];
               }
           }
        }
       if(num==3)
       {
           int tempmap[12][16]={
               20,1,1,22,0,20,1,1,20,0,1,0,1,1,2,1,
               1,1,2,1,0,1,20,20,1,0,1,0,1,2,8,2,
               1,2,8,2,0,1,1,21,1,0,1,17,4,4,2,1,
               4,1,4,1,0,20,1,1,20,0,1,0,0,0,0,0,
               0,0,17,0,0,0,1,1,0,0,1,0,1,1,1,1,
               1,1,1,1,1,3,1,1,1,1,3,1,1,1,1,1,
               0,0,17,0,0,1,1,1,1,0,1,0,0,0,0,0,
               1,1,11,1,0,0,1,1,0,0,1,0,2,2,2,20,
               1,4,3,20,0,1,1,1,1,0,1,17,4,4,3,8,
               1,1,3,23,0,1,1,1,1,0,1,0,0,0,0,0,
               0,0,0,0,0,0,1,1,0,0,3,0,1,1,1,1,
               14,1,1,1,1,1,1,1,1,0,1,17,1,1,1,15,
           };

           for(int i=0;i<12;i++)
           {
               for(int j=0;j<16;j++)
               {
                   map[num-1][i][j]=tempmap[i][j];
               }
           }
       }
       if(num==4)
       {
           int tempmap[12][16]={
               1,21,1,1,0,1,31,32,33,1,0,1,1,1,1,1,
               8,2,20,1,0,1,34,35,36,1,0,1,1,1,1,1,
               1,3,1,1,0,1,1,1,1,1,0,1,20,1,10,1,
               1,1,1,1,0,1,1,1,1,1,0,1,1,11,1,1,
               0,0,17,0,0,0,0,18,0,0,0,0,17,0,0,0,
               1,1,4,1,17,1,1,3,1,1,1,11,1,1,1,1,
               1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,
               3,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,
               17,0,0,0,17,0,0,0,0,17,0,0,0,0,0,17,
               1,0,1,20,4,1,0,1,1,4,1,1,1,1,0,1,
               1,0,1,3,1,3,0,1,23,2,8,1,1,1,0,1,
               15,0,20,1,20,1,0,1,1,3,1,1,1,1,0,14,
           };
           for(int i=0;i<12;i++)
           {
               for(int j=0;j<16;j++)
               {
                   map[num-1][i][j]=tempmap[i][j];
               }
           }
       }
       if(num==5)
       {
           int tempmap[12][16]={
               15,0,1,1,3,17,1,0,1,4,1,17,1,1,17,1,
               1,0,1,1,1,0,20,0,4,2,4,0,1,1,0,1,
               1,17,4,1,1,0,1,0,2,4,2,0,3,3,0,3,
               0,0,0,0,17,0,3,0,2,2,2,0,20,20,0,1,
               20,1,4,1,1,0,1,0,22,23,19,0,20,20,0,1,
               20,1,1,1,4,0,4,0,0,0,0,0,0,0,0,1,
               0,0,12,0,0,0,1,1,3,1,1,1,1,1,1,1,
               1,1,12,1,1,0,3,0,0,0,0,0,0,0,0,3,
               1,1,4,1,1,0,1,0,1,1,1,1,1,1,1,1,
               22,23,20,8,10,0,1,0,1,1,1,0,0,0,0,0,
               0,0,0,0,0,0,1,0,1,1,1,0,1,1,1,1,
               14,1,1,1,1,1,1,0,1,1,1,16,1,1,1,24,
           };
           for(int i=0;i<12;i++)
           {
               for(int j=0;j<16;j++)
               {
                   map[num-1][i][j]=tempmap[i][j];
               }
           }
       }
       if(num==6)
       {
           int tempmap[12][16]={
               14,0,20,20,2,0,1,1,1,1,1,1,1,1,1,1,
               1,0,20,20,2,0,1,0,0,0,0,0,0,0,0,17,
               1,0,0,0,4,0,1,0,25,8,2,1,2,25,1,25,
               1,17,17,1,1,17,1,0,5,1,2,25,1,2,1,1,
               1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
               1,1,1,11,4,1,20,1,1,1,25,25,1,1,1,1,
               0,0,0,0,0,0,1,0,0,0,0,0,0,17,0,1,
               2,1,1,4,8,0,1,0,10,2,0,0,1,4,0,1,
               2,1,11,23,12,0,1,0,9,2,0,0,5,1,0,1,
               4,2,1,4,1,0,1,0,8,2,26,2,4,2,0,1,
               17,0,0,0,0,0,1,0,0,0,0,1,2,1,0,1,
               1,1,3,1,12,1,1,0,1,1,1,19,1,1,0,15,
           };
           for(int i=0;i<12;i++)
           {
               for(int j=0;j<16;j++)
               {
                   map[num-1][i][j]=tempmap[i][j];
               }
           }
       }
       if(num==7)
       {
           int tempmap[12][16]={
               15,0,27,29,0,22,0,1,1,1,0,10,0,20,0,3,
               1,0,8,27,0,23,0,1,1,1,0,4,0,20,0,3,
               1,0,8,27,0,4,0,3,0,26,0,3,0,8,0,3,
               1,0,2,8,0,2,0,1,0,1,0,1,0,2,0,1,
               1,0,2,10,0,1,0,1,0,1,0,1,0,1,0,1,
               17,0,25,25,0,17,0,18,0,17,0,17,0,25,0,17,
               1,25,1,1,12,1,1,1,1,1,1,1,1,1,1,1,
               17,0,25,25,0,17,0,17,0,17,0,17,0,25,0,17,
               1,0,2,2,0,1,0,1,0,1,0,1,0,1,0,1,
               3,0,8,10,0,2,0,12,0,4,0,3,0,10,0,1,
               3,0,8,27,0,2,0,22,0,20,0,4,0,20,0,1,
               3,0,8,28,0,2,0,23,0,20,0,10,0,20,0,14,
           };
           for(int i=0;i<12;i++)
           {
               for(int j=0;j<16;j++)
               {
                   map[num-1][i][j]=tempmap[i][j];
               }
           }
       }
       num++;
       if(num>Total_Floor)
       {
           break;
       }
    }
}
  • 地牢中每层的地图都不相同,而且每层地图中还有许多游戏角色(物品、怪物、金币等)。而且每层地牢之间是连通的,可以去往下一层地牢,也可以回到上一层地牢,而玩家在地牢中对每层地牢造成的影响都必须保存着,为了实现地牢的这些效果,将地牢抽象为一个3维数组。数组的第3维代表地牢的层数,第1维和第2维表示每层的地牢地图。每层地牢就可以通过第3个维度进行联系,而且每层的地图可以设置为不相同,并且玩家对地牢造成的影响都可以储存在这个3维数组当中。

  • 在实现地牢中每层地图的过程当中,为了方便加载地图资源,将二维数组中的元素与地图贴图资源的名称相对应,比如0代表墙,1代表路,2代表金币,3代表小星星,15代表下一层入口,20代表黄钥匙等等。

  • 地牢中的英雄与怪物都有自身的属性,如生命值、攻击力、防御力等等,将他们都抽象为一个结构体,结构体中存储英雄与怪物的自身属性,修改起来也较为方便。

地牢第一层

1.3 商店类StoreWidget

  • 商店类
#ifndef STOREWIDGET_H
#define STOREWIDGET_H

#include <QWidget>
#include <QLabel>
#include <QGraphicsView>
#include <QTimer>
#include <QKeyEvent>
#include <QShowEvent>
class StoreWidget : public QWidget
{
    Q_OBJECT
public:
    explicit StoreWidget(QWidget *parent = 0);
    int chooseOption; //选择了第几项
    int BuyTimes;
    QTimer *haveBuyTimer;//购买计时器
    bool setChooseEnable;//是否可以购买
    bool StoreWinisShow;//商店窗口是否显示
    int Currstore_price;//当前价格
    int Nextstore_price;//下一次价格
private:
    int OptionNum; //有多少个选项
    int border_color_it;
    QString OptionBoxColor[6]= {"FFFFFF", "CCCCCC", "999999", "666666", "999999", "CCCCCC"};
    QTimer *OptionBoxTimer;
    QGraphicsView *OptionBox;
    QWidget *StoreWin;
    QLabel *text1;
    QLabel *text2;
    QLabel *hpOption;
    QLabel *mpOption;
    QLabel *atkOption;
    QLabel *defOption;
    QLabel *exitOption;
private:
    void initialStoreWin();//初始化商店界面
    void keyPressEvent(QKeyEvent *event);//当前类中的键盘事件与mainwindow中的键盘事件互不影响
    void showEvent(QShowEvent *);//重写窗口显示事件,为了使当前窗口获得焦点
public slots:
    void OptionBoxborderChanged();
};

#endif // STOREWIDGET_H

  • 商店类中商店购买功能的实现
void StoreWidget::keyPressEvent(QKeyEvent *event)
{   
    if(event->key() == Qt::Key_W)
    { //向上
        if (chooseOption > 0)
        {
            chooseOption -= 1;
            OptionBox->setGeometry(32, 112 + 48 * chooseOption, 192, 32);
        }
        else
            chooseOption = 0;
    }
    else if (event->key() == Qt::Key_S)
    { //向下
        if (chooseOption <= OptionNum - 2)
        {
            chooseOption += 1;
            OptionBox->setGeometry(32, 112 + 48 * chooseOption, 192, 32);
        }
        else
            chooseOption = OptionNum - 1;
    }
    else if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter || event->key() == Qt::Key_Space)
    {
        if (chooseOption != OptionNum - 1)//不是选择的离开商店选项
        {
            Currstore_price=((BuyTimes) * (BuyTimes) - (BuyTimes) + 2) * 10;
            Nextstore_price = ((BuyTimes +1 ) * (BuyTimes +1 ) - (BuyTimes +1 ) + 2) * 10;

            haveBuyTimer->start(100);//开启购买(计时器开启后不是马上执行,而是在当前函数执行完毕后才开始执行,
                                              //所以,如果在执行计时器后才改变setChooseEnable的值,那么在
                                              //当前函数体内,setChooseEnable的值就还不会改变
            if(!setChooseEnable)//金币不够,则不能购买
            {
                return;
            }

            text1->setText(QString::fromStdWString(L"你若给我 ") +
                           QString::number(Nextstore_price) + QString::fromStdWString(L" 个金币"));
            text2->setText(QString::fromStdWString(L"我就可以帮你"));
            hpOption->setText(QString::fromStdWString(L"提升 ") +
                              QString::number(100 * (BuyTimes +1 )) + QString::fromStdWString(L" 点生命"));
            mpOption->setText(QString::fromStdWString(L"提升 ") +
                              QString::number(20 * (BuyTimes +1 )) + QString::fromStdWString(L" 点魔法"));


            BuyTimes++;

            return;
        }
        else
        {
            this->hide();
            StoreWinisShow=false;
            chooseOption=0;//选项框回到起始位置
            OptionBox->setGeometry(32,112,192,32);
            return;
        }
    }
}

商店的功能

  • 商店是通过键盘操作上移下移选项框来进行选择,再通过Enter或者Space键进行购买。在实现时重写QT键盘事件keyPressEvent来实现商店的购买功能。当检测到输入按键为W,选项框就会上移,但若选项框已停留在第一个选项上则不会上移,检测到输入按键为S时,选项框就会下移,但若选项框已停留在最后一个选项上则不会下移。当检测到输入按键为Enter或者Space时,会做出判断,如果选择的选项不是离开商店,则继续进行判断,否则关闭商店窗口。当选择的不是离开商店时,会先判断当前剩余金币是否大于等于当前购买的花费,如过小于,则不能购买,对按键操作不反应,并提示玩家,金币不足。若满足购买的花费,则执行购买操作,每次购买完成后,都会更新商店选项与购买花费,为了平衡游戏难度,“提升攻击力”与“提升防御力”选项不会更新。

1.4 开始界面类interface

开始界面

  • 开始界面提供游戏模式选择接口,玩家通过点击不同模式的选项框进入到不同的游戏模式。开始界面的背景窗口是重写绘图事件paintEvent来实现的,每当开始界面窗口更新时,都会触发绘图事件,绘制窗口背景图片。当玩家点击进入不同的游戏模式时,也会触发绘图事件,绘制不同游戏模式的窗口背景图片。

迷宫模式窗口背景图片
地牢模式窗口背景图片

  • 当玩家选择迷宫模式或者地牢模式按钮后,会出现加载进度条。加载进度条是由QT中的QprogressBar进度条类来实现的。通过Qtimer计时器类对象发出的timeout信号,来触发槽函数loading实现进度条值的变化,当进度条跑满时,使用窗口的update函数强制刷新窗口来执行绘图事件,这样就将玩家的点击与进度条的变化,窗口背景的绘制都联系起来了。

加载进度条的效果

1.5 主界面类mainwindow

主界面中包含的窗口结构
布局管理器结构

主界面的实现

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QGridLayout>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QMainWindow>
#include <QWidget>
#include <QSpinBox>
#include <QPushButton>
#include <QLabel>
#include <QComboBox>
#include <QLineEdit>
#include <QKeyEvent>
#include <QResizeEvent>//QResizeEvent 是主窗口的变化事件
#include <QSequentialAnimationGroup>
#include <QPropertyAnimation>
#include <QTimer>//计时器   QTime 只是用来产生随机数的
#include <QMediaPlayer>//视频、音乐类
#include <QMediaPlaylist>
#include <QPoint>
#include <QProgressBar>
#include "maze.h"
#include "Dungeon.h"
#include "interface.h"
#include "storewidget.h"
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
/**********************   主界面     ***********************/
private:
    int BASIC_WIDTH;//地图窗口宽度
    int BASIC_HEIGHT;//地图窗口高度
    QPoint windowPos;//窗口位置
    QPoint mousePos;//鼠标位置
    QPoint dPos;//鼠标移动后的位置
private:
    interface *surface;//开始界面
    QWidget *MainWidget;//中心窗口
    QWidget *MazeWidget[60][60];//地图窗口数组
    QWidget *People;//角色
    QString character[12];//角色图片字符串
    QGridLayout *gLayout_Map;//地图网格布局管理器
    QHBoxLayout *hLayout;//主界面水平布局管理器
private:
    void initialWindow_Layout();//初始化主窗口
    void keyPressEvent(QKeyEvent *event);//键盘事件(用于操作)
    void mousePressEvent(QMouseEvent *event);//鼠标按下事件(用于移动主界面)
    void mouseMoveEvent(QMouseEvent *event);//鼠标移动事件
private slots:
    void ShowWidget();//显示界面
/**********************   迷宫模式     ***********************/
private:
    int iNum;//自动寻路显示路径辅助变量
    int lastheight;//上一次设置的迷宫高度
    int lastwidth;//上一次设置的迷宫宫宽度
    int StytleNum;//地图风格数字
    bool isPlay;//键盘操作标识(用于限制操作时自动寻路和AI)
    bool isShow;//显示地图标识(用于刷新迷宫地图时销毁上次生成的窗口)
    bool issurface;//开始界面标识(用于标识开始界面已加载完成)
    bool isAIAnimationButton;//AI移动标识
    bool isAutoMoveButton;//自动寻路标识
private:
    maze m;//迷宫类
    QWidget *Controlwidget;//控制界面
    QGridLayout *gLayout_Control;//控制界面网格布局
    QSpinBox *sp_w;//迷宫大小输入
    QSpinBox *sp_h;
    QLabel *label_Stytle;//地图风格显示
    QComboBox *SelectMapStytle;//地图风格选择
    QPushButton *AIAnimationButton;//AI操作
    QPushButton *AutoMoveButton;//自动寻路
    QPushButton *quitButton;//返回主菜单按钮
    QSequentialAnimationGroup *group;//AI操作动画组
    QTimer *timer;//定时器
private:
    void initialControlWidget();//初始化控制界面
    void ShowMaze_Layout();//显示迷宫地图
    void hideMaze();//隐藏迷宫地图
    void resetMaze();//重置迷宫
private slots:
    void moveCharacter();//AI移动时人物图片切换
    void CreateMaze_Layout();//创建迷宫
    void ShowPath();//自动寻路显示路径
    void ShowAnimation();//显示动画
    void timeStart();//定时器开启
    void MapStytleSet();//设置地图风格
    void quit();//返回主菜单
/**********************   地牢模式     ***********************/
private:
    Dungeon d;//地牢类
    QWidget *infoWidget;//状态显示界面
    int moveDirection;//移动方向
    int moveNum;
    QLabel *Floor;//地牢层数
    QLabel *level;//人物状态信息
    QLabel *exp;
    QLabel *hp;
    QLabel *mp;
    QLabel *atk;
    QLabel *def;
    QLabel *score;//金币
    QLabel *yellowkeyNum;//钥匙信息
    QLabel *purplekeyNum;
    QLabel *redkeyNum;
    QLabel *CharacterName;
private:
    void initialinfoWidget();//初始化状态界面
    void initialGetitemWin();//初始化获得物品信息界面
    void initialFightWin();//初始化战斗界面
    void initialSetNameWin();//初始化设置角色名界面
    void ShowDungeon();//显示地牢
    void hideDungeon();//隐藏地牢
    void updateStatusData();//更新状态数据
    void Move();//人物移动
    void changeHP(int num);
    void QuestionBox(int num);//问号箱
    void items(int _itemNum, int _moveDirection);//物品
    void doors(int _doorNum, int _moveDirection);
    void Monsters(int _MonsterNum,int _moveDirection);
    void checkPrefloor();//上一层
    void checkNextfloor();//下一层
    bool isDynamic(int i,int j);
    void soundPlay(int CurrentIndex);
private slots:
    void GetitemWinshow();//获得物品信息界面显示
    void FightWinshow();//战斗界面显示
    void ShowdynamicEffect();//展示动态效果
    void OpenStore();//打开商店
    void ReturnMainMenuPlay();//返回主菜单
    void RestartPlay();//重新开始
    void soundStop();//音效停止
    void CheckBGMstate();//检查音乐状态
    void EnterDungeon();//角色名设置完成,进入地牢
private://获得物品信息栏
    QLabel *GetitemsShow;
    QTimer *GetitemTimer;
    int GetitemNum;
    int itemNum;
private://设置角色名界面
    QLineEdit *NameEdit;
    QPushButton *SetDone;
private://战斗界面
    QWidget *FightWidget;
    QTimer *FightTimer;
    bool isFighting;
    QLabel *Monster_pic;//怪物信息标签
    QLabel *Monster_name;
    QLabel *Monster_hpText;
    QLabel *Monster_hp;
    QLabel *Monster_atkText;
    QLabel *Monster_atk;
    QLabel *Monster_defText;
    QLabel *Monster_def;

    QLabel *Character_pic;//人物信息标签
    QLabel *Character_name;
    QLabel *Character_hpText;
    QLabel *Character_hp;
    QLabel *Character_atkText;
    QLabel *Character_atk;
    QLabel *Character_defText;
    QLabel *Character_def;

    int MonsterNum;//怪物编号
    int fight_period_it;//战斗次数
    int fight_end_it;//战斗结束标识
private://商店界面
    StoreWidget *Store;
private://按钮
    QPushButton *ReturnMainMenu;
    QPushButton *Restart;
private://动态效果
    QTimer *dynamicEffectTimer;//动态效果计时器
    int display_it;
private://音效
    QMediaPlayer *BGM;
    QTimer *BGMTimer;
    QMediaPlaylist *soundlist;
    QMediaPlayer *sound;
    QTimer *soundTimer;
};

#endif // MAINWINDOW_H

  • 主界面中的窗口结构与使用的布局管理器结构图以在上图给出。当主窗口构造分配内存时,这些窗口也会被分配内存。在实际的游戏执行过程中,会将除主窗口外的所有其它窗口先隐藏起来,即调用窗口的hide函数,当游戏打开时,最先显示的是开始界面窗口,玩家点击不同的接口按钮后,根据玩家选择的模式按钮,显示对应模式下的窗口,同时隐藏开始界面窗口。

  • 玩家选择迷宫模式后,在进度条跑满后,会触发绘图事件,开始界面的背景图片重新绘制为迷宫模式的窗口图片,当玩家输入好迷宫大小点击生成迷宫按钮后,开始界面窗口会隐藏起来,同时地图窗口与迷宫控制界面窗口和主人物窗口会显示,这样就是实现了玩家控制窗口切换的效果。

  • 同样的,玩家选择地牢模式后,在进度条跑满后,会触发绘图事件,开始界面的背景图片重新绘制为地牢模式的窗口图片,当玩家输入角色名后,开始界面的窗口会隐藏,同时地图窗口与地牢人物状态显示窗口和主人物窗口会显示出来。当玩家在地牢中碰到怪物后,地牢战斗窗口也会显示出来,战斗完成后隐藏起来。当玩家进入商店,商店界面窗口也会显示出来,玩家购买完成,点击离开商店选项后,商店界面就会隐藏起来,这样就实现了玩家与游戏之间的交互。

  • 每种游戏模式下都有返回主界面按钮,因为在游戏设计时隐藏了主界面窗口的边框,只有通过开始界面的“离开游戏”选项才能退出游戏,在玩家点击退出游戏后,会有提示对话框,玩家必须点击“确认”按钮才会真的突出游戏,这种设计是为了防止玩家误点而关闭游戏。

1.6 其它功能的实现

迷宫模式下地图风格切换的实现

  • 在迷宫模式下,有3种地图风格可以选择:魔法少女、火影忍者、超级玛丽。玩家选择不同的地图风格后,点击生成迷宫按钮后,就会生成相应风格的迷宫。

在这里插入图片描述

  • 下拉菜单选项框类QcomboBox存储不同地图风格的名称,当玩家点开下拉菜单,选择不同的地图风格时,QcomboBox类对象会产生一个currentIndexChanged信号,并触发MapStytleSet槽函数,槽函数会使下方的QLabel标签显示相应地图风格的概览图片。点击生成迷宫按钮后,加载相对应地图风格的贴图,就会生成玩家选择的风格的地图。

游戏的BGM以及地牢模式中的音效实现

  • QT中的音乐媒体类QmediaPlayer可以加载音乐资源,并播放。而地牢模式中的游戏音效,实现的方法是通过音乐媒体列表类QmediaPlaylist先把各种音效资源加载到列表里,然后需要不同的音效就通过setCurrentIndex函数列表中的不同音效进行播放。

2.游戏安装和使用说明

  • 游戏的安装:

    本游戏软件为绿色软件,无需安装。双击exe程序“迷宫与地牢”即可运行。
    游戏的玩法:
    在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章