用Qt設計自己的方塊遊戲
這個教程介紹方塊遊戲類的使用。教程共分三個部分。第一部分是簡介,讓你用最簡單的辦法實現自己的方塊遊戲。第二部分是功能展示,這裡通過一個例子對這個類的所有功能進行了演示。第三部分是遊戲分析,通過對介面函式的展示和對整個遊戲設計流程的分析,幫助你更好的理解原始碼。
需要說明的是:我們下面使用的程式設計環境是基於Qt 4.6的Qt Creator 1.3.0 Windows版本。這個類包含的四個檔案myitem.cpp, myitem.h ,gamearea.cpp ,gamearea.h 會和本教程打包在一起,你也可以到網上下載。
下載地址可以到我的部落格 http://hi.baidu.com/yafeilinux 進行檢視。
基於這個類我已經寫了一個範例遊戲:俄羅斯方塊勞拉版
可以到csdn下載:http://download.csdn.net/source/1866707
或到qt論壇下載:http://www.qtcn.org/bbs/read.php?tid=24169
第一部分:簡介
其實在Qt Creator中已經有了俄羅斯方塊的例子,大家可以在幫助中搜尋Tetrix進行檢視。其內容如下:
但是對於初學者,這個例子並不是那麼容易就能看懂。所以我結合這個例子和網上的一些資料,寫了一個比較簡單的方塊遊戲類。希望能幫助初學者更好的理解這個例子和寫出自己的方塊遊戲。
我這裡已經對所有的功能函式進行了整理,最簡單的,你只需要定義一個物件就能讓這個遊戲執行起來。
寫最簡單的遊戲
1. 新建Empty Qt4 Project,我們這裡命名為myTetrix 。
2. 向工程裡新增新的普通文字檔案,命名為main.cpp 。
3. 將myitem.cpp, myitem.h, gamearea.cpp, gamearea.h四個檔案複製到工程資料夾下。
4. 將上面四個檔案加入到工程中。
5. 將main.cpp的內容更改如下:
#include
#include "gamearea.cpp"
int main(int argc,char* argv[])
{
QApplication app(argc,argv);
GameArea box(500);
box.show();
return app.exec();
}
6.然後執行程式。效果如下圖。
當遊戲結束時會彈出提示框,確定後遊戲將重新開始。
如下圖所示。
7.可以看到,用這個類建立方塊遊戲是這麼的簡單。我們只是在主函式裡新建了一個該類的物件,其中的引數為方塊下移的速度,單位是毫秒,上面的500即0.5秒。
提示:
(如何向工程中新增檔案)
在工程資料夾上點右鍵,彈出的選單中Add New表示新增新檔案,Add Existing Files表示新增工程資料夾中已有的檔案。
第二部分:功能展示
要想實現更強大的功能,我們就需要應用控制窗體,而讓這個遊戲區域只作為它的一個部件。為了更好的控制遊戲,我們也需要自己建立定時器,而不再應用該類自帶的定時器了。
核心功能:
(一)建立工程。
1.首先建立工程Qt4 Gui Application,這裡命名為Tetris,選用QWidget作為Base class 。
2.然後將myitem.cpp, myitem.h ,gamearea.cpp, gamearea.h四個檔案複製到工程資料夾下並新增到工程中。
3.在widget.h中新增#include "gamearea.h"的標頭檔案包含。並在下面的private中宣告一個遊戲類物件GameArea *gameArea;
4.在widget.cpp的建構函式裡新增語句。
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
this->resize(800,500);
this->gameArea = new GameArea(this);
}
這裡重新設定了主視窗大小,並在主視窗上新建了一個遊戲區域物件。
5.這時執行程式效果如下。
可以看到,因為使用了另一個建構函式,沒有使用該類自帶的定時器,所以只是顯示了遊戲區域,遊戲並沒有執行。
(二)新增定時器和開始按鈕,讓遊戲可以執行。
1.在widget.h裡的private中新增定時器物件和分數變數的宣告。
QTimer *timer;
int score;
在public中新增顯示分數函式的宣告。
void doScore(int);
新增槽函式的宣告。
private slots:
void timer_upDate();
2.在widget.cpp檔案中的建構函式裡新增下面的語句:
this->timer = new QTimer(this);
connect(this->timer,SIGNAL(timeout()),this,SLOT(timer_upDate()));
score =0;
定義了定時器並進行了訊號和槽函式的關聯,初始化分數為0;
3.然後在下面定義兩個函式。
void Widget::timer_upDate() //定時器溢位處理
{
this->gameArea->moveOneStep(); //先移動一步,這時並沒有顯示出來
if(this->gameArea->isMoveEnd()) //如果無法移動,到底了或結束了
{
if(this->gameArea->isGame_Over()) //如果是結束了
{
this->timer->stop(); //停止計時
QMessageBox::warning(this,tr("warning"),tr("Game Over!"),QMessageBox::Yes);
//彈出對話方塊
this->score =0; //清空分數
this->gameArea->init_Game(); //重新開始遊戲
this->gameArea->gameStart();
this->timer->start(500);
}
else //如果是移動到底了
{
this->gameArea->nextItem(); //出現下一個圖形
int num = this->gameArea->getFullRowNum(); //獲得已滿的行數
this->doScore(num); //顯示分數
this->gameArea->gameStart(); //繼續遊戲
}
}
else //如果沒有到底
{
this->gameArea->do_MoveNext(); //顯示方塊下移一步後的介面
}
}
void Widget::doScore(int num) //顯示分數
{
score += num*100;
this->ui->label_2->setText(tr("%1").arg(score));
}
4.在設計器中向主視窗上新增兩個標籤label和label_2,其中label寫上“你的分數是:”,label_2寫上“0”;然後再新增一個開始按鈕。新增完後效果如下。
5.然後右擊“開始遊戲”按鈕,選擇其單擊事件的槽函式。更改如下。
void Widget::on_pushButton_clicked() //開始按鈕
{
this->gameArea->init_Game(); //第一次進入遊戲時進行的初始化
this->gameArea->gameStart(); //開始遊戲
this->timer->start(500); //開啟定時器
this->gameArea->setFocus(); //讓遊戲區域獲得焦點,這樣才能響應鍵盤
}
6.現在遊戲已經可以正常進行了。執行效果如下。
(三)新增暫停和重新開始按鈕,完成基本的控制功能。
1.在主視窗上新增“暫停遊戲”和“重新開始”兩個按鈕。在“暫停遊戲”按鈕的屬性中將checkable選中。如下圖所示。
2.分別進入兩個按鈕的單擊事件槽函式。修改如下。
void Widget::on_pushButton_2_clicked() //暫停按鈕
{
if(this->ui->pushButton_2->isChecked())
{
this->timer->stop();
this->ui->pushButton_2->setText(tr("取消暫停"));
}
else
{
this->timer->start(500);
this->ui->pushButton_2->setText(tr("暫停遊戲"));
this->gameArea->setFocus();
}
}
void Widget::on_pushButton_3_clicked() //重新開始
{
this->timer->stop();
this->on_pushButton_clicked();
}
3.在main.cpp中新增語句,讓程式中可以使用中文。
新增#include 的標頭檔案包含。
在main()函式裡新增QTextCodec::setCodecForTr(QTextCodec::codecForLocale());語句。
4.程式執行效果如下。
高階功能的應用
(一)改變顏色和給方塊新增圖片。
1.新增“更改顏色”按鈕和“方塊貼圖”按鈕。如下圖。
2.更改其單擊事件槽函式。如下。
void Widget::on_pushButton_4_clicked() //改變顏色
{
this->gameArea->setGameAreaColor(QColor(255,255,0,qrand()%255));
//更改遊戲區域背景顏色
this->gameArea->setBoxBrushColor(QColor(0,255,0,qrand()%255));
//更改小方塊背景顏色
this->gameArea->setBoxPenColor(QColor(0,0,0,qrand()%255));
//更改小方塊邊框顏色
this->gameArea->draw_gameArea();
//更新遊戲區域
this->gameArea->setFocus();
}
void Widget::on_pushButton_5_clicked() //方塊貼圖
{
this->gameArea->set_draw_box_picture(true);
//確認使用方塊背景圖片
this->gameArea->setBoxPicture("box.gif");
//新增方塊背景圖片
this->gameArea->draw_gameArea();
//更新顯示區域
this->gameArea->setFocus();
}
3.執行效果如下。
點選“改變背景”按鈕後,遊戲區域背景,方塊的填充顏色和邊框顏色都改變了。
點選“方塊貼圖”按鈕。注意,只有方塊顏色的透明度不是255時,才能看見貼圖。所以,如果開始遊戲後直接按“方塊貼圖”按鈕,是不能顯示出背景圖片的,我們需要先改變顏色。
(二)是否顯示背景網格和下一個要出現的方塊。
1.新增“網格顯示”按鈕和“方塊提示”按鈕。並將它們屬性中的checkable選中。介面如下。
2.修改它們的單擊事件槽函式。
void Widget::on_pushButton_6_clicked() //網格顯示
{
if(this->ui->pushButton_6->isChecked())
{
this->gameArea->setDrawGrid(false);
}
else
{
this->gameArea->setDrawGrid(true);
}
this->gameArea->draw_gameArea();
this->gameArea->setFocus();
}
void Widget::on_pushButton_7_clicked() //方塊提示
{
if(this->ui->pushButton_7->isChecked())
{
this->gameArea->setDrawNextItem(false);
}
else
{
this->gameArea->setDrawNextItem(true);
}
this->gameArea->draw_gameArea();
this->gameArea->setFocus();
}
3.執行效果如下。
(三)新增方塊移動的聲音。
1.新增“開啟聲音”按鈕,並將其屬性中的checkable選中。
2.修改其單擊事件槽函式。
void Widget::on_pushButton_8_clicked() //聲音開關
{
if(this->ui->pushButton_8->isChecked())
{
this->gameArea->setPlaySound_itemChange("changeItem.wav",true);
this->gameArea->setPlaySound_moveDown("moveDown.wav",true);
this->gameArea->setPlaySound_moveLeft("moveLeft.wav",true);
this->gameArea->setPlaySound_moveRight("moveLeft.wav",true);
this->ui->pushButton_8->setText(tr("關閉聲音"));
}
else
{
this->gameArea->setPlaySound(false); //關閉音樂
this->ui->pushButton_8->setText(tr("開啟聲音"));
}
this->gameArea->setFocus();
}
3.我們把需要的聲音檔案放到工程資料夾下的debug資料夾下。注意:只能是wav格式的。然後執行程式,測試一下效果。
(四)新增向下按鍵移動步數設定。
1.新增“是否墜落”按鈕,並將其屬性中的checkable選中。
2.更改其單擊事件槽函式。
void Widget::on_pushButton_9_clicked() //是否墜落
{
if(this->ui->pushButton_9->isChecked())
{
this->gameArea->setKey_Down_Move_oneStep(true);
//按一下向下方向鍵,下移一步
}
else
{
this->gameArea->setKey_Down_Move_oneStep(false);
//按一下向下方向鍵,移動到底
}
this->gameArea->setFocus();
}
3.執行程式,測試一下效果。
(五)自己新增方塊。
1.新增“新增方塊”按鈕。
2.修改其單擊事件槽函式。
void Widget::on_pushButton_10_clicked() //新增方塊
{
this->gameArea->init_Game();
//清空遊戲區域
this->gameArea->setbox(10,4);
this->gameArea->setbox(10,5);
this->gameArea->setbox(10,6);
//在第10行第4,5,6列新增三個方塊
this->gameArea->gameStart();
//重新開始遊戲
this->gameArea->draw_gameArea();
this->gameArea->setFocus();
}
3.執行程式,效果如下。
(六)設定旋轉游戲區。
1.新增“旋轉游戲”按鈕。
2.修改其單擊事件槽函式。
void Widget::on_pushButton_11_clicked() //旋轉游戲
{
this->gameArea->setRotate(true);
//開啟旋轉
this->gameArea->setGameAreaPixOrigin(100,200);
//設定遊戲區域新的座標原點
this->gameArea->setGameAreaPix(-100,-200);
//設定遊戲區域的位置
this->gameArea->setRotateAngle(qrand()%360);
//旋轉度數
this->gameArea->draw_gameArea();
this->gameArea->setFocus();
}
3.執行程式,效果如下。
第三部分:遊戲分析
(一)可被外部呼叫的功能函式的原型。
GameArea(QWidget *parent = 0); //不帶定時器的建構函式
GameArea(int speed,QWidget *parent = 0); //帶定時器的建構函式
//以下是核心功能控制函式
void init_gameArea(int X,int Y,int frame_width,int frame_height,int width,int height,int boxStep,int start_x,int start_y);
void moveOneStep();
bool isMoveEnd();
bool isGame_Over();
void init_Game();
void gameStart();
void nextItem();
int getFullRowNum();
void do_MoveNext();
void draw_gameArea();
//以下是設定顏色函式
void setGameAreaColor(QColor color=Qt::white);
void setBoxBrushColor(QColor color=Qt::green);
void setBoxPenColor(QColor color=Qt::black);
void set_draw_box_picture(bool Bool=false);
void setBoxPicture(QString fileName);
//以下是設定聲音函式
void setPlaySound_moveLeft(QString fileName,bool Bool=false);
void setPlaySound_moveRight(QString fileName,bool Bool=false);
void setPlaySound_moveDown(QString fileName,bool Bool=false);
void setPlaySound_itemChange(QString fileName,bool Bool=false);
void setPlaySound(bool Bool=false);
//以下是設定遊戲區域旋轉函式
void setRotate(bool Bool=false);
void setGameAreaPixOrigin(int x,int y);
void setGameAreaPix(int x,int y);
void setRotateAngle(int angle);
//以下是其他功能函式
void setKey_Down_Move_oneStep(bool Bool = false);
void setDrawGrid(bool Bool = true);
void setDrawNextItem(bool Bool =true);
void setbox(int row,int col);
(二)遊戲流程分析。
這裡共有四個檔案myitem.cpp ,myitem.h, gamearea.cpp, gamearea.h
其中myitem.cpp, myitem.h是方塊類的定義檔案,它用來提供隨機產生的方塊。
gamearea.cpp, gamearea.h是遊戲區域類的定義檔案,它實現了遊戲的所有功能。
為了幫助大家更好的理解原始碼,我們這裡描述一下游戲的實現流程。
難點解析:
1. 遊戲實現的核心方法是什麼?
這裡是利用了陣列對整個遊戲區域進行儲存。
2. 遊戲是怎麼實現顯示現在和已有的圖形的?
這裡利用了兩個陣列,方塊每移動一步,都對整個陣列進行一次備份。
3. 遊戲是怎麼判斷方塊已經重合的?
這裡是先嚐試讓方塊移動一步,判斷其是否與其他圖形重合,如果不重合就移動。如果重合了,就進行其他操作。
4. 遊戲是怎麼進行消行的?
這裡是讓已滿的行和它上面的所有的行均等於其上面的一行。
到這裡整篇教程就結束了。這個方塊遊戲類還有很多功能不太完善,為了使程式碼更容易理解,也捨去了一些功能,例如讓不同方塊顯示不同的顏色等。大家可以參考Qt自帶的例程進行完善,也很希望大家對這個類的原始碼進行修改和完善。
最後,如果你喜歡我的寫作風格,並且初學Qt,可以在我的空間檢視Qt Creator系列教程,希望能對你的入門有所幫助。
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/yafeilinux/archive/2009/12/21/5049945.aspx
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22785983/viewspace-662967/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- D. 方塊遊戲遊戲
- C/C++ Qt Dialog 對話方塊元件應用C++QT元件
- Tetris 俄羅斯方塊遊戲遊戲
- Qt 對話方塊新增工具欄QT
- 用 SQL 寫的俄羅斯方塊遊戲「GitHub 熱點速覽」SQL遊戲Github
- 【Java遊戲】java俄羅斯方塊!Java遊戲
- 《暗黑3》設計師是如何評價自己遊戲中陷阱的設計?遊戲
- 如何搭建自己的遊戲設計框架之左右互搏術遊戲設計框架
- C/C++ Qt 自定義Dialog對話方塊元件應用C++QT元件
- 如何自學qt(4)——對話方塊QT
- 基於Flutter的俄羅斯方塊小遊戲Flutter遊戲
- 用Unity開發一款塔防遊戲(一):攻擊方設計Unity遊戲
- 從邏輯觸發,講講如何設計自己的遊戲遊戲
- 遊戲設計裡的那些色彩應用遊戲設計
- 俄羅斯方塊聯機小遊戲的實現遊戲
- 《水晶危機》:手感極佳的方塊對戰遊戲遊戲
- Python 實戰開發俄羅斯方塊遊戲Python遊戲
- 基於MonoGame重製《俄羅斯方塊》遊戲MonoGAM遊戲
- 【遊戲設計隨筆10】解密遊戲設計的30堂課遊戲設計解密
- 遊戲文件與遊戲設計遊戲設計
- 幀同步遊戲的設計遊戲
- MDA:一種用於遊戲設計和研究的方法遊戲設計
- 【遊戲設計】從“通關率”檢驗遊戲設計遊戲設計
- 遊戲圖示的設計跟其它應用的圖示設計有何不同?遊戲
- 遊戲UX設計:地圖設計的考量遊戲UX地圖
- C++ Qt開發:標準Dialog對話方塊元件C++QT元件
- C++ Qt開發:自定義Dialog對話方塊元件C++QT元件
- 使用C#和MonoGame開發俄羅斯方塊遊戲C#MonoGAM遊戲
- 女扮男裝?性轉西施? 乙女遊戲《與君盟》簽約方塊遊戲遊戲
- 遊戲設計方法論——非玄學的遊戲設計知識譜系遊戲設計
- 如何根據自己的需要培養遊戲開發技能?又一篇遊戲程式設計入門指南遊戲開發程式設計
- 全景探祕遊戲設計藝術(1):遊戲設計師遊戲設計師
- 用JS實現方塊碰撞JS
- 無心插柳——ZUN和“東方Project”對遊戲女性角色設計的影響Project遊戲
- 【遊戲設計】淺談快速反應事件(QTE)的應用遊戲設計事件QT
- 遊戲機制設計:資源管理挑戰與遊戲中的AI設計遊戲AI
- 一名遊戲設計師的思考——遊戲性遊戲設計師
- 遊戲設計-Roguelike類遊戲的一些思考遊戲設計
- 遊戲戰鬥的設計分析遊戲