C++學習教程,QT飛機大戰教程(含詳細步驟教程)

1 項目簡介

飛機大戰是我們大家所熟知的一款小遊戲,本教程就是教大家如何製作一款自己的飛機大戰

首先我們看一下效果圖

玩家控制一架小飛機,然後自動發射子彈,如果子彈打到了飛下來的敵機,則射殺敵機,並且有爆炸的特效

接下來再說明一下案例的需求,也就是我們需要實現的內容

  • 滾動的背景地圖
  • 飛機的製作和控制
  • 子彈的製作和射擊
  • 敵機的製作
  • 碰撞檢測
  • 爆炸效果
  • 音效添加

2 創建項目

創建項目步驟如下:

  • 打開Qt
  • 跟着嚮導創建項目

基類選擇 QWidget空窗口

​ 第一個場景爲主場景 MainScene

​ 不帶UI界面

2.1 打開Qt

找到你安裝的Qt Creator,打開它

如果安裝時,沒有選擇在桌面上建立快捷方式,那麼你的Qt軟件位置如下

C:\qt\Qt5.x.x\Tools\QtCreator\bin

在這個路徑下找到 qtcreator.exe 雙擊打開即可

2.2 按照嚮導創建項目

2.2.1 新建項目

點擊菜單 中的文件 -> 新建文件或項目 或者 在首頁面中點擊New Project

2.2.2 選擇模板

模板選擇 Application -> Qt Widget Application

2.2.3 項目名稱和位置

給項目起個名稱以及選中項目要保存的地方

這一步選擇後在Kits 構建套件中直接點擊下一步即可

2.2.4 類信息

基類選擇 QWidget

類名也就是我們第一個窗口場景的名稱,這裏我起名爲 MainScene 代表遊戲中的主場景

取消創建界面中的內容

2.2.5 完成創建

在彙總頁面中點擊完成,我們就邁開了項目的第一步!

3 設置主場景

​ 主場景設置的步驟如下:

  • 添加配置文件,保存遊戲中所有配置數據
  • 初始化主場景窗口大小、標題

3.1 配置文件添加

創建新的頭文件爲 config.h 主要記錄程序中所有的配置數據,方便後期修改

添加窗口寬度、高度的配置信息,依據背景圖大小進行設置

/**********  遊戲配置數據 **********/
#define GAME_WIDTH  512  //寬度
#define GAME_HEIGHT 768  //高度
#define GAME_TITLE "飛機大戰 v1.0" //標題

3.2 主場景基本設置

在mainScene.h中添加新的成員函數initScene 用來初始化遊戲場景

void  initScene();

在mainScene.cpp中實現如下代碼

void MainScene::initScene()
{
    //初始化窗口大小
    setFixedSize(GAME_WIDTH,GAME_HEIGHT);

    //設置窗口標題
    setWindowTitle(GAME_TITLE);
}

在構造函數MainScene中調用該函數 initScene

MainScene::MainScene(QWidget *parent)
    : QWidget(parent)
{
    //初始化場景
    initScene();
}

測試運行效果如圖:

4 資源導入

在主場景中其實還有一個配置項沒有實現,也就是窗口左上角的那個圖標資源

那麼接下來我們將遊戲中的資源進行導入並且設置遊戲圖標

資源導入步驟

  • 生成qrc文件
  • 項目同級目錄下創建res文件夾並將資源粘貼過來
  • 編輯qrc,加入前綴和文件
  • 利用qrc生成二進制文件 rcc
  • rcc文件放入到debug同級目錄下
  • 註冊二進制文件
  • 添加圖標資源

4.1 qrc文件生成

右鍵項目,點擊添加新文件

選擇Qt -> Qt Resource File

資源文件起名 如:res

生成res.qrc文件

4.2 創建res文件夾

項目的同級目錄下創建文件夾res,並將準備好的資源粘貼進去

4.3 編輯qrc文件

右鍵qrc文件,選中Open in Editor

添加前綴爲 '' \ ''

添加文件 將res下所有文件選中即可

4.4 qrc生成 rcc二進制文件

由於資源過大,會提示錯誤:

這個錯誤也就是“編譯器的堆空間不足”。

由於資源文件qrc過大,超出分配的內存範圍

因此我們需要利用二進制資源,而生成二進制資源就需要我們剛剛的qrc文件

