[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程序“迷宮與地牢”即可運行。
    遊戲的玩法:
    在這裏插入圖片描述

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