使用Qt開發(fā)俄羅斯方塊游戲
使用Qt開發(fā)俄羅斯方塊游戲,可能大家都比較感興趣吧。那么就快看下面的詳細講解吧!
其實在Qt Creator中已經(jīng)有了俄羅斯方塊的例子,大家可以在幫助中搜索Tetrix進行查看。其內(nèi)容如下:
但是對于初學者,這個例子并不是那么容易就能看懂。所以我結合這個例子和網(wǎng)上的一些資料,寫了一個比較簡單的方塊游戲類。希望能幫助初學者更好的理解這個例子和寫出自己的方塊游戲。
我這里已經(jīng)對所有的功能函數(shù)進行了整理,最簡單的,你只需要定義一個對象就能讓這個游戲運行起來。
寫最簡單的游戲
1. 新建Empty Qt4 Project,我們這里命名為myTetrix 。
2. 向工程里添加新的普通文本文件,命名為main.cpp 。
3. 將myitem.cpp, myitem.h, gamearea.cpp, gamearea.h四個文件復制到工程文件夾下。
4. 將上面四個文件加入到工程中。
5. 將main.cpp的內(nèi)容更改如下:
- #include
- #include "gamearea.cpp"
- int main(int argc,char* argv[])
- {
- QApplication app(argc,argv);
- GameArea box(500);
- box.show();
- return app.exec();
- }
6.然后運行程序。效果如下圖。
當游戲結束時會彈出提示框,確定后游戲將重新開始。
如下圖所示。
7.可以看到,用這個類建立方塊游戲是這么的簡單。我們只是在主函數(shù)里新建了一個該類的對象,其中的參數(shù)為方塊下移的速度,單位是毫秒,上面的500即0.5秒。
提示:(如何向工程中添加文件)
在工程文件夾上點右鍵,彈出的菜單中Add New表示添加新文件,Add Existing Files表示添加工程文件夾中已有的文件。
#p#
功能展示
要想實現(xiàn)更強大的功能,我們就需要應用控制窗體,而讓這個游戲區(qū)域只作為它的一個部件。為了更好的控制游戲,我們也需要自己建立定時器,而不再應用該類自帶的定時器了。
核心功能:
(一)建立工程。
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的構造函數(shù)里添加語句。
- Widget::Widget(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::Widget)
- {
- ui->setupUi(this);
- this->resize(800,500);
- this->gameArea = new GameArea(this);
- }
這里重新設定了主窗口大小,并在主窗口上新建了一個游戲區(qū)域對象。
5.這時運行程序效果如下。
可以看到,因為使用了另一個構造函數(shù),沒有使用該類自帶的定時器,所以只是顯示了游戲區(qū)域,游戲并沒有運行。
(二)添加定時器和開始按鈕,讓游戲可以運行。
1.在widget.h里的private中添加定時器對象和分數(shù)變量的聲明。
- QTimer *timer;
- int score;
在public中添加顯示分數(shù)函數(shù)的聲明。
- void doScore(int);
添加槽函數(shù)的聲明。
- private slots:
- void timer_upDate();
2.在widget.cpp文件中的構造函數(shù)里添加下面的語句:
- this->timer = new QTimer(this);
- connect(this->timer,SIGNAL(timeout()),this,SLOT(timer_upDate()));
- score =0;
定義了定時器并進行了信號和槽函數(shù)的關聯(lián),初始化分數(shù)為0;
3.然后在下面定義兩個函數(shù)。
- 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; //清空分數(shù)
- this->gameArea->init_Game(); //重新開始游戲
- this->gameArea->gameStart();
- this->timer->start(500);
- }
- else //如果是移動到底了
- this->gameArea->nextItem(); //出現(xiàn)下一個圖形
- int num = this->gameArea->getFullRowNum(); //獲得已滿的行數(shù)
- this->doScore(num); //顯示分數(shù)
- this->gameArea->gameStart(); //繼續(xù)游戲
- }
- }
- else //如果沒有到底
- {
- this->gameArea->do_MoveNext(); //顯示方塊下移一步后的界面
- }
- }
- void Widget::doScore(int num) //顯示分數(shù)
- {
- score += num*100;
- this->ui->label_2->setText(tr("%1").arg(score));
- }
4.在設計器中向主窗口上添加兩個標簽label和label_2,其中l(wèi)abel寫上“你的分數(shù)是:”,label_2寫上“0”;然后再添加一個開始按鈕。添加完后效果如下。
5.然后右擊“開始游戲”按鈕,選擇其單擊事件的槽函數(shù)。更改如下。
- void Widget::on_pushButton_clicked() //開始按鈕
- {
- this->gameArea->init_Game(); //第一次進入游戲時進行的初始化
- this->gameArea->gameStart(); //開始游戲
- this->timer->start(500); //開啟定時器
- this->gameArea->setFocus(); //讓游戲區(qū)域獲得焦點,這樣才能響應鍵盤
- }
6.現(xiàn)在游戲已經(jīng)可以正常進行了。運行效果如下。
#p#
(三)添加暫停和重新開始按鈕,完成基本的控制功能。
1.在主窗口上添加“暫停游戲”和“重新開始”兩個按鈕。在“暫停游戲”按鈕的屬性中將checkable選中。如下圖所示。
2.分別進入兩個按鈕的單擊事件槽函數(shù)。修改如下。
- 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()函數(shù)里添加QTextCodec::setCodecForTr(QTextCodec::codecForLocale());語句。
4.程序運行效果如下。
高級功能的應用
(一)改變顏色和給方塊添加圖片。
1.添加“更改顏色”按鈕和“方塊貼圖”按鈕。如下圖。
2.更改其單擊事件槽函數(shù)。如下。
- void Widget::on_pushButton_4_clicked() //改變顏色
- {
- this->gameArea->setGameAreaColor(QColor(255,255,0,qrand()%255));
- //更改游戲區(qū)域背景顏色
- this->gameArea->setBoxBrushColor(QColor(0,255,0,qrand()%255));
- //更改小方塊背景顏色
- this->gameArea->setBoxPenColor(QColor(0,0,0,qrand()%255));
- //更改小方塊邊框顏色
- this->gameArea->draw_gameArea();
- //更新游戲區(qū)域
- this->gameArea->setFocus();
- http://fund.eastmoney.com/dwjz.html
- }
- void Widget::on_pushButton_5_clicked() //方塊貼圖
- {
- this->gameArea->set_draw_box_picture(true);
- //確認使用方塊背景圖片
- this->gameArea->setBoxPicture("box.gif");
- //添加方塊背景圖片
- this->gameArea->draw_gameArea();
- //更新顯示區(qū)域
- this->gameArea->setFocus();
- }
3.運行效果如下。
點擊“改變背景”按鈕后,游戲區(qū)域背景,方塊的填充顏色和邊框顏色都改變了。
點擊“方塊貼圖”按鈕。注意,只有方塊顏色的透明度不是255時,才能看見貼圖。所以,如果開始游戲后直接按“方塊貼圖”按鈕,是不能顯示出背景圖片的,我們需要先改變顏色。
#p#
(二)是否顯示背景網(wǎng)格和下一個要出現(xiàn)的方塊。
1.添加“網(wǎng)格顯示”按鈕和“方塊提示”按鈕。并將它們屬性中的checkable選中。界面如下。
2.修改它們的單擊事件槽函數(shù)。
- void Widget::on_pushButton_6_clicked() //網(wǎng)格顯示
- {
- 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.修改其單擊事件槽函數(shù)。
- 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格式的。然后運行程序,測試一下效果。
(四)添加向下按鍵移動步數(shù)設置。
1.添加“是否墜落”按鈕,并將其屬性中的checkable選中。
2.更改其單擊事件槽函數(shù)。
- 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.修改其單擊事件槽函數(shù)。
- void Widget::on_pushButton_10_clicked() //添加方塊
- {
- this->gameArea->init_Game();
- //清空游戲區(qū)域
- 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.運行程序,效果如下。
(六)設置旋轉游戲區(qū)。
1.添加“旋轉游戲”按鈕。
2.修改其單擊事件槽函數(shù)。
- void Widget::on_pushButton_11_clicked() //旋轉游戲
- {
- this->gameArea->setRotate(true);
- //開啟旋轉
- this->gameArea->setGameAreaPixOrigin(100,200);
- //設置游戲區(qū)域新的坐標原點
- this->gameArea->setGameAreaPix(-100,-200);
- //設置游戲區(qū)域的位置
- this->gameArea->setRotateAngle(qrand()%360);
- //旋轉度數(shù)
- this->gameArea->draw_gameArea();
- this->gameArea->setFocus();
- }
3.運行程序,效果如下。
第三部分:游戲分析
(一)可被外部調用的功能函數(shù)的原型。
- GameArea(QWidget *parent = 0); //不帶定時器的構造函數(shù)
- GameArea(int speed,QWidget *parent = 0); //帶定時器的構造函數(shù)
- //以下是核心功能控制函數(shù)
- 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();
- //以下是設置顏色函數(shù)
- 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);
- //以下是設置聲音函數(shù)
- 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);
- //以下是設置游戲區(qū)域旋轉函數(shù)
- void setRotate(bool Bool=false);
- void setGameAreaPixOrigin(int x,int y);
- void setGameAreaPix(int x,int y);
- void setRotateAngle(int angle);
- //以下是其他功能函數(shù)
- 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是方塊類的定義文件,它用來提供隨機產(chǎn)生的方塊。
gamearea.cpp, gamearea.h是游戲區(qū)域類的定義文件,它實現(xiàn)了游戲的所有功能。
為了幫助大家更好的理解源碼,我們這里描述一下游戲的實現(xiàn)流程。
小結:似乎這個游戲是見怪不怪的了,不管怎么樣,還是希望這篇文章能夠幫到你?。?!
【編輯推薦】