利用cmd打開終端,定位到res.qrc的目錄下,輸入命令

rcc -binary .\res.qrc -o plane.rcc

4.5 複製rcc文件

將生成好的rcc文件,放入到debug同級目錄中一份

4.6 註冊二進制文件

在config.h中追加配置數據

#define GAME_RES_PATH  "./plane.rcc" //rcc文件路徑

在main.cpp中修改代碼

#include "mainscene.h"
#include <QApplication>
#include <QResource>
#include "config.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    //註冊外部的二進制資源文件
    QResource::registerResource(GAME_RES_PATH);

    MainScene w;
    w.show();

    return a.exec();
}

此時,qrc文件已經沒用了,刪除即可!

最簡單的刪除方式就是 .pro工程文件中刪除代碼,與工程無瓜葛

刪除以下代碼:
RESOURCES += \
    res.qrc

4.7 添加圖標資源

配置文件config.h中追加代碼

虛擬資源路徑語法如下:

" : + 前綴名 + 文件路徑 "
#define GAME_ICON  ":/res/app.ico"

在mainScene.cpp的 initScene函數中追加代碼:

//設置圖標資源
    setWindowIcon(QIcon( GAME_ICON));  //加頭文件 #include <QIcon>

運行測試:

5 地圖滾動

步驟:

  • 創建地圖文件和類
  • 添加成員函數和成員屬性 實現成員函數
  • 遊戲運行調用定時器
  • 啓動定時器,監聽定時器信號實現遊戲循環
  • 計算遊戲內元素座標
  • 繪製到屏幕中

5.1 創建地圖文件和類

​ 右鍵項目,添加新文件

選擇C++ -> C++ Class

修改類名爲map,點擊下一步,直到創建完畢

至此,地圖Map的文件和類創建完畢

5.2 地圖的成員函數和成員屬性

在map.h中添加如下代碼

#ifndef MAP_H
#define MAP_H
#include <QPixmap>

class Map
{
public:
    //構造函數
    Map();

    //地圖滾動座標計算
    void mapPosition();

public:

    //地圖圖片對象
    QPixmap m_map1;
    QPixmap m_map2;

    //地圖Y軸座標
    int m_map1_posY;
    int m_map2_posY;

    //地圖滾動幅度
    int m_scroll_speed;
};

#endif // MAP_H

5.3 實現成員函數

​ 在config.h中添加新的配置數據

/**********  地圖配置數據 **********/
#define MAP_PATH  ":/res/img_bg_level_1.jpg" //地圖圖片路徑
#define MAP_SCROLL_SPEED 2  //地圖滾動速度

在map.cpp中實現成員函數

#include "map.h"
#include "config.h"

Map::Map()
{
    //初始化加載地圖對象
    m_map1.load(MAP_PATH);
    m_map2.load(MAP_PATH);

    //設置地圖其實y軸座標
    m_map1_posY = -GAME_HEIGHT;
    m_map2_posY = 0;

    //設置地圖滾動速度
    m_scroll_speed = MAP_SCROLL_SPEED;
}

void Map::mapPosition()
{
    //處理第一張圖片滾動
    m_map1_posY += MAP_SCROLL_SPEED;
    if(m_map1_posY >= 0)
    {
        m_map1_posY =-GAME_HEIGHT;
    }

    //處理第二張圖片滾動
    m_map2_posY += MAP_SCROLL_SPEED;
    if(m_map2_posY >= GAME_HEIGHT )
    {
        m_map2_posY =0;
    }
}

5.4 定時器添加

在mainScene.h中添加新的定時器對象

QTimer m_Timer;

在 config.h中添加 屏幕刷新間隔

#define GAME_RATE  10   //刷新間隔,幀率 單位毫秒

在MainScene.cpp的initScene中追加代碼

//定時器設置
    m_Timer.setInterval(GAME_RATE);

5.5 啓動定時器實現地圖滾動

在MainScene.h中添加新的成員函數以及成員對象

//啓動遊戲  用於啓動定時器對象
    void playGame();
    //更新座標
    void updatePosition();
    //繪圖事件
    void paintEvent(QPaintEvent *event);

    //地圖對象
    Map m_map;

在MainScene.cpp中實現成員函數

void MainScene::playGame()
{
    //啓動定時器
    m_Timer.start();

    //監聽定時器
    connect(&m_Timer,&QTimer::timeout,[=](){
        //更新遊戲中元素的座標
        updatePosition();
        //重新繪製圖片
        update();
    });
}

void MainScene::updatePosition()
{
    //更新地圖座標
    m_map.mapPosition();
}

void MainScene::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    //繪製地圖
    painter.drawPixmap(0,m_map.m_map1_posY , m_map.m_map1);
    painter.drawPixmap(0,m_map.m_map2_posY , m_map.m_map2);
}

測試運行遊戲,實現地圖滾動

6 英雄飛機

步驟如下:

  • 創建英雄文件和類
  • 添加成員函數和成員屬性
  • 實現成員函數
  • 創建飛機對象並顯示
  • 拖拽飛機

6.1 創建英雄文件和類

創建HeroPlane類以及生成對應的文件

和創建地圖的步驟一樣,這裏就不在詳細截圖了

創建好後生成HeroPlane.h 和 HeroPlane.cpp兩個文件

6.2 飛機的成員函數和成員屬性

在HeroPlane.h中添加代碼

class HeroPlane
{
public:
    HeroPlane();

    //發射子彈
    void shoot();
    //設置飛機位置
    void setPosition(int x, int y);

public:
    //飛機資源 對象
    QPixmap m_Plane;

    //飛機座標
    int m_X;
    int m_Y;

    //飛機的矩形邊框
    QRect m_Rect;
};

6.3 成員函數實現

這裏飛機有個發射子彈的成員函數,由於我們還沒有做子彈

因此這個成員函數先寫成空實現即可

在config.h中追加飛機配置參數

/**********  飛機配置數據 **********/
#define HERO_PATH ":/res/hero2.png"

heroPlane.cpp中實現成員函數代碼:

#include "heroplane.h"
#include "config.h"

HeroPlane::HeroPlane()
{
    //初始化加載飛機圖片資源
    m_Plane.load(HERO_PATH);

    //初始化座標
    m_X = GAME_WIDTH * 0.5 - m_Plane.width()*0.5;
    m_Y = GAME_HEIGHT - m_Plane.height();

    //初始化矩形框
    m_Rect.setWidth(m_Plane.width());
    m_Rect.setHeight(m_Plane.height());
    m_Rect.moveTo(m_X,m_Y);

}

void HeroPlane::setPosition(int x, int y)
{
    m_X = x;
    m_Y = y;
    m_Rect.moveTo(m_X,m_Y);
}

void HeroPlane::shoot()
{

}

6.4 創建飛機對象並顯示

在MainScene.h中追加新的成員屬性

//飛機對象
    HeroPlane m_hero;

在MainScene.cpp的paintEvent中追加代碼

//繪製英雄
painter.drawPixmap(m_hero.m_X,m_hero.m_Y,m_hero.m_Plane);

測試飛機顯示到屏幕中

6.5 拖拽飛機

在MainScene.h中添加鼠標移動事件

//鼠標移動事件
    void mouseMoveEvent(QMouseEvent *event);

重寫鼠標移動事件

void MainScene::mouseMoveEvent(QMouseEvent *event)
{
    int x = event->x() - m_hero.m_Rect.width()*0.5; //鼠標位置 - 飛機矩形的一半
    int y = event->y() - m_hero.m_Rect.height()*0.5;

    //邊界檢測
    if(x <= 0 )
    {
        x = 0;
    }
    if(x >= GAME_WIDTH - m_hero.m_Rect.width())
    {
        x = GAME_WIDTH - m_hero.m_Rect.width();
    }
    if(y <= 0)
    {
        y = 0;
    }
    if(y >= GAME_HEIGHT - m_hero.m_Rect.height())
    {
        y = GAME_HEIGHT - m_hero.m_Rect.height();
    }
    m_hero.setPosition(x,y);
}

測試飛機可以拖拽

7 子彈製作

製作步驟如下:

  • 創建子彈文件和類
  • 添加子彈類中的成員函數和成員屬性
  • 實現成員函數
  • 測試子彈

7.1 創建子彈文件和類

創建Bullet類以及生成對應的文件

創建好後生成bullet.h 和 bullet.cpp兩個文件

7.2 子彈的成員函數和成員屬性

在Bullet.h中添加代碼

#ifndef BULLET_H
#define BULLET_H
#include "config.h"
#include <QPixmap>

class Bullet
{
public:
    Bullet();

    //更新子彈座標
    void updatePosition();

public:
    //子彈資源對象
    QPixmap m_Bullet;
    //子彈座標
    int m_X;
    int m_Y;
    //子彈移動速度
    int m_Speed;
    //子彈是否閒置
    bool m_Free;
    //子彈的矩形邊框(用於碰撞檢測)
    QRect m_Rect;
};

#endif // BULLET_H

7.3 子彈類成員函數實現

在config.h中追加子彈配置信息

/**********  子彈配置數據 **********/
#define BULLET_PATH ":/res/bullet_11.png"   //子彈圖片路徑
#define BULLET_SPEED 5  //子彈移動速度

在bullet.cpp中實現成員函數,代碼如下:

#include "bullet.h"

Bullet::Bullet()
{
    //加載子彈資源
    m_Bullet.load(BULLET_PATH);

    //子彈座標 初始座標可隨意設置,後期會重置
    m_X = GAME_WIDTH*0.5 - m_Bullet.width()*0.5;
    m_Y = GAME_HEIGHT;

    //子彈狀態
    m_Free = true;

    //子彈速度
    m_Speed = BULLET_SPEED;

    //子彈矩形框
    m_Rect.setWidth(m_Bullet.width());
    m_Rect.setHeight(m_Bullet.height());
    m_Rect.moveTo(m_X,m_Y);
}
void Bullet::updatePosition()
{
    //如果子彈是空閒狀態,不需要座標計算
    //玩家飛機可以控制子彈的空閒狀態爲false
    if(m_Free)
    {
        return;
    }

    //子彈向上移動
    m_Y  -= m_Speed;
    m_Rect.moveTo(m_X,m_Y);

    if(m_Y <= -m_Rect.height())
    {
        m_Free = true;
    }
}

7.4 測試子彈

子彈本身應該由飛機發射,測試階段我們寫一段輔助代碼,看看效果即可

測試過後,這些代碼可以刪除掉

在MainScene.h中添加測試代碼

//測試子彈代碼
    Bullet temp_bullet;

在MainScene.cpp中的updatePosition裏添加測試代碼

//測試子彈代碼
    temp_bullet.m_Free = false;
    temp_bullet.updatePosition();

在MainScene.cpp中的paintEvent裏添加測試代碼

//測試子彈代碼
    painter.drawPixmap(temp_bullet.m_X,temp_bullet.m_Y,temp_bullet.m_Bullet);

運行程序,此時會有一發子彈從屏幕中射出

測試完畢後,測試代碼刪除或註釋即可

8 玩家發射子彈

玩家發射子彈製作步驟如下:

  • 英雄飛機添加新的成員屬性
  • 實現發射成員函數
  • 主場景控制子彈發射

8.1 飛機添加新成員屬性

在config.h中添加新的配置數據

#define BULLET_NUM 30   //彈匣中子彈總數
#define BULLET_INTERVAL 20 //發射子彈時間間隔

在HeroPlane.h中新增成員屬性如下:

//彈匣
    Bullet m_bullets[BULLET_NUM];

    //發射間隔記錄
    int m_recorder;

8.2 成員函數補充

在構造函數 HeroPlane 中初始化發生間隔記錄

//初始化發射間隔記錄
    m_recorder = 0;

之前在英雄飛機類中預留的一個shoot函數我們進行實現,代碼如下:

void HeroPlane::shoot()
{
    //累加時間間隔記錄變量
    m_recorder++;
    //判斷如果記錄數字 未達到發射間隔,直接return
    if(m_recorder < BULLET_INTERVAL)
    {
        return;
    }
    //到達發射時間處理
    //重置發射時間間隔記錄
    m_recorder = 0;

    //發射子彈
    for(int i = 0 ; i < BULLET_NUM;i++)
    {
        //如果是空閒的子彈進行發射
        if(m_bullets[i].m_Free)
        {
            //將改子彈空閒狀態改爲假
            m_bullets[i].m_Free = false;
            //設置發射的子彈座標
            m_bullets[i].m_X = m_X + m_Rect.width()*0.5 - 10;
            m_bullets[i].m_Y = m_Y - 25 ;
            break;
        }
    }
}

8.3 主場景中實現發射子彈

在MainScene.cpp的updatePosition成員函數中追加如下代碼

//發射子彈
    m_hero.shoot();
    //計算子彈座標
    for(int i = 0 ;i < BULLET_NUM;i++)
    {
        //如果子彈狀態爲非空閒,計算髮射位置
        if(!m_hero.m_bullets[i].m_Free)
        {
            m_hero.m_bullets[i].updatePosition();
        }
    }

在MainScene.cpp的paintEvent成員函數中追加如下代碼:

//繪製子彈
    for(int i = 0 ;i < BULLET_NUM;i++)
    {
        //如果子彈狀態爲非空閒,計算髮射位置
        if(!m_hero.m_bullets[i].m_Free)
        {
            painter.drawPixmap(m_hero.m_bullets[i].m_X,m_hero.m_bullets[i].m_Y,m_hero.m_bullets[i].m_Bullet);
        }
    }

測試運行,玩家可以發射子彈

9 敵機制作

敵機制作與子彈製作原理類似,也是每隔一定的時間讓敵機出場

製作步驟如下:

  • 創建敵機文件和類
  • 添加敵機類中的成員函數和成員屬性
  • 實現成員函數
  • 敵機出場
  • 測試敵機

9.1 創建敵機文件和類

創建EnemyPlane類以及生成對應的文件

創建好後生成enemyPlane.h 和 enemyPlane.cpp兩個文件

9.2 敵機成員函數和成員屬性

在enemyPlane.h中添加如下代碼:

#ifndef ENEMYPLANE_H
#define ENEMYPLANE_H
#include <QPixmap>

class EnemyPlane
{
public:
    EnemyPlane();

    //更新座標
    void updatePosition();
public:
    //敵機資源對象
    QPixmap m_enemy;

    //位置
    int m_X;
    int m_Y;

    //敵機的矩形邊框(碰撞檢測)
    QRect m_Rect;

    //狀態
    bool m_Free;

    //速度
    int m_Speed;
};

#endif // ENEMYPLANE_H

9.3 敵機成員函數實現

在config.h中追加敵機配置信息

/**********  敵機配置數據 **********/
#define ENEMY_PATH  ":/res/img-plane_5.png"  //敵機資源圖片
#define ENEMY_SPEED 5  //敵機移動速度
#define ENEMY_NUM   20  //敵機總數量
#define ENEMY_INTERVAL  30  //敵機出場時間間隔

在enemyPlane.cpp中實現成員函數,代碼如下:

EnemyPlane::EnemyPlane()
{
    //敵機資源加載
    m_enemy.load(ENEMY_PATH);

    //敵機位置
    m_X = 0;
    m_Y = 0;

    //敵機狀態
    m_Free = true;

    //敵機速度
    m_Speed = ENEMY_SPEED;

    //敵機矩形
    m_Rect.setWidth(m_enemy.width());
    m_Rect.setHeight(m_enemy.height());
    m_Rect.moveTo(m_X,m_Y);
}

void EnemyPlane::updatePosition()
{
    //空閒狀態,不計算座標
    if(m_Free)
    {
        return;
    }

    m_Y += m_Speed;
    m_Rect.moveTo(m_X,m_Y);

    if(m_Y >= GAME_HEIGHT + m_Rect.height())
    {
        m_Free = true;
    }
}

9.4 敵機出場

在MainScene.h中追加敵機出場的成員函數

在MainScene.h中追加敵機數組 和 敵機出場間隔記錄 的成員屬性

//敵機出場
    void enemyToScene();    

    //敵機數組
    EnemyPlane m_enemys[ENEMY_NUM];

    //敵機出場間隔記錄
    int m_recorder;

初始化間隔記錄屬性,在MainScene.cpp的 initScene 成員函數中追加

m_recorder = 0;

實現成員函數 enemyToScene

void MainScene::enemyToScene()
{
    m_recorder++;
    if(m_recorder < ENEMY_INTERVAL)
    {
        return;
    }

    m_recorder = 0;

    for(int i = 0 ; i< ENEMY_NUM;i++)
    {
        if(m_enemys[i].m_Free)
        {
            //敵機空閒狀態改爲false
            m_enemys[i].m_Free = false;
            //設置座標
            m_enemys[i].m_X = rand() % (GAME_WIDTH - m_enemys[i].m_Rect.width());
            m_enemys[i].m_Y = -m_enemys[i].m_Rect.height();
            break;
        }
    }
}

在PlayGame成員函數的timeout信號發送時候,槽函數中首先追加 enemyToScene

//敵機出場
        enemyToScene();

更新敵機座標,在updatePosition成員函數中追加代碼

//敵機座標計算
    for(int i = 0 ; i< ENEMY_NUM;i++)
    {
        //非空閒敵機 更新座標
       if(m_enemys[i].m_Free == false)
       {
          m_enemys[i].updatePosition();
       }
    }

繪製敵機,在paintEvent成員函數中追加繪製敵機代碼

//繪製敵機
    for(int i = 0 ; i< ENEMY_NUM;i++)
    {
        if(m_enemys[i].m_Free == false)
        {
            painter.drawPixmap(m_enemys[i].m_X,m_enemys[i].m_Y,m_enemys[i].m_enemy);
        }
    }

添加隨機數種子

在MainScene.cpp中 initScene 成員函數裏添加隨機數種子

//隨機數種子
    srand((unsigned int)time(NULL));  //頭文件  #include <ctime>

運行測試敵機出場效果

10 碰撞檢測

實現碰撞檢測步驟如下:

  • 添加並實現碰撞檢測成員函數
  • 調用並測試函數

10.1 添加並實現碰撞檢測函數

在MainScene.h中添加新的成員函數

void collisionDetection();

在MainScene.cpp中實現該成員函數

void MainScene::collisionDetection()
{
    //遍歷所有非空閒的敵機
    for(int i = 0 ;i < ENEMY_NUM;i++)
    {
        if(m_enemys[i].m_Free)
        {
            //空閒飛機 跳轉下一次循環
            continue;
        }

        //遍歷所有 非空閒的子彈
        for(int j = 0 ; j < BULLET_NUM;j++)
        {
            if(m_hero.m_bullets[j].m_Free)
            {
                //空閒子彈 跳轉下一次循環
                continue;
            }

            //如果子彈矩形框和敵機矩形框相交,發生碰撞,同時變爲空閒狀態即可
            if(m_enemys[i].m_Rect.intersects(m_hero.m_bullets[j].m_Rect))
            {
                m_enemys[i].m_Free = true;
                m_hero.m_bullets[j].m_Free = true;
            }
        }
    }
}

10.2 調用並測試函數

在MainScene.cpp中 playGame成員函數裏,追加碰撞檢測代碼

運行查看效果,子彈和敵機碰撞後會同時消失

11 爆炸效果

爆炸效果功能實現步驟如下:

  • 創建爆炸文件和類
  • 添加爆炸類中的成員函數和成員屬性
  • 實現成員函數
  • 調用並測試效果

11.1 創建爆炸文件和類

創建Bomb類以及生成對應的文件

創建好後生成bomb.h 和 bomb.cpp兩個文件

11.2 爆炸成員函數和成員屬性

在config.h中加入爆炸配置數據

#define BOMB_PATH  ":/res/bomb-%1.png"   //爆炸資源圖片
#define BOMB_NUM  20     //爆炸數量
#define BOMB_MAX  7      //爆炸圖片最大索引
#define BOMB_INTERVAL 20   //爆炸切圖時間間隔

在bomb.h中添加如下代碼:

#ifndef BOMB_H
#define BOMB_H
#include "config.h"
#include <QPixmap>
#include <QVector>

class Bomb
{
public:
    Bomb();

    //更新信息(播放圖片下標、播放間隔)
    void updateInfo();

public:

    //放爆炸資源數組
    QVector<QPixmap> m_pixArr;

    //爆炸位置
    int m_X;
    int m_Y;

    //爆炸狀態
    bool m_Free;

    //爆炸切圖的時間間隔
    int m_Recoder;

    //爆炸時加載的圖片下標
    int m_index;
};

#endif // BOMB_H

11.3 實現成員函數

Bomb::Bomb()
{
    //初始化爆炸圖片數組
    for(int i = 1 ;i <= BOMB_MAX ;i++)
    {
        //字符串拼接,類似  ":/res/bomb-1.png"
        QString str = QString(BOMB_PATH).arg(i);
         m_pixArr.push_back(QPixmap(str));
    }

    //初始化座標
    m_X = 0;
    m_Y = 0;

    //初始化空閒狀態
    m_Free = true;

    //當前播放圖片下標
    m_index = 0;

    //爆炸間隔記錄
    m_Recoder = 0;
}

void Bomb::updateInfo()
{
    //空閒狀態
    if(m_Free)
    {
        return;
    }

    m_Recoder++;
    if(m_Recoder < BOMB_INTERVAL)
    {
        //記錄爆炸間隔未到,直接return,不需要切圖
        return;
    }
    //重置記錄
    m_Recoder = 0;

    //切換爆炸播放圖片
    m_index++;
    //注:數組中的下標從0開始,最大是6
    //如果計算的下標大於6,重置爲0
    if(m_index > BOMB_MAX-1)
    {
        m_index = 0;
        m_Free = true;
    }
}

11.4 加入爆炸數組

在MainScene.h中加入爆炸數組 成員屬性

//爆炸數組
    Bomb m_bombs[BOMB_NUM];

在碰撞檢測成員函數中,當發生碰撞時,設置爆炸對象的信息

//播放爆炸效果
                for(int k = 0 ; k < BOMB_NUM;k++)
                {
                    if(m_bombs[k].m_Free)
                    {
                        //爆炸狀態設置爲非空閒
                        m_bombs[k].m_Free = false;
                        //更新座標

                        m_bombs[k].m_X = m_enemys[i].m_X;
                        m_bombs[k].m_Y = m_enemys[i].m_Y;
                        break;
                    }
                }

在 MainScene.cpp的updatePosition中追加代碼

//計算爆炸播放的圖片
    for(int i = 0 ; i < BOMB_NUM;i++)
    {
        if(m_bombs[i].m_Free == false)
        {
           m_bombs[i].updateInfo();
        }
    }

在 MainScene.cpp的paintEvent 中追加繪製爆炸代碼

//繪製爆炸圖片
    for(int i = 0 ; i < BOMB_NUM;i++)
    {
        if(m_bombs[i].m_Free == false)
        {
           painter.drawPixmap(m_bombs[i].m_X,m_bombs[i].m_Y,m_bombs[i].m_pixArr[m_bombs[i].m_index]);
        }
    }

測試,實現爆炸效果

12 音效添加

音效添加步驟如下:

  • 添加多媒體模塊
  • 播放音效

12.1 添加多媒體模塊

在工程文件planeWar.pro 中修改代碼

QT  += core gui multimedia

12.2 播放音效

在config.h中 添加音效的配置路徑

#define SOUND_BACKGROUND ":/res/bg.wav"
#define SOUND_BOMB ":/res/bomb.wav"
注: QSound使用時候要包含頭文件 #include \

在PlayGame中添加背景音樂

//啓動背景音樂
    QSound::play(SOUND_BACKGROUND);

在爆炸時候添加爆炸音效

//播放音效
    QSound::play(SOUND_BOMB);

測試音效

13 打包發佈

  1. 確定環境變量配置好 PATH: C:\Qt\Qt5.x.x\5.x.x\mingw53_32\bin
  2. 在QT中把運行模式切換成 release 模式, 編譯。 在外層目錄中會有 release 版本的目錄. 
  3. 將目錄中的 rcc 二進制資源文件、可執行程序文件(.exe) 拷貝到另外一個單獨的文件夾中.
  4. 進入 cmd 命令模式,切換到可執行程序所在的目錄. 執行以下命令,將可執行程序所需的庫文件拷貝到當前目錄:
    c windeployqt PlaneWar.exe
  5. 額外可以將 ico 圖標也拷貝到當前可執行程序所在的目錄.
  6. 啓動 HM NIS EDIT 軟件,在軟件中選擇: 文件->新建腳本嚮導, 接下來跟着嚮導操作.
  7. 爲了讓安裝包安裝軟件也有快捷方式圖標,在生成的腳本里。進行修改:
    c CreateShortCut "$DESKTOP\飛機大戰.lnk" "$INSTDIR\PlaneWar.exe" CreateShortCut "$DESKTOP\飛機大戰.lnk" "$INSTDIR\PlaneWar.exe" "" "$INSTDIR\app.ico
  8. 點擊菜單欄的 NSIS ,然後選擇編譯,在桌面生成安裝包.
發佈了643 篇原創文章 · 獲贊 1315 · 訪問量 163萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章