Qt5 圖形視圖框架QGraphicsView
1、圖形視圖框架包含三大類:場景類(QGraphicsScene),視圖類(QGraphicsView),圖元類(QGraphicsItem);
2、對於有很多項的場景,使用輕量級的QGraphicsItem類作爲數目衆多的自定義項的基礎最好,僅對數目較少的項使用QGraphicsObject
3、當一個項發生了變換(transformation),該項所有的子對象自動應用 該變換,遞歸應用到最深層次的子孫對象,
變換有(拖動,移動。。。。。),通過調用QGraphicsItem::setFlag(QGraphicsItem::ItemIngnoreTransformation)可以使子項忽略父項的變換,通常使用的標誌還有可移動,選中,獲得焦點等
4、通過把項設置爲QGraphicsItemGroup的子項,可以將他們分組,創建項的集合。
5、圖形視圖類使用三種座標系統,但是實際應用中只是關心其中的兩種。視圖使用物理座標系統,場景使用在構造函數中傳入的QRectF定義的邏輯座標系統。Qt自動進行場景座標到視圖座標的映射,放置項時使用的是場景的座標。項的中心是在(0,0)點的邏輯座標系統,每個項的(0,0)點實際在該項場景中所在位置的中心(文本項除外,原點在項的左上角)。
6、圖形項:QGraphicsItem因爲有兩個純虛函數而不能實例化對象,這兩個純虛函數是boundingRect()和paint()
paint()函數必須重新實現來繪製項,boundingRect()函數在圖形視圖框架中爲項提供一個邊界矩形,用於衝突監測和保證項僅在QGraphicsView的視口(viewport)中可見時才重繪。如果要創建非矩形形狀的自定義圖形項,最好同時實現shape()方法,這個方法返回一個精確描述項的輪廓的QpainterPath,對於準確檢測衝突和鼠標點擊非常有用。
7、如果要自定義一個形狀,最簡單的是使用標準的QGraphicsItem的子類之一,比如QGraphicsPathItem和QGraphicsPolygonItem,如果有定製行爲,可以重新實現保護事件的處理函數,如keyPressEvent()。如果只是想要自己繪製,可以從QGraphicsItem派生,重新實現boundingRect()和paint()和shape()方法。
俄羅斯方塊的實現
俄羅斯方塊的邏輯
小方塊的類型
效果圖
代碼的實現
onePiece.h
#ifndef ONEPIECE_H
#define ONEPIECE_H
/************
*一塊方塊的繪製
*
*
***************/
#include <QGraphicsObject>
#include <QColor>
class onePiece : public QGraphicsObject
{
public:
onePiece(const QColor &brushColor = Qt::red);
//爲項提供一個外圍的邊界矩形
virtual QRectF boundingRect() const;
//QGraphicsView調用,在本地座標系統中繪製項
virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0);
//重新定義項的形狀,默認調用boundingRect獲取項的矩形形狀輪廓
virtual QPainterPath shape() const;
private:
QColor m_brushColor;
};
#endif // ONEPIECE_H
onepiece.c
#include "onepiece.h"
#include <QPainter>
#include "enumHeader.h"
/****
* 爲了避免同一個方塊組內小方塊發生碰撞,
* 小方塊的大小實際爲19.5*19.5,但是小方塊加上筆刷的寬度後爲20*20
* 這樣看起來是四個小方塊連在一起的
* **/
onePiece::onePiece(const QColor &brushColor)
:m_brushColor(brushColor)
{
}
QRectF onePiece::boundingRect() const
{
qreal penWidth = PEN_WIDTH;
return QRectF(-(PIECE_DIAMETER - penWidth)/2, -(PIECE_DIAMETER - penWidth)/2,
PIECE_DIAMETER - penWidth, PIECE_DIAMETER - penWidth);
}
void onePiece::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
//背景貼圖
painter->drawPixmap(-PIECE_DIAMETER/2,-PIECE_DIAMETER/2,PIECE_DIAMETER,PIECE_DIAMETER,QPixmap(":/piece/Image/piece/box.png"));
painter->setBrush(m_brushColor);
//將方塊的邊界的顏色進行透明化
QColor penColor = m_brushColor;
// 將顏色的透明度減小
penColor.setAlpha(200);
painter->setPen(penColor);
//使用當前的筆刷和筆畫矩形框
painter->drawRect(-PIECE_DIAMETER/2, -PIECE_DIAMETER/2, PIECE_DIAMETER, PIECE_DIAMETER);
}
QPainterPath onePiece::shape() const
{
QPainterPath path;
//去除筆刷的寬度,這樣同一個方塊組的方塊就不會被檢測出碰撞的情況
path.addRect(-(PIECE_DIAMETER-PEN_WIDTH)/2,-(PIECE_DIAMETER-PEN_WIDTH)/2,PIECE_DIAMETER-PEN_WIDTH,PIECE_DIAMETER-PEN_WIDTH);
return path;
}
pieceBox.h
#ifndef PIECEBOX_H
#define PIECEBOX_H
/********
* 方塊組
* 4*4
*
*
* ******/
#include <QGraphicsItemGroup>
#include <QKeyEvent>
#include <QTimer>
#include "enumHeader.h"
#include <QTransform>
#include "onepiece.h"
#include <QGraphicsItem>
class pieceBox :public QObject,public QGraphicsItemGroup
{
Q_OBJECT
public:
pieceBox();
//顏色表
static QColor colorTable[7];
//繪製方塊組的邊框矩形
virtual QRectF boundingRect() const;
//是否發生碰撞
bool isCollding() const;
//獲取當前的方塊類型
BoxType getCurrentBoxType() const;
//創建方塊組
void createBox(const QPointF &point = QPointF(0,0),
BoxType currentBoxType = RandomShape);
//消除方塊組
void clearBoxGroup(const bool &isClear = false);
protected:
virtual void keyPressEvent(QKeyEvent * event);
signals:
void signal_needNewBox();
void signal_gameOver();
public slots:
void slot_moveOneStep();
void slot_startTimer(int timeSec);
void slot_stopTimer();
private:
QTimer *m_Timer;
BoxType m_currentBoxType;
QTransform m_oldTransform;
QList<onePiece *> m_pieceBoxList; //存放新方塊組的四個方塊
};
#endif // PIECEBOX_H
pieceBox.c
#include "piecebox.h"
#include "enumHeader.h"
#include <QList>
#include <QDebug>
QColor pieceBox::colorTable[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)};
pieceBox::pieceBox()
{
m_pieceBoxList.clear();
//使得方塊組支持鍵盤操作
setFlags(QGraphicsItem::ItemIsFocusable);
//保存矩陣的原狀態,使得可以還原矩陣
m_oldTransform = transform();
m_Timer = new QTimer(this);
connect(m_Timer,SIGNAL(timeout()),this,SLOT(slot_moveOneStep()));
m_currentBoxType = RandomShape;
}
//繪製方塊組的邊框矩形
QRectF pieceBox::boundingRect() const
{
qreal penWidth = PEN_WIDTH;
return QRectF(-(PIECE_DIAMETER*2 - penWidth) / 2, -(PIECE_DIAMETER*2 - penWidth) / 2,
PIECE_DIAMETER*4-penWidth, PIECE_DIAMETER*4-penWidth);
}
bool pieceBox::isCollding() const
{
//依次檢測方塊組中的每個方塊的碰撞
foreach (onePiece *piece, m_pieceBoxList) {
// qDebug() << "colliding number:" << piece->collidingItems().count();
//獲取與該方塊碰撞的方塊的個數
if(piece->collidingItems().count() > 1)
{
return true;
}
}
return false;
}
BoxType pieceBox::getCurrentBoxType() const
{
return m_currentBoxType;
}
void pieceBox::createBox(const QPointF &point, BoxType currentBoxType)
{
int boxType = currentBoxType;
if(boxType == RandomShape)
{
boxType = qrand() % 7;
}
//設置該方塊組的顏色
QColor boxColor = colorTable[boxType];
//準備四個小方塊
//恢復方塊組的變換矩陣,因爲之前的方塊組的變換會導致變換矩陣的位置發生變換,
//防止新的方塊組因爲舊的方塊組變換異常
setTransform(m_oldTransform);
setRotation(0);
resetTransform();
m_pieceBoxList.clear();
for(int i = 0;i < 4;i++)
{
onePiece *piece = new onePiece(boxColor);
m_pieceBoxList.append(piece);
//將小方塊添加到方塊組中
addToGroup(piece);
}
//設置方塊組的形狀
switch (boxType) {
case IShape:
m_currentBoxType = IShape;
m_pieceBoxList.at(0)->setPos(-30,-10);
m_pieceBoxList.at(1)->setPos(-10,-10);
m_pieceBoxList.at(2)->setPos(10,-10);
m_pieceBoxList.at(3)->setPos(30,-10);
break;
case JShape:
m_currentBoxType = JShape;
m_pieceBoxList.at(0)->setPos(10,-10);
m_pieceBoxList.at(1)->setPos(10,10);
m_pieceBoxList.at(2)->setPos(10,30);
m_pieceBoxList.at(3)->setPos(-10,30);
break;
case LShape:
m_currentBoxType = LShape;
m_pieceBoxList.at(0)->setPos(-10,-10);
m_pieceBoxList.at(1)->setPos(-10,10);
m_pieceBoxList.at(2)->setPos(10,30);
m_pieceBoxList.at(3)->setPos(-10,30);
break;
case OShape:
m_currentBoxType = OShape;
m_pieceBoxList.at(0)->setPos(-10,-10);
m_pieceBoxList.at(1)->setPos(10,-10);
m_pieceBoxList.at(2)->setPos(-10,10);
m_pieceBoxList.at(3)->setPos(10,10);
break;
case SShape:
m_currentBoxType = SShape;
m_pieceBoxList.at(0)->setPos(30,-10);
m_pieceBoxList.at(1)->setPos(10,-10);
m_pieceBoxList.at(2)->setPos(10,10);
m_pieceBoxList.at(3)->setPos(-10,10);
break;
case TShape:
m_currentBoxType = TShape;
m_pieceBoxList.at(0)->setPos(-10,-10);
m_pieceBoxList.at(1)->setPos(10,-10);
m_pieceBoxList.at(2)->setPos(30,-10);
m_pieceBoxList.at(3)->setPos(10,10);
break;
case Zshape:
m_currentBoxType = Zshape;
m_pieceBoxList.at(0)->setPos(-10,-10);
m_pieceBoxList.at(1)->setPos(10,-10);
m_pieceBoxList.at(2)->setPos(10,10);
m_pieceBoxList.at(3)->setPos(30,10);
break;
default:
break;
}
//設置方塊組的位置
setPos(point);
//檢測是否發生碰撞,發生碰撞,遊戲結束
if(isCollding())
{
slot_stopTimer();
emit signal_gameOver();
}
}
//刪除方塊組中的小方塊到情景中
void pieceBox::clearBoxGroup(const bool &isClear)
{
QList<QGraphicsItem *> itemList = childItems();
foreach (QGraphicsItem *piece, itemList) {
removeFromGroup(piece);
// qDebug() << "clear box group" << isClear;
if(isClear)
{
//銷燬小方塊
((onePiece *)piece)->deleteLater();
}
}
m_pieceBoxList.clear();
}
void pieceBox::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Down:
moveBy(0,20);
//檢測是否碰撞
if(isCollding())
{
moveBy(0,-20);
clearBoxGroup();
//需要新的方塊
emit signal_needNewBox();
}
break;
case Qt::Key_Left:
moveBy(-20,0);
if(isCollding())
{
moveBy(20,0);
}
break;
case Qt::Key_Right:
moveBy(20,0);
if(isCollding())
{
moveBy(-20,0);
}
break;
case Qt::Key_Up:
setRotation(rotation()+90);
if(isCollding())
{
setRotation(rotation()-90);
}
break;
case Qt::Key_Space: //快速下落
moveBy(0,20);
while (!isCollding()) {
moveBy(0,20);
}
moveBy(0,-20);
clearBoxGroup();
//需要新的方塊
emit signal_needNewBox();
break;
default:
break;
}
}
void pieceBox::slot_moveOneStep()
{
moveBy(0,20);
// qDebug() << "move one step";
if(isCollding())
{
moveBy(0,-20);
// 將小方塊從方塊組中移除到場景中
clearBoxGroup();
//需要新的方塊
emit signal_needNewBox();
}
}
void pieceBox::slot_startTimer(int timeSec)
{
m_Timer->start(timeSec);
}
void pieceBox::slot_stopTimer()
{
m_Timer->stop();
}
**界面類**panel.h
#ifndef PANEL_H
#define PANEL_H
#include <QWidget>
#include <QPalette>
#include <QPixmap>
#include <QGraphicsScene>
#include <QGraphicsView>
#include "piecebox.h"
#include "onepiece.h"
#include <QGraphicsLineItem>
#include <QMediaPlayer>
namespace Ui {
class Panel;
}
class Panel : public QWidget
{
Q_OBJECT
public:
explicit Panel(QWidget *parent = 0);
~Panel();
void setbackground(const int &Lv);
void initControlWidget();
void initGraphicsViewWidget();
/**遊戲控制項***/
void startGame();
void pauseGame();
void restartGame();
void stopGame();
void updateScore(const int fullRows = 0);
private slots:
void on_pbt_startGame_clicked();
void on_pbt_pauseGame_clicked();
void on_pbt_restart_clicked();
void on_pbt_stopGame_clicked();
void slot_clearFullRows();
void slot_gameOver();
void slot_moveBox();
private:
Ui::Panel *ui;
QPalette m_Palette;
QPixmap m_pixmap;
int m_currentLv;
int m_currentLVSpeed;
bool m_isPauseGame;
bool m_isGameOver;
QGraphicsScene *m_scene;
//四條邊界線
QGraphicsLineItem *m_topLine;
QGraphicsLineItem *m_leftLine;
QGraphicsLineItem *m_buttomLine;
QGraphicsLineItem *m_rightLine;
pieceBox *m_currentBox;
pieceBox *m_nextBox;
QList<int> m_rowList;
QMediaPlayer *m_mediaPlayer;
};
#endif // PANEL_H
panel.c
#include "panel.h"
#include "ui_panel.h"
#include "enumHeader.h"
#include <QDebug>
#include <QGraphicsBlurEffect>
#include <QPropertyAnimation>
#include <QMessageBox>
#include <QMediaContent>
Panel::Panel(QWidget *parent) :
QWidget(parent),
ui(new Ui::Panel)
{
ui->setupUi(this);
m_isPauseGame = false;
m_isGameOver = false;
m_mediaPlayer = new QMediaPlayer;
m_mediaPlayer->setMedia(QUrl::fromLocalFile(QString("clearRow.mp3")));
m_mediaPlayer->setVolume(100);
//設置背景
setbackground(LV0);
initControlWidget();
initGraphicsViewWidget();
}
Panel::~Panel()
{
delete ui;
}
void Panel::setbackground(const int &Lv)
{
setAutoFillBackground(true);
switch (Lv) {
case LV0:
m_currentLv = LV0;
m_currentLVSpeed = LV0_SPEED;
ui->label_gameLevel->setText("俄羅斯方塊");
m_pixmap.load(":/background/Image/background/background.png");
break;
case LV1:
m_currentLv = LV1;
m_currentLVSpeed = LV1_SPEED;
ui->label_gameLevel->setText("第一關");
m_pixmap.load(":/background/Image/background/background01.png");
break;
case LV2:
m_currentLv = LV2;
m_currentLVSpeed = LV2_SPEED;
ui->label_gameLevel->setText("第二關");
m_pixmap.load(":/background/Image/background/background02.png");
break;
case LV3:
m_currentLv = LV3;
m_currentLVSpeed = LV3_SPEED;
ui->label_gameLevel->setText("第三關");
m_pixmap.load(":/background/Image/background/background03.png");
break;
case LV4:
m_currentLv = LV4;
m_currentLVSpeed = LV4_SPEED;
ui->label_gameLevel->setText("第四關");
m_pixmap.load(":/background/Image/background/background04.png");
break;
case LV5:
m_currentLv = LV5;
m_currentLVSpeed = LV5_SPEED;
ui->label_gameLevel->setText("第五關");
m_pixmap.load(":/background/Image/background/background05.png");
break;
default:
break;
}
m_Palette.setBrush(QPalette::Window, QBrush(m_pixmap.scaled(size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation)));
setPalette(m_Palette);
}
void Panel::initControlWidget()
{
switch (m_currentLv) {
case LV0:
ui->pbt_startGame->setEnabled(true);
ui->pbt_pauseGame->setEnabled(false);
ui->pbt_restart->setEnabled(false);
ui->pbt_stopGame->setEnabled(false);
break;
case LV1:
case LV2:
case LV3:
case LV4:
case LV5:
ui->pbt_startGame->setEnabled(false);
ui->pbt_pauseGame->setEnabled(true);
ui->pbt_restart->setEnabled(true);
ui->pbt_stopGame->setEnabled(true);
break;
default:
break;
}
}
void Panel::initGraphicsViewWidget()
{
//使用抗鋸齒渲染
ui->GraphicsView->setRenderHint(QPainter::Antialiasing);
//設置緩衝背景,加速渲染
ui->GraphicsView->setCacheMode(QGraphicsView::CacheBackground);
m_scene = new QGraphicsScene(this);
m_scene->setSceneRect(30,30,310,410);
ui->GraphicsView->setScene(m_scene);
//方塊可移動的四條線
//向外擴展3像素,這樣可以使方塊組到達邊界的時候再移動就會發生碰撞
m_topLine = m_scene->addLine(32,32,238,32);
m_leftLine = m_scene->addLine(32,32,32,438);
m_buttomLine = m_scene->addLine(32,438,238,438);
m_rightLine = m_scene->addLine(238,32,238,438);
m_topLine->setPen(QPen(QColor(255,255,255)));
m_leftLine->setPen(QPen(QColor(255,255,255)));
m_buttomLine->setPen(QPen(QColor(255,255,255)));
m_rightLine->setPen(QPen(QColor(255,255,255)));
m_currentBox = new pieceBox;
m_nextBox = new pieceBox;
connect(m_currentBox,SIGNAL(signal_needNewBox()),this,SLOT(slot_clearFullRows()));
connect(m_currentBox,SIGNAL(signal_gameOver()),this,SLOT(slot_gameOver()));
m_scene->addItem(m_currentBox);
m_scene->addItem(m_nextBox);
}
void Panel::startGame()
{
m_currentBox->createBox(QPointF(135,55));
m_nextBox->createBox(QPointF(290,55));
//將鍵盤焦點給當前的方塊組
m_currentBox->setFocus();
m_currentBox->slot_startTimer(m_currentLVSpeed);
}
void Panel::updateScore(const int fullRows)
{
int score = ui->LCDNum_Score->value() + fullRows*ROWSCORE;
ui->LCDNum_Score->display(score);
if(score < 1000) //第一關
{
}else if(score < 2000) //第二關
{
setbackground(LV2);
initControlWidget();
m_currentBox->slot_stopTimer();
m_currentBox->slot_startTimer(m_currentLVSpeed);
}else if(score < 4000) //第三關
{
setbackground(LV3);
initControlWidget();
m_currentBox->slot_stopTimer();
m_currentBox->slot_startTimer(m_currentLVSpeed);
}else if(score < 8000) //第四關
{
setbackground(LV4);
initControlWidget();
m_currentBox->slot_stopTimer();
m_currentBox->slot_startTimer(m_currentLVSpeed);
}else if(score < 16000) //第五關
{
setbackground(LV5);
initControlWidget();
m_currentBox->slot_stopTimer();
m_currentBox->slot_startTimer(m_currentLVSpeed);
}else //從第一關重新開始
{
setbackground(LV1);
initControlWidget();
m_currentBox->slot_stopTimer();
m_currentBox->slot_startTimer(m_currentLVSpeed);
}
}
/**
* 開始遊戲
* @brief Panel::on_pbt_startGame_clicked
*/
void Panel::on_pbt_startGame_clicked()
{
m_isGameOver = false;
if(m_isPauseGame)
{
ui->pbt_startGame->setEnabled(false);
m_isPauseGame = false;
m_currentBox->slot_startTimer(m_currentLVSpeed);
return;
}
//默認等級爲LV1
setbackground(LV1);
initControlWidget();
startGame();
}
/**
* 暫停遊戲
* @brief Panel::on_pbt_pauseGame_clicked
*/
void Panel::on_pbt_pauseGame_clicked()
{
if(m_isPauseGame)
{
return;
}
m_isPauseGame = true;
m_currentBox->slot_stopTimer();
ui->pbt_startGame->setEnabled(true);
QMessageBox::information(this,"提示","暫停遊戲!",QMessageBox::Yes);
}
/**
* 重新開始遊戲
* @brief Panel::on_pbt_restart_clicked
*/
void Panel::on_pbt_restart_clicked()
{
m_currentBox->slot_stopTimer();
m_currentBox->clearBoxGroup();
m_nextBox->clearBoxGroup(true);
//先將當前的小正方形組移出遊戲框,防止下面的清除item將該方塊組清除了
m_currentBox->setPos(290,55);
ui->LCDNum_Score->display(0);
//清空視圖中所有的小方塊
foreach (QGraphicsItem *item, m_scene->items(34, 34, 204, 404, Qt::ContainsItemShape,Qt::AscendingOrder)) {
// 先從場景中移除小方塊,因爲使用deleteLater()是在返回主事件循環後才銷燬
// 小方塊的,爲了在出現新的方塊組時不發生碰撞,所以需要先從場景中移除小方塊
m_scene->removeItem(item);
onePiece *piece = (onePiece*) item;
piece->deleteLater();
}
m_isPauseGame = false;
on_pbt_startGame_clicked();
}
/**
* 停止遊戲
* @brief Panel::on_pbt_stopGame_clicked
*/
void Panel::on_pbt_stopGame_clicked()
{
m_currentBox->slot_stopTimer();
slot_gameOver();
}
/**清除滿行的小方塊
* @brief Panel::slot_clearFullRows
*/
void Panel::slot_clearFullRows()
{
m_rowList.clear();
//獲取比一行方格多行的所有小方塊,不包含最高的一行
for(int i = 414;i > 35; i-=20)
{
//返回可視區域(202*22)內所有的完全可視的item
QList<QGraphicsItem *> itemList = m_scene->items(34,i,204,22,Qt::ContainsItemShape,Qt::AscendingOrder);
// qDebug() << "可是區域內的item數:" << itemList.count();
//已滿
if(itemList.count() == 10)
{
//遍歷列表刪除小方塊
foreach (QGraphicsItem *item, itemList) {
onePiece *piece = (onePiece *)item;
//模糊效果,先放大再縮小
QGraphicsBlurEffect *blurEffect = new QGraphicsBlurEffect;
piece->setGraphicsEffect(blurEffect);
QPropertyAnimation *animation = new QPropertyAnimation(piece,"scale");
animation->setDuration(250);
animation->setEasingCurve(QEasingCurve::OutBounce);
animation->setStartValue(4);
animation->setEndValue(0.25);
animation->start(QAbstractAnimation::DeleteWhenStopped);
connect(animation,SIGNAL(finished()),piece,SLOT(deleteLater()));
}
m_mediaPlayer->play();
//記錄滿行的行地址
m_rowList.append(i);
}
}
// qDebug() << "滿行的行數:" << m_rowList.size();
//存在滿行,刪除後將上面的方塊下移
if(!m_rowList.isEmpty())
{
//等待所有的小正方形都銷燬後再將上方的小正方形向下移動
QTimer::singleShot(300,this,SLOT(slot_moveBox()));
}else //直接創建新的方塊組
{
m_currentBox->createBox(QPointF(135,55), m_nextBox->getCurrentBoxType());
// 清空並銷燬提示方塊組中的所有小方塊
m_nextBox->clearBoxGroup(true);
if(!m_isGameOver)
{
m_nextBox->createBox(QPointF(290,55));
}
}
}
void Panel::slot_gameOver()
{
// qDebug() << "game over";
m_isGameOver = true;
QMessageBox::information(this,"提示",QString("您的遊戲得分爲%1!").arg(ui->LCDNum_Score->value()),QMessageBox::Yes);
ui->LCDNum_Score->display(0);
m_currentBox->clearFocus();
setbackground(LV0);
initControlWidget();
m_isPauseGame = false;
//初始化界面
m_currentBox->clearBoxGroup(true);
m_nextBox->clearBoxGroup(true);
//先將當前的小正方形組移出遊戲框,防止下面的清除item將該方塊組清除了
m_currentBox->setPos(290,55);
//清空視圖中所有的小方塊
foreach (QGraphicsItem *item, m_scene->items(34, 34, 204, 404, Qt::ContainsItemShape,Qt::AscendingOrder)) {
// 先從場景中移除小方塊,因爲使用deleteLater()是在返回主事件循環後才銷燬
// 小方塊的,爲了在出現新的方塊組時不發生碰撞,所以需要先從場景中移除小方塊
m_scene->removeItem(item);
onePiece *piece = (onePiece*) item;
piece->deleteLater();
}
}
/**清空滿行的小方塊後向下移動上面的小方塊
* @brief Panel::slot_moveBox
*/
void Panel::slot_moveBox()
{
// 從位置最靠上的滿行開始
for (int i = m_rowList.count(); i > 0; i--)
{
foreach (QGraphicsItem *item, m_scene->items(34, 34, 206, m_rowList.at(i-1) - 32, Qt::ContainsItemShape,Qt::AscendingOrder)) {
item->moveBy(0, 20);
}
}
// 更新分數
updateScore(m_rowList.count());
// 將滿行列表清空爲0
m_rowList.clear();
// 等所有行下移以後再出現新的方塊組
m_currentBox->createBox(QPointF(135,55), m_nextBox->getCurrentBoxType());
// 清空並銷燬提示方塊組中的所有小方塊
m_nextBox->clearBoxGroup(true);
m_nextBox->createBox(QPointF(290,55));
}