中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Qt怎么實現方塊游戲

發布時間:2023-03-17 10:40:07 來源:億速云 閱讀:141 作者:iii 欄目:開發技術

這篇“Qt怎么實現方塊游戲”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Qt怎么實現方塊游戲”文章吧。

1.方塊游戲架構

在這個游戲中,有一個區域用來擺放方塊,該區域寬為10,高為20,以小正方形為單位,它可以看作是擁有20行10列的一個網格。標準的游戲中一共有7種方塊,它們都是由4個小正方形組成的規則圖形,依據形狀分別用字母I、J、L、O、S、T和Z來命名。

這里使用圖形視圖框架來實現整個游戲的設計。小正方形由OneBox來表示,它繼承自QGraphicsObject類,之所以繼承自這個類,是因為這樣就可以使用信號和槽機制,話可以使用屬性動畫。小正方形就是一個寬和高都為20像素的正方形圖形項。游戲中的方塊游戲由方塊組BoxGroup類來實現,繼承自QObject和QGraphicsItemGroup類,這樣該類也可以使用信號和槽機制。方塊組是一個寬和高都是80像素的圖形項組,其中包含了4個小方塊,通過設置小方塊的位置來實現7種標準的方塊圖形。它們的形狀和位置如下圖,在BoxGroup類中實現了方塊圖形的創建、移動和碰撞檢測。

Qt怎么實現方塊游戲

方塊移動區域在游戲場景中使用四條直線圖形項所圍成區域來表示,之所以要這樣實現,是因為這樣可以通過方塊組是否與直線圖形項碰撞來檢測是否移動出界。整個游戲界面由MyView類來實現,該類繼承自QGraphicsView類,實現了場景設置、游戲邏輯設計和游戲聲音設置及其他控制功能。

整個游戲場景寬800像素,高500像素。方塊移動區域寬200像素,高400像素,縱向每20個像素被視作一行,共有20行;橫行也是每20個像素視作一列,所以共有10列,該區域可以看作一個由20行10列20×20像素的方格組成的網格。方塊組在方塊移動區域的初始位置為上方正中間,但方塊組的最上方一行小正方形在方塊移動區域以外,這樣可以保證方塊組完全出現在移動區域的最上方,方塊組每移動一次,就是移動一個方格的位置。場景還設置了下一個要出現方塊的提示方塊、游戲暫停等控制按鈕和游戲分數級別的顯示文本,整個場景的示意圖如下圖所示:

2.游戲邏輯

當游戲開始后,首先創建一個新的方塊組,并將其添加到場景中的方塊移動區域上方。然后進行碰撞檢測,如果這時已經發生了碰撞,那么游戲結束;如果沒有發生碰撞,就可以使用鍵盤的方向鍵對其進行旋轉變形或者左右移動。當到達指定事件時方塊組會自動下移一個方格,這時再次判斷是否發生碰撞,如果發生了碰撞,先消除滿行的方格,然后出現新的方塊組,并繼續進行整個流程。其中方程塊的移動、旋轉、碰撞檢測等都在BoxGroup類中進行;游戲的開始、結束、出現新的方程組、消除滿行等都在MyView類中進行。游戲程序圖以及方塊組移動和旋轉流程圖如下:

Qt怎么實現方塊游戲

2.1、方塊組的移動和旋轉

方塊組的左移、右移、下移和旋轉都是先進行該操作,然后判斷是否發生碰撞,比如發生了碰撞就再進行反向操作。比如,使用方向鍵左移方塊組,那么就先將方塊組左移一格,然后進行碰撞檢測,看是否與邊界線或者其他方塊碰撞了,如果發生了碰撞,那么就再移過來,即右移一個。方塊組的移動和旋轉流程如下:

Qt怎么實現方塊游戲

2.2、碰撞檢測

對于方塊組的碰撞檢測,其實是使用方塊組中的4個小方塊來進行的,這樣就不用再為每個方塊圖形都設置一個碰撞檢測時使用的形狀。要進行碰撞檢測時,對每一個小方塊都使用函數來獲取與它們碰撞的圖形項的數目,因為現在小方塊在方塊組中,所以應該只有方塊組與它們碰撞了(由于我們對小方塊的形狀進行了設置,所以挨著的四個小方塊相互間不會被檢測出發生了碰撞),也就是說與它們碰撞的圖形項數目應該不會大于1,如果有哪個小方塊發現與它碰撞的圖形項的數目大于1,那么說明已經發生了碰撞。

2.3、游戲結束

當一個新的方塊組出現時,就立即對齊進行碰撞檢測,如果它一出現就與其他方塊發生了碰撞,說明游戲已經結束了,這時由方塊組發射游戲結束信號。

2.4、消除滿行

游戲開始后,每當出現一個新的方塊以前,都判斷游戲移動區域的每一行是否已經擁有10個小方塊。如果有一行已經擁有了10個小方塊,說明改行已滿,那么就銷毀該行的所有小方塊,然后讓該行上面的所有小方塊都下移一格。

3.效果圖

Qt怎么實現方塊游戲

4.具體實現

box.h

#ifndef BOX_H
#define BOX_H
#include <QGraphicsObject>
#include<QGraphicsItemGroup>
 
class OneBox :public QGraphicsObject
{
public:
    OneBox(const QColor &color = Qt::red);
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
    QPainterPath shape() const;
 
private:
    QColor brushColor;
 
};
 
 
class BoxGroup : public QObject,public QGraphicsItemGroup
{
    Q_OBJECT
public:
    enum BoxShape {IShape, JShape, LShape, OShape, SShape, TShape, ZShape, RandomShape};//8中俄羅斯方框形狀
    BoxGroup();
    QRectF boundingRect() const;//在函數后用const表示不能改變類的成員
    void clear_box_group(bool destroy_box = false);
    void create_box(const QPointF &point, BoxShape shape = RandomShape);//在函數的申明處可以將參數設定為默認值,定義處不需要
    bool isColliding();
    BoxShape getCurrentShape() {return current_shape;}//獲得當前俄羅斯方塊的形狀
 
 
protected:
    void keyPressEvent(QKeyEvent *event);
 
signals:
    void need_new_box();
    void game_finished();
 
public slots:
    void move_one_step();
    void startTimer(int interval);
    void stop_timer();
 
private:
    BoxShape current_shape;
    QTransform old_transform;
    QTimer *timer;
 
};
 
#endif // BOX_H

box.cpp

#include "box.h"
#include<QPainter>
#include<QTimer>
#include<QKeyEvent>
 
//OneBox是從QGraphicsObject繼承而來的
OneBox::OneBox(const QColor &color) : brushColor(color) {
 
}
 
 
//該函數為指定后面的繪圖區域的外邊框
QRectF OneBox::boundingRect() const {
 
    qreal pen_width = 1;
    //小方塊的邊長為20.5像素
    return QRectF(-10-pen_width/2, -10-pen_width/2, 20+pen_width, 20+pen_width);
 
}
 
void OneBox::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
 
    //貼圖,看起來有質感,否則單獨用顏色去看,會感覺那些方塊顏色很單一
    painter->drawPixmap(-10, -10, 20, 20, QPixmap(":/images/box.gif"));
    painter->setBrush(brushColor);//設置畫刷顏色
    QColor penColor = brushColor;
    penColor.setAlpha(20);//將顏色的透明度減小,使方框邊界和填充色直接能區分開
    painter->setPen(penColor);//色繪制畫筆
    //這里畫矩形框,框內填充部分用畫刷畫,框外線條用畫筆畫
    painter->drawRect(-10, -10, 20, 20);//畫矩形框
}
 
 
//在局部坐標點上返回item的shape,但是好像沒有其它地方調用了該函數
QPainterPath OneBox::shape() const{
 
    //QPainterPath是一個繪圖操作的容器
    QPainterPath path;
    path.addRect(-9.5, -9.5, 19, 19);
    return path;
}
 
 
//BoxGroup是從QGraphicsItemGroup,QObject繼承而來的
BoxGroup::BoxGroup() {
 
    setFlags(QGraphicsItem::ItemIsFocusable);//允許設置輸入焦點
    old_transform = transform();//返回當前item的變換矩陣,當BoxGroup進行旋轉后,可以使用它來進行恢復
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(move_one_step()));
    current_shape = RandomShape;
}
 
 
QRectF BoxGroup::boundingRect() const {
 
    qreal pen_width = 1;
    return QRectF(-40-pen_width/2, -40-pen_width/2, 80+pen_width, 80+pen_width);//2*2個小方塊組成一個小方塊組
}
 
 
void BoxGroup::keyPressEvent(QKeyEvent *event) {
 
    static qreal angle = 0;
    switch(event->key())
    {
        //向下鍵位墜落鍵
        case Qt::Key_Down:{
            moveBy(0, 20);//moveBy是系統自帶的函數,不需要我們自己去實現
            while(!isColliding()) {
                moveBy(0, 20);
            }
            moveBy(0, -20);//往回跳
            clear_box_group();//到達底部后就將當前方塊組的4個item移除,不銷毀方塊組
            emit need_new_box();//發射信號,在MyView中接收
            break;}
        case Qt::Key_Left:{
            moveBy(-20, 0);
            if(isColliding()) {
                moveBy(20, 0);
            }
            break;}
        case Qt::Key_Right:{
            moveBy(20, 0);
            if(isColliding()) {
                moveBy(-20, 0);
            }
            break;}
         //實現小方塊組變形
         case Qt::Key_Up:{
            setRotation(angle+90.0);
            angle = angle+90.0;
            //rotation();
            if(isColliding())
            {
                setRotation(angle-90);
                angle = angle-90.0;
                //rotation();
            }
            break;}
    }
}
 
 
//檢測是否有碰撞
bool BoxGroup::isColliding() {
 
    QList<QGraphicsItem *> item_list = childItems();//返回子item列表
    QGraphicsItem *item;
    foreach(item, item_list) {
        if(item->collidingItems().count()>1)//collidingItems返回與當前item碰撞的子item列表
            return true;//代表至少有一個item發生了碰撞
    }
    return false;
}
 
 
//將方塊組從視圖中移除掉,如果有需要(即參數為true的情況下)則銷毀掉
//其本質是將所有的小方塊從方塊組中移除掉,達到從視圖中將方塊組移除的目的
void BoxGroup::clear_box_group(bool destroy_box) {
 
    QList<QGraphicsItem *> item_list = childItems();
    QGraphicsItem *item;
    foreach(item, item_list) {
        removeFromGroup(item);//將item從方塊組中移除掉
        if(destroy_box) {
            OneBox *box = (OneBox*)item;
            box->deleteLater();//當控制返回到事件循環時,該目標被刪除,即銷毀
        }
    }
}
 
 
//創建俄羅斯方塊組,根據形狀參數選擇方塊組的顏色和形狀
void BoxGroup::create_box(const QPointF &point, BoxShape shape) {
 
    static const QColor color_table[7] = {
        QColor(200, 0, 0, 100), QColor(255, 200, 0, 100), QColor(0, 0, 200, 100),
        QColor(0, 200, 0, 100), QColor(0, 200, 255, 100), QColor(200, 0, 255, 100),
        QColor(150, 100, 100, 100)
    };
    int shape_id = shape; //Box_Shape是枚舉型,其實也是整型,因為它相當于整型的宏定義
    if(shape == RandomShape) {
        shape_id = qrand()%7;//隨機取一個顏色
    }
    QColor color = color_table[shape_id];//根據id選顏色
    QList<OneBox *> list;
    setTransform(old_transform);//恢復方塊組前的變換矩陣
    for(int i = 0; i < 4; ++i) { //4個小方塊組成一個方塊組
        OneBox *temp  = new OneBox(color);
        list << temp;//將小方塊加入list列表
        addToGroup(temp);
    }
    switch(shape_id) {
        case IShape:
        current_shape = IShape;//橫著的一桿
        list.at(0)->setPos(-30, -10);
        list.at(1)->setPos(-10, -10);
        list.at(2)->setPos(10, -10);
        list.at(3)->setPos(30, -10);
        break;
        case JShape:
        current_shape = JShape;//J型
        list.at(0)->setPos(10, -10);
        list.at(1)->setPos(10, 10);
        list.at(2)->setPos(10, 30);
        list.at(3)->setPos(-10, 30);
        break;
        case LShape:
        current_shape = LShape;//L型的方塊組
        list.at(0)->setPos(-10, -10);
        list.at(1)->setPos(-10, 10);
        list.at(2)->setPos(-10, 30);
        list.at(3)->setPos(10, 30);
        break;
        case OShape://田字型
        current_shape = OShape;
        list.at(0)->setPos(-10, -10);
        list.at(1)->setPos(10, -10);
        list.at(2)->setPos(-10, 10);
        list.at(3)->setPos(10, 10);
        break;
        case SShape://S型
        current_shape = SShape;
        list.at(0)->setPos(10, -10);
        list.at(1)->setPos(30, -10);
        list.at(2)->setPos(-10, 10);
        list.at(3)->setPos(10, 10);
        break;
        case TShape: //土子型
        current_shape = TShape;
        list.at(0)->setPos(-10, -10);
        list.at(1)->setPos(10, -10);
        list.at(2)->setPos(30, -10);
        list.at(3)->setPos(10, 10);
        break;
        case ZShape://Z字型
        current_shape = ZShape;
        list.at(0)->setPos(-10, -10);
        list.at(1)->setPos(10, -10);
        list.at(2)->setPos(10, 10);
        list.at(3)->setPos(30, 10);
        break;
        default: break;
    }
    setPos(point);//將準備好的俄羅斯方塊放入指定的位置,然后進行碰撞檢測
    if(isColliding()) {
        //如果俄羅斯方塊一出現后就發生了碰撞,因為它是從中間出來的,所以一開始不可能是與左右兩邊發生碰撞,
        //只能是與下面碰撞,因此如果發生了碰撞,說明游戲已經結束,就可以發送游戲結束信號了,且定時器停止。
        stop_timer();
        emit game_finished();
    }
}
 
 
//這個是系統里的函數,本程序中是在主函數中啟動的
//其實是該子類中的timeEvent()函數調用的
void BoxGroup::startTimer(int interval) {
    timer->start(interval);//啟動定時器并且設置定時器間隔,然后在BoxGroup()的構造函數中設置了該定時器的信號與槽函數
}
 
 
//每當定時器到時間了,小方塊組就向下移一步
void BoxGroup::move_one_step() {
    moveBy(0, 20);//該函數是父類的函數,這里指向下移動一個單位,因為向下為正坐標
    if(isColliding()) {//發生碰撞的情況下
        moveBy(0, -20);
        clear_box_group();//將方塊組移除視圖
        emit need_new_box();//發生信號通知程序需要新的方塊組出現
    }
}
 
 
 
void BoxGroup::stop_timer() {
 
    timer->stop();//定時器停止
}

myview.h

#ifndef MYVIEW_H
#define MYVIEW_H
#include <QGraphicsView>
class BoxGroup;
 
class MyView : public QGraphicsView
{
    Q_OBJECT
public:
    explicit MyView(QWidget *parent = 0);//關鍵字explicit是為了防止隱式類型轉換
 
public slots:
    void start_game();
    void clear_full_rows();
    void move_box();
    void game_over();
 
    void restartGame();
    void finishGame();
    void pauseGame();
    void returnGame();
 
 
protected:
 
 
private:
    //遮罩面板
    QGraphicsWidget *maskWidget;
    //各種按鈕
    QGraphicsWidget *mask_widget;
    //首頁和游戲中需要用到的各種按鈕
    QGraphicsWidget *start_button;
    QGraphicsWidget *finish_button;
    QGraphicsWidget *restart_button;
    QGraphicsWidget *pause_button;
    QGraphicsWidget *option_button;
    QGraphicsWidget *return_button;
    QGraphicsWidget *help_button;
    QGraphicsWidget *exit_button;
    QGraphicsWidget *show_menu_button;
 
    //顯示人機交互的文本信息
    QGraphicsTextItem *game_welcome_text;
    QGraphicsTextItem *game_pause_text;
    QGraphicsTextItem *game_over_text;
 
 
    QGraphicsTextItem *gameScoreText;
    QGraphicsTextItem *gameLevelText;
    QGraphicsLineItem *top_line;
    QGraphicsLineItem *bottom_line;
    QGraphicsLineItem *left_line;
    QGraphicsLineItem *right_line;
    BoxGroup *box_group;
    BoxGroup *next_box_group;
    qreal game_speed;
    QList<int> rows;
 
    void init_view();
    void init_game();
    void update_score(const int full_row_num = 0);
 
 
};
 
#endif // MYVIEW_H

myview.cpp

#include "myview.h"
#include"box.h"
#include<QIcon>
#include<QPropertyAnimation>
#include<QGraphicsBlurEffect>
#include<QTimer>
#include<QPushButton>
#include<QGraphicsProxyWidget>
#include<QApplication>
#include<QLabel>
#include<QFileInfo>
 
static const qreal INITSSPEED = 500;//游戲的初始化速度
 
MyView::MyView(QWidget *parent)
{
    init_view();
}
 
void MyView::start_game()
{
    game_welcome_text->hide();
    start_button->hide();
    option_button->hide();
    help_button->hide();
    exit_button->hide();
    mask_widget->hide();
    init_game();
}
 
void MyView::clear_full_rows()
{
    for(int y = 429; y > 50; y -= 20) {
        //每隔20行取一個item出來,括號里面的參數不能弄錯,否則沒有方塊消失的效果
        QList<QGraphicsItem *> list = scene()->items(199, y, 202, 22, Qt::ContainsItemShape,Qt::DescendingOrder);//返回指定區域內所有可見的item
        if(list.count() == 10) {   //如果一行已滿,則銷毀該行的所有小方塊
            foreach(QGraphicsItem *item, list) {
                OneBox *box = (OneBox *) item;
//                box->deleteLater();
                //先為小方塊使用了模糊圖形效果,然后為其添加了放大再縮小的屬性動畫,等動畫指定結束后才調用deleteLater()槽
                QGraphicsBlurEffect *blurEffect = new QGraphicsBlurEffect;
                box->setGraphicsEffect(blurEffect);
                QPropertyAnimation *animation = new QPropertyAnimation(box,"scale");
                animation->setEasingCurve(QEasingCurve::OutBounce);
                animation->setDuration(250);
                animation->setStartValue(4);
                animation->setEndValue(0.25);
                animation->start(QAbstractAnimation::DeleteWhenStopped);
                //connect(animation,SIGNAL(finished()),box,SLOT(deleteLater()));
                connect(animation,&QPropertyAnimation::finished,box,&OneBox::deleteLater);
            }
            rows << y;//將滿行的行號保存到rows中
        }
    }
 
    //如果滿行,則下移上面的方塊
    if(rows.count()>0) {
//     move_box();
        QTimer::singleShot(400,this,SLOT(move_box()));
    }
    else {
        //沒有滿行,則新出現提示方塊,且提示方塊出更新新的提示方塊
        box_group->create_box(QPointF(300, 70), next_box_group->getCurrentShape());
        next_box_group->clear_box_group(true);
        next_box_group->create_box(QPointF(500, 70));//
    }
 
}
 
void MyView::move_box()
{
    for(int i = rows.count(); i > 0; --i) {
        int row = rows.at(i-1);//取出滿行的行號,從最上面的位置開始
        //取出從區域上邊界到當前滿行之間所形成的矩形區域
        foreach(QGraphicsItem *item, scene()->items(199, 49, 202, row-47, Qt::ContainsItemShape,Qt::DescendingOrder)) {
            item->moveBy(0, 20);
        }
    }
    //更新分數
    update_score(rows.count());
    //出現新的方塊組
    rows.clear();
    box_group->create_box(QPointF(300, 70), next_box_group->getCurrentShape());
    next_box_group->clear_box_group(true);
    next_box_group->create_box(QPoint(500, 70));
}
 
void MyView::game_over()
{
    //游戲結束
    pause_button->hide();
    show_menu_button->hide();
    mask_widget->show();
    game_over_text->show();
    restart_button->setPos(370, 200);
    finish_button->show();
}
 
void MyView::restartGame()
{
    mask_widget->hide();
    game_over_text->hide();
    finish_button->hide();
    restart_button->setPos(600, 150);
 
    //銷毀當前方塊組和當前方塊中的所有小方塊
    next_box_group->clear_box_group(true);
    box_group->clear_box_group();
    box_group->hide();
    foreach(QGraphicsItem *item, scene()->items(199, 49, 202, 402,Qt::ContainsItemBoundingRect,Qt::DescendingOrder)) {
        scene()->removeItem(item);
        OneBox *box = (OneBox*)item;
        box->deleteLater();
    }
    init_game();
}
 
void MyView::finishGame()
{
    game_over_text->hide();
    finish_button->hide();
    restart_button->setPos(600, 150);
    restart_button->hide();
    pause_button->hide();
    show_menu_button->hide();
    gameScoreText->hide();
    gameLevelText->hide();
    top_line->hide();
    bottom_line->hide();
    left_line->hide();
    right_line->hide();
 
    next_box_group->clear_box_group(true);
    box_group->clear_box_group();
    box_group->hide();
    foreach(QGraphicsItem *item, scene()->items(199, 49, 202, 402,Qt::ContainsItemBoundingRect,Qt::DescendingOrder)) {
        scene()->removeItem(item);
        OneBox *box = (OneBox*)item;
        box->deleteLater();
    }
 
    mask_widget->show();
    game_welcome_text->show();
    start_button->show();
    option_button->show();
    help_button->show();
    exit_button->show();
    scene()->setBackgroundBrush(QPixmap(":/images/background.png"));
}
 
void MyView::pauseGame()
{
    box_group->stop_timer();//中斷游戲最主要的是停止方塊下移的定時器工作
    restart_button->hide();
    pause_button->hide();
    show_menu_button->hide();
    mask_widget->show();
    game_pause_text->show();
    return_button->show();
}
 
void MyView::returnGame()
{
    return_button->hide();
    game_pause_text->hide();
    mask_widget->hide();
    restart_button->show();
    pause_button->show();
    show_menu_button->show();
    box_group->startTimer(game_speed);
}
 
 
 
void MyView::init_view()
{
    setRenderHint(QPainter::Antialiasing);//使用抗鋸齒的方式渲染
    setCacheMode(CacheBackground);//設置緩存背景,這樣可以加快渲染速度
    setWindowTitle(tr("Teris游戲"));
    setWindowIcon(QIcon(":/images/icon.png"));//設置標題處的圖標
    setMinimumSize(810, 510);  //2者設置成一樣說明視圖尺寸不能再更改
    setMaximumSize(810, 510);
    QGraphicsScene *scene = new QGraphicsScene;//新建場景指針
    scene->setSceneRect(5, 5, 800, 500);//場景大小
    scene->setBackgroundBrush(QPixmap(":/images/background.png"));
    setScene(scene);//設置場景
 
    //俄羅斯方塊可移動區域外界的4條線,與外界預留3個像素是為了方便進行碰撞檢測
    top_line = scene->addLine(197, 27, 403, 27);
    bottom_line = scene->addLine(197, 453, 403, 453);
    left_line = scene->addLine(197, 27, 197, 453);
    right_line = scene->addLine(403, 27, 403, 453);
 
    //添加當前方塊組
    box_group = new BoxGroup;//通過新建BoxGroup對象間接達到調用box的2個類
    connect(box_group, SIGNAL(need_new_box()), this, SLOT(clear_full_rows()));
    connect(box_group, SIGNAL(game_finished()), this, SLOT(game_over()));
    scene->addItem(box_group);
 
    //添加提示方塊組
    next_box_group = new BoxGroup;
    scene->addItem(next_box_group);
 
    gameScoreText = new QGraphicsTextItem();//文本的父item為對應的場景
    gameScoreText->setFont(QFont("Times", 50, QFont::Bold));//為文本設置字體
    gameScoreText->setPos(450, 350);//分數在場景中出現的位置
 
    gameLevelText = new QGraphicsTextItem();
    gameLevelText->setFont(QFont("Times", 50, QFont::Bold));
    gameLevelText->setPos(20, 150);
 
    scene->addItem(gameLevelText);
    scene->addItem(gameScoreText);
 
    //開始游戲
   //start_game();
    //設置初始為隱藏狀態
    top_line->hide();
    bottom_line->hide();
    left_line->hide();
    right_line->hide();
    gameScoreText->hide();
    gameLevelText->hide();
 
    //黑色遮罩
    QWidget *mask = new QWidget;
    mask->setAutoFillBackground(true);
    mask->setPalette(QPalette(QColor(0, 0, 0, 50)));//alpha為不透明度
    mask->resize(900, 600);
    //addWidget()函數的返回值是QGraphicsProxyWidget,如果不添加相應的頭文件,則此處會報錯
    mask_widget = scene->addWidget(mask);
    mask_widget->setPos(-50, -50);
    mask_widget->setZValue(1);//該層薄紗放在原圖的上面,這里有點類似于opengl中的3維繪圖
 
    //選項面板
    QWidget *option = new QWidget;
    //將關閉按鈕放在option上
    QPushButton *option_close_button = new QPushButton(tr("關  閉"), option);//第2個參數為按鈕所在的widget
    //設置按鈕的字體顏色是白色
    QPalette palette;
    palette.setColor(QPalette::ButtonText, Qt::black);//第一個參數調色版的role,這里指的是按鈕字體顏色
    option_close_button->setPalette(palette);
    //設置關閉按鈕的位置,和單擊后的響應
    option_close_button->move(120, 300);
    connect(option_close_button, SIGNAL(clicked()), option, SLOT(hide()));//單擊后消失
 
    option->setAutoFillBackground(true);
    option->setPalette(QPalette(QColor(0, 0, 0, 180)));
    option->resize(300, 400);
    QGraphicsWidget *option_widget = scene->addWidget(option);
    option_widget->setPos(250, 50);
    option_widget->setZValue(3);
    option_widget->hide();
 
 
    //幫助面板
    QWidget *help = new QWidget;
    QPushButton *help_close_button = new QPushButton(tr("幫  助"), help);
    help_close_button->setPalette(palette);
    help_close_button->move(120, 300);
    connect(help_close_button, SIGNAL(clicked()), help, SLOT(hide()));
 
    help->setAutoFillBackground(true);
    help->setPalette(QPalette(QColor(0, 0, 0, 180)));
    help->resize(300, 400);
    QGraphicsWidget *help_widget = scene->addWidget(help);
    help_widget->setPos(250, 50);
    help_widget->setZValue(3);
    help_widget->hide();
 
    //游戲歡迎文本
    game_welcome_text = new QGraphicsTextItem();//第一個參數為文本內容,第二個參數為父item
    game_welcome_text->setHtml(tr("<font color=green>Tetris游戲</font>"));
    game_welcome_text->setFont(QFont("Times", 40, QFont::Bold));
    game_welcome_text->setPos(300, 100);
    game_welcome_text->setZValue(2);//放在第2層
 
 
    //游戲暫停文本
    game_pause_text = new QGraphicsTextItem();//第一個參數為文本內容,第二個參數為父item
    game_pause_text->setHtml(tr("<font color=green>游戲暫停中!</font>"));
    game_pause_text->setFont(QFont("Times", 40, QFont::Bold));
    game_pause_text->setPos(300, 100);
    game_pause_text->setZValue(2);//放在第2層
    game_pause_text->hide();
 
    //游戲結束文本
    game_over_text = new QGraphicsTextItem();//第一個參數為文本內容,第二個參數為父item
    game_over_text->setHtml(tr("<font color=green>GAME OVER!</font>"));
    game_over_text->setFont(QFont("Times", 40, QFont::Bold));
    game_over_text->setPos(300, 100);
    game_over_text->setZValue(2);//放在第2層
    game_over_text->hide();
 
    scene->addItem(game_welcome_text);
    scene->addItem(game_pause_text);
    scene->addItem(game_over_text);
    // 游戲中使用的按鈕
 
    QPushButton *button1 = new QPushButton(tr("開    始"));
    QPushButton *button2 = new QPushButton(tr("選    項"));
    QPushButton *button3 = new QPushButton(tr("幫    助"));
    QPushButton *button4 = new QPushButton(tr("退    出"));
    QPushButton *button5 = new QPushButton(tr("重新開始"));
    QPushButton *button6 = new QPushButton(tr("暫    停"));
    QPushButton *button7 = new QPushButton(tr("主 菜 單"));
    QPushButton *button8 = new QPushButton(tr("返回游戲"));
    QPushButton *button9 = new QPushButton(tr("結束游戲"));
 
    connect(button1, SIGNAL(clicked()), this, SLOT(start_game()));
    connect(button2, SIGNAL(clicked()), option, SLOT(show()));
    connect(button3, SIGNAL(clicked()), help, SLOT(show()));
    connect(button4, SIGNAL(clicked()), qApp, SLOT(quit()));//此處槽函數的接收對象為應用程序本身
    connect(button5, SIGNAL(clicked()), this, SLOT(restartGame()));
    connect(button6, SIGNAL(clicked()), this, SLOT(pauseGame()));
    connect(button7, SIGNAL(clicked()), this, SLOT(show_menu_button()));
    connect(button8, SIGNAL(clicked()), this, SLOT(returnGame()));//返回主菜單
    connect(button9, SIGNAL(clicked()), this, SLOT(finishGame()));
 
    start_button = scene->addWidget(button1);//restart_button并不是QPushbutton類型,而是QGraphicsItem類型,后面的類似
    option_button = scene->addWidget(button2);
    help_button = scene->addWidget(button3);
    exit_button = scene->addWidget(button4);
    restart_button = scene->addWidget(button5);
    pause_button = scene->addWidget(button6);
    show_menu_button = scene->addWidget(button7);
    return_button = scene->addWidget(button8);
    finish_button = scene->addWidget(button9);
 
    //設置位置
    start_button->setPos(370, 200);
    option_button->setPos(370, 250);
    help_button->setPos(370, 300);
    exit_button->setPos(370, 350);
    restart_button->setPos(600, 150);
    pause_button->setPos(600, 200);
    show_menu_button->setPos(600, 250);
    return_button->setPos(370, 200);
    finish_button->setPos(370, 250);
 
    //將這些按鈕都放在z方向的第二層
    start_button->setZValue(2);
    option_button->setZValue(2);
    help_button->setZValue(2);
    exit_button->setZValue(2);
    restart_button->setZValue(2);
    return_button->setZValue(2);
    finish_button->setZValue(2);
 
    //一部分按鈕隱藏起來
    restart_button->hide();
    finish_button->hide();
    pause_button->hide();
    show_menu_button->hide();
    return_button->hide();
 
}
 
void MyView::init_game()
{
    box_group->create_box(QPointF(300, 70)); //創建方塊組,在中間位置處出現
    box_group->setFocus();//設置人機交互焦點,這樣就可以使用鍵盤來控制它
    box_group->startTimer(INITSSPEED);//啟動定時器
    game_speed = INITSSPEED;//游戲速度,暫停時需要用到
    next_box_group->create_box(QPoint(500, 70));//創建提示方塊組
 
    scene()->setBackgroundBrush(QPixmap(":/images/background01.png"));
    gameScoreText->setHtml(tr("<font color=red>00</font>"));
    gameLevelText->setHtml(tr("<font color=white>第<br>一<br>幕</font>"));
 
    restart_button->show();
    pause_button->show();
    show_menu_button->show();
    gameScoreText->show();
    gameLevelText->show();
    top_line->show();
    bottom_line->show();
    left_line->show();
    right_line->show();
    // 可能以前返回主菜單時隱藏了boxGroup
    box_group->show();
}
 
void MyView::update_score(const int full_row_num)
{
    //更新分數
    int score = full_row_num *100;
    int currentScore =gameScoreText->toPlainText().toInt();
    currentScore+=score;
    //顯示當前分數
    gameScoreText->setHtml(tr("<font color=red>%1</font>").arg(currentScore));
    //判斷級別
    if(currentScore<500)
    {
        //第一級,什么都不用做
 
    }
    else if(currentScore <1000)
    {
        //第二級
        gameLevelText->setHtml(tr("<font color=white>第<br>二<br>幕</font>"));
        scene()->setBackgroundBrush(QPixmap(":/images/background02.png"));
        game_speed =300;
        box_group->stop_timer();
        box_group->startTimer(game_speed);
    }
    else {
        //添加下一個級別的設置
    }
}

main.cpp

#include<QApplication>
#include"myview.h"
#include<QTextCodec>
#include<QTime>
 
int main(int argc, char* argv[]) {
 
    QApplication  app(argc, argv);
    QTextCodec::setCodecForLocale(QTextCodec::codecForLocale());
    //QTime提供了鬧鐘功能
    qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));//secsTo()為返回當前的秒數
 
    MyView view;//主函數是直接調用的視圖類
    view.show();
 
    return app.exec();
}

以上就是關于“Qt怎么實現方塊游戲”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

qt
AI

梁平县| 双城市| 阳谷县| 综艺| 亚东县| 惠水县| 崇信县| 云林县| 甘肃省| 华池县| 江门市| 环江| 昭平县| 四平市| 兴隆县| 新兴县| 通辽市| 桃源县| 福海县| 沈阳市| 武汉市| 永宁县| 肃北| 临漳县| 庆云县| 稻城县| 焉耆| 黎川县| 双牌县| 淮滨县| 如皋市| 全南县| 镇赉县| 兰考县| 嘉祥县| 平果县| 蓝山县| 嫩江县| 临夏市| 上虞市| 河西区|