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

1 項目簡介

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

首先我們看一下效果圖

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

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

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

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

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

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

2.2.2 選擇模板

模板選擇 Application -> Qt Widget Application

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

2.2.3 項目名稱和位置

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

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

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

2.2.4 類信息

基類選擇 QWidget

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

取消創建界面中的內容

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

2.2.5 完成創建

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

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

3 設置主場景

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

添加配置文件,保存遊戲中所有配置數據

初始化主場景窗口大小、標題

3.1 配置文件添加

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

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

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

3.2 主場景基本設置

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

<code>void  initScene();/<code>

在mainScene.cpp中實現如下代碼

<code>void MainScene::initScene()/<code>
<code>{/<code>
<code>    //初始化窗口大小/<code>
<code>    setFixedSize(GAME_WIDTH,GAME_HEIGHT);/<code>
<code> /<code>
<code>    //設置窗口標題/<code>
<code>    setWindowTitle(GAME_TITLE);/<code>
<code>}/<code>

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

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

測試運行效果如圖:

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

4 資源導入

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

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

資源導入步驟

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

4.1 qrc文件生成

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

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

選擇Qt -> Qt Resource File

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

資源文件起名 如:res

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

生成res.qrc文件

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

4.2 創建res文件夾

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

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

右鍵qrc文件,選中Open in Editor

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

添加前綴為 '' \\ ''

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

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

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

4.4 qrc生成 rcc二進制文件

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

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

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

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

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

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

<code>rcc -binary .\\res.qrc -o plane.rcc/<code>
C++學習教程,QT飛機大戰教程上(含詳細步驟教程)

4.5 複製rcc文件

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

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

4.6 註冊二進制文件

在config.h中追加配置數據

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

在main.cpp中修改代碼

<code>#include "mainscene.h"/<code>
<code>#include <qapplication>/<code>
<code>#include <qresource>/<code>
<code>#include "config.h"/<code>
<code> /<code>
<code>int main(int argc, char *argv[])/<code>
<code>{/<code>
<code>    QApplication a(argc, argv);/<code>
<code> /<code>
<code>    //註冊外部的二進制資源文件/<code>
<code>    QResource::registerResource(GAME_RES_PATH);/<code>
<code> /<code>
<code>    MainScene w;/<code>
<code>    w.show();/<code>
<code> /<code>
<code>    return a.exec();/<code>
<code>}/<code>

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

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

刪除以下代碼:

<code>RESOURCES += \\/<code>
<code>    res.qrc/<code>

4.7 添加圖標資源

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

虛擬資源路徑語法如下:

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

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

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

運行測試:

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

5 地圖滾動

步驟:

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

5.1 創建地圖文件和類

​ 右鍵項目,添加新文件

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

選擇C++ -> C++ Class

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

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

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

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

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

在map.h中添加如下代碼

<code>#ifndef MAP_H/<code>
<code>#define MAP_H/<code>
<code>#include <qpixmap>/<code>
<code> /<code>
<code>class Map/<code>
<code>{/<code>
<code>public:/<code>
<code>    //構造函數/<code>
<code>    Map();/<code>
<code> /<code>
<code>    //地圖滾動座標計算/<code>
<code>    void mapPosition();/<code>
<code> /<code>
<code>public:/<code>
<code> /<code>
<code>    //地圖圖片對象/<code>
<code>    QPixmap m_map1;/<code>
<code>    QPixmap m_map2;/<code> 
<code> /<code>
<code>    //地圖Y軸座標/<code>
<code>    int m_map1_posY;/<code>
<code>    int m_map2_posY;/<code>
<code> /<code>
<code>    //地圖滾動幅度/<code>
<code>    int m_scroll_speed;/<code>
<code>};/<code>
<code> /<code>
<code>#endif // MAP_H/<code>

5.3 實現成員函數

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

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

在map.cpp中實現成員函數

<code>#include "map.h"/<code>
<code>#include "config.h"/<code>
<code> /<code>
<code>Map::Map()/<code>
<code>{/<code>
<code>    //初始化加載地圖對象/<code>
<code>    m_map1.load(MAP_PATH);/<code>
<code>    m_map2.load(MAP_PATH);/<code>
<code> /<code>
<code>    //設置地圖其實y軸座標/<code>
<code>    m_map1_posY = -GAME_HEIGHT;/<code>
<code>    m_map2_posY = 0;/<code>
<code> /<code>
<code>    //設置地圖滾動速度/<code>
<code>    m_scroll_speed = MAP_SCROLL_SPEED;/<code>
<code>}/<code>
<code> /<code>
<code>void Map::mapPosition()/<code>
<code>{/<code>
<code>    //處理第一張圖片滾動/<code>
<code>    m_map1_posY += MAP_SCROLL_SPEED;/<code>
<code>    if(m_map1_posY >= 0)/<code>
<code>    {/<code>
<code>        m_map1_posY =-GAME_HEIGHT;/<code>
<code>    }/<code>
<code> /<code>
<code>    //處理第二張圖片滾動/<code>
<code>    m_map2_posY += MAP_SCROLL_SPEED;/<code>
<code>    if(m_map2_posY >= GAME_HEIGHT )/<code>
<code>    {/<code>
<code>        m_map2_posY =0;/<code>
<code>    }/<code>
<code>}/<code>

5.4 定時器添加

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

<code>QTimer m_Timer;/<code>

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

<code>define GAME_RATE  10   //刷新間隔,幀率 單位毫秒/<code>

在MainScene.cpp的initScene中追加代碼

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

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

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

<code>//啟動遊戲  用於啟動定時器對象/<code>
<code>    void playGame();/<code>
<code>    //更新座標/<code>
<code>    void updatePosition();/<code> 
<code>    //繪圖事件/<code>
<code>    void paintEvent(QPaintEvent *event);/<code>
<code> /<code>
<code>    //地圖對象/<code>
<code>    Map m_map;/<code>

在MainScene.cpp中實現成員函數

<code>void MainScene::playGame()/<code>
<code>{/<code>
<code>    //啟動定時器/<code>
<code>    m_Timer.start();/<code>
<code> /<code>
<code>    //監聽定時器/<code>
<code>    connect(&m_Timer,&QTimer::timeout,[=](){/<code>
<code>        //更新遊戲中元素的座標/<code>
<code>        updatePosition();/<code>
<code>        //重新繪製圖片/<code>
<code>        update();/<code>
<code>    });/<code>
<code>}/<code>
<code> /<code>
<code>void MainScene::updatePosition()/<code>
<code>{/<code>
<code>    //更新地圖座標/<code> 
<code>    m_map.mapPosition();/<code>
<code>}/<code>
<code> /<code>
<code>void MainScene::paintEvent(QPaintEvent *event)/<code>
<code>{/<code>
<code>    QPainter painter(this);/<code>
<code> /<code>
<code>    //繪製地圖/<code>
<code>    painter.drawPixmap(0,m_map.m_map1_posY , m_map.m_map1);/<code>
<code>    painter.drawPixmap(0,m_map.m_map2_posY , m_map.m_map2);/<code>
<code>}/<code>

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

6 英雄飛機

步驟如下:

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

6.1 創建英雄文件和類

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

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

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

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

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

在HeroPlane.h中添加代碼

<code>class HeroPlane/<code>
<code>{/<code>
<code>public:/<code>
<code>    HeroPlane();/<code>
<code> /<code>
<code>    //發射子彈/<code>
<code>    void shoot();/<code>
<code>    //設置飛機位置/<code>
<code>    void setPosition(int x, int y);/<code>
<code> /<code>
<code>public:/<code>
<code>    //飛機資源 對象/<code>
<code>    QPixmap m_Plane;/<code>
<code> /<code>
<code>    //飛機座標/<code>
<code>    int m_X;/<code>
<code>    int m_Y;/<code>
<code> /<code>
<code>    //飛機的矩形邊框/<code>
<code>    QRect m_Rect;/<code>
<code>};/<code>

6.3 成員函數實現

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

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

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

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

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

<code>#include "heroplane.h"/<code>
<code>#include "config.h"/<code>
<code> /<code>
<code>HeroPlane::HeroPlane()/<code>
<code>{/<code>
<code>    //初始化加載飛機圖片資源/<code>
<code>    m_Plane.load(HERO_PATH);/<code>
<code> /<code>
<code>    //初始化座標/<code>
<code>    m_X = GAME_WIDTH * 0.5 - m_Plane.width()*0.5;/<code>
<code>    m_Y = GAME_HEIGHT - m_Plane.height();/<code>
<code> /<code>
<code>    //初始化矩形框/<code>
<code>    m_Rect.setWidth(m_Plane.width());/<code>
<code>    m_Rect.setHeight(m_Plane.height());/<code> 
<code>    m_Rect.moveTo(m_X,m_Y);/<code>
<code> /<code>
<code>}/<code>
<code> /<code>
<code>void HeroPlane::setPosition(int x, int y)/<code>
<code>{/<code>
<code>    m_X = x;/<code>
<code>    m_Y = y;/<code>
<code>    m_Rect.moveTo(m_X,m_Y);/<code>
<code>}/<code>
<code> /<code>
<code>void HeroPlane::shoot()/<code>
<code>{/<code>
<code> /<code>
<code>}/<code>

6.4 創建飛機對象並顯示

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

<code>//飛機對象/<code>
<code>    HeroPlane m_hero;/<code>

在MainScene.cpp的paintEvent中追加代碼

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

測試飛機顯示到屏幕中

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

6.5 拖拽飛機

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

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

重寫鼠標移動事件

<code>void MainScene::mouseMoveEvent(QMouseEvent *event)/<code>
<code>{/<code>
<code>    int x = event->x() - m_hero.m_Rect.width()*0.5; //鼠標位置 - 飛機矩形的一半/<code>
<code>    int y = event->y() - m_hero.m_Rect.height()*0.5;/<code>
<code> /<code>
<code>    //邊界檢測/<code>
<code>    if(x <= 0 )/<code>
<code>    {/<code>
<code>        x = 0;/<code>
<code>    }/<code>
<code>    if(x >= GAME_WIDTH - m_hero.m_Rect.width())/<code>
<code>    {/<code>
<code>        x = GAME_WIDTH - m_hero.m_Rect.width();/<code>
<code>    }/<code>
<code>    if(y <= 0)/<code>
<code>    {/<code>
<code>        y = 0;/<code>
<code>    }/<code>
<code>    if(y >= GAME_HEIGHT - m_hero.m_Rect.height())/<code>
<code>    {/<code>
<code>        y = GAME_HEIGHT - m_hero.m_Rect.height();/<code>
<code>    }/<code>
<code>    m_hero.setPosition(x,y);/<code>
<code>}/<code>

測試飛機可以拖拽

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


由於篇幅過長,因此分為兩篇文章發佈。


分享到:


相關文章: