使用(C++)QT实现经典小游戏(俄罗斯方块)
一、简介
学习QT有段时间了,但是也没用来做过啥,这两日就突然想到了这个游戏,于是就打算用QT写一个,也不是纯纯自己写的代码,在写之前我也是找了几个别人的项目看了一下,学习了框架的搭建,和某些类的使用。
首先我也是将整个程序分作了四块:
一、方块类:主要就是对每个方块的坐标的一个封装
二、游戏区域:根据实时的要求,根据坐标画出方块
三、下一块方块:刷新下一块方块
四、计分区域:根据得分显示关卡、分数等
二、代码实现
在代码中都已经写了注释了,外面就不多累述了
1.ui界面
NextArea和GameArea都是由Qwidget提升上来的。
2.item方块类
2.1头文件
/*
* 俄罗斯方块的方块类文件
*/
#ifndef ITEM_H
#define ITEM_H
#pragma once
#include <QObject>
#include <QWidget>
#include <QVector>
#include <QPoint>
#include <QPainter>
typedef QVector<QPoint> povector; //坐标容器
enum ItemType//7种方块,四种朝向
{
ItemType_I = 0,
ItemType_L1,
ItemType_L2,
ItemType_T,
ItemType_O,
ItemType_Z1,
ItemType_Z2,
ItemType_MAX,
};
class Item
{
public:
Item(){}
Item(ItemType type,int direction);//有参构造方块
~Item(){}
void NewItem(int random_number);//通过随机的一个数来创建一个新的方块
void initpoint(ItemType type,int direction);//根据方块的类型和朝向初始化四个小方块的坐标
ItemType type(); //返回方块的类型
int direction(); //返回方块的朝向
void ClearPoints();//清除坐标信息
void drawItem(QPainter &painter,int x,int y,int width,int height); //根据坐标和宽高画图形
void changedirection(int direction=1); //改变方块的朝向,我的朝向加1即为下一个朝向,顺时针旋转90°
void moveItem(int x,int y);//横向移动x格,竖向移动y格
void movetoItem(int x,int y);//移动到(x,y)位置
void AddPoints(povector& points); //添加方块格子坐标
void Deleterow(int y); //删除坐标为y的一行
void MoveDown(int nRow, int y);//删除行以后其它的方块下移
public:
ItemType mytype; //我的方块
int mydirection; //我的方块朝向
QPoint mypos; //我的方块位置坐标
povector myPoint; //我的方块四小块的坐标
};
#endif // ITEM_H
2.2源文件
#include "item.h"
//创建方块
void Item::NewItem(int random_number)
{
myPoint.clear();
qsrand(random_number);//获取随机数
ItemType type = (ItemType)(qrand()%ItemType_MAX); // 产生随机的方块类型
int direction = qrand()%4; 产生随机的方块的朝向
initpoint(type,direction);
mytype = type;
mydirection = direction;
}
//初始化方块位置信息
void Item::initpoint(ItemType type, int direction)
{
direction = 0;
switch (type)
{
case ItemType_I://长条形
{
if(0==direction%2)//朝向0 2都是横长条
{
for (int i = 0; i < 4; i++)
{
myPoint.append(mypos + QPoint( i,0));
}
}
else//朝向1 3都是竖长条
{
for (int i = 0; i < 4; i++)
{
myPoint.append(mypos + QPoint(0,i-3));
}
}
break;
}
case ItemType_L1://右枪形
{
if(0==direction)//朝向0
{
myPoint.append(mypos + QPoint( 0,0));// 1 0 0
myPoint.append(mypos + QPoint( 0,1));// 1 0 0
myPoint.append(mypos + QPoint( 0,2));// 1 1 0
myPoint.append(mypos + QPoint( 1,2));// 0 0 0
}
else if(1==direction)//朝向1
{
myPoint.append(mypos + QPoint( 0,1));// 0 0 0
myPoint.append(mypos + QPoint( 1,1));// 1 1 1
myPoint.append(mypos + QPoint( 2,1));// 1 0 0
myPoint.append(mypos + QPoint( 0,2));// 0 0 0
}
else if(2==direction)//朝向2
{
myPoint.append(mypos + QPoint( 0,0));
myPoint.append(mypos + QPoint( 1,0));// 1 1 0
myPoint.append(mypos + QPoint( 1,1));// 0 1 0
myPoint.append(mypos + QPoint( 1,2));// 0 1 0
}
else//朝向3
{
myPoint.append(mypos + QPoint( 0,2));//0 0 0
myPoint.append(mypos + QPoint( 1,2));//0 0 1
myPoint.append(mypos + QPoint( 2,2));//1 1 1
myPoint.append(mypos + QPoint( 2,1));//
}
break;
}
case ItemType_L2://左枪形
{
if(0==direction)//朝向0
{
myPoint.append(mypos + QPoint( 1,0));//0 1 0 0
myPoint.append(mypos + QPoint( 1,1));//0 1 0 0
myPoint.append(mypos + QPoint( 1,2));//1 1 0 0
myPoint.append(mypos + QPoint( 0,2));//0 0 0 0
}
else if(1==direction)//朝向1
{
myPoint.append(mypos + QPoint( 0,1));// 0 0 0
myPoint.append(mypos + QPoint( 0,2));// 1 0 0
myPoint.append(mypos + QPoint( 1,2));// 1 1 1
myPoint.append(mypos + QPoint( 2,2));// 0 0 0
}
else if(2==direction)//朝向2
{
myPoint.append(mypos + QPoint( 0,0));//
myPoint.append(mypos + QPoint( 1,0));// 1 1 0
myPoint.append(mypos + QPoint( 0,1));// 1 0 0
myPoint.append(mypos + QPoint( 0,2));// 1 0 0
}
else//朝向3
{
myPoint.append(mypos + QPoint( 0,1));//0 0 0 0
myPoint.append(mypos + QPoint( 1,1));//1 1 1 0
myPoint.append(mypos + QPoint( 2,1));//0 0 1 0
myPoint.append(mypos + QPoint( 2,2));//0 0 0 0
}
break;
}
case ItemType_T://T形
{
if(0==direction)//朝向0
{
myPoint.append(mypos + QPoint( 1,0));//0 1 0 0
myPoint.append(mypos + QPoint( 1,1));//1 1 1 0
myPoint.append(mypos + QPoint( 0,1));//0 0 0 0
myPoint.append(mypos + QPoint( 2,1));//0 0 0 0
}
else if(1==direction)//朝向1
{
myPoint.append(mypos + QPoint( 0,0));// 1 0 0
myPoint.append(mypos + QPoint( 0,1));// 1 1 0
myPoint.append(mypos + QPoint( 0,2));// 1 0 0
myPoint.append(mypos + QPoint( 1,1));// 0 0 0
}
else if(2==direction)//朝向2
{
myPoint.append(mypos + QPoint( 0,0));
myPoint.append(mypos + QPoint( 1,0));//1 1 1 0
myPoint.append(mypos + QPoint( 2,0));//0 1 0 0
myPoint.append(mypos + QPoint( 1,1));//0 0 0 0
}
else//朝向3
{
myPoint.append(mypos + QPoint( 1,0));//0 1 0 0
myPoint.append(mypos + QPoint( 0,1));//1 1 0 0
myPoint.append(mypos + QPoint( 1,1));//0 1 0 0
myPoint.append(mypos + QPoint( 1,2));//0 0 0 0
}
break;
}
case ItemType_O://正方形
{
myPoint.append(mypos + QPoint( 0,0));//1 1 0 0
myPoint.append(mypos + QPoint( 0,1));//1 1 0 0
myPoint.append(mypos + QPoint( 1,0));//0 0 0 0
myPoint.append(mypos + QPoint( 1,1));//0 0 0 0
break;
}
case ItemType_Z1://右Z形
{
if(0==direction%2)//朝向0/2
{
myPoint.append(mypos + QPoint( 0,0));// 1 0 0
myPoint.append(mypos + QPoint( 0,1));// 1 1 0
myPoint.append(mypos + QPoint( 1,1));// 0 1 0
myPoint.append(mypos + QPoint( 1,2));// 0 0 0
}
else//朝向1/3
{
myPoint.append(mypos + QPoint( 0,1));//
myPoint.append(mypos + QPoint( 1,0));//0 1 1 0
myPoint.append(mypos + QPoint( 1,1));//1 1 0 0
myPoint.append(mypos + QPoint( 2,0));//0 0 0 0
}
break;
}
case ItemType_Z2://左Z形
{
if(0==direction%2)//朝向0/2
{
myPoint.append(mypos + QPoint( 1,0));// 0 1 0
myPoint.append(mypos + QPoint( 0,1));// 1 1 0
myPoint.append(mypos + QPoint( 1,1));// 1 0 0
myPoint.append(mypos + QPoint( 0,2));// 0 0 0
}
else//朝向1/3
{
myPoint.append(mypos + QPoint( 0,0));
myPoint.append(mypos + QPoint( 1,0));//1 1 0 0
myPoint.append(mypos + QPoint( 1,1));//0 1 1 0
myPoint.append(mypos + QPoint( 2,1));//0 0 0 0
}
break;
}
default:
break;
}
}
//方块类型
ItemType Item::type()
{
return mytype;
}
//方块朝向
int Item::direction()
{
return mydirection;
}
//清除方块位置信息
void Item::ClearPoints()
{
myPoint.clear();
}
//画方块
void Item::drawItem(QPainter &painter,int x,int y,int width, int height)
{
for (int i = 0; i < myPoint.size(); i++)
{
QPoint pt = myPoint[i];
if(pt.y()>=1)
{
painter.drawRect(QRect(x+pt.x() * width,y+pt.y() * height, width, height));
}
}
}
//改变方块朝向
void Item::changedirection(int direction)
{
mydirection = (mydirection+direction)%4;
initpoint(mytype,mydirection);
}
//移动方块
void Item::moveItem(int x, int y)
{
for (int i = 0; i < myPoint.size(); i++)
{
int x1 = myPoint[i].x() + x;
int y1 = myPoint[i].y() + y;
myPoint[i].setX(x1);
myPoint[i].setY(y1);
}
mypos += QPoint(x, y);
}
//将方块移动到指定位置
void Item::movetoItem(int x, int y)
{
for (int i = 0; i < myPoint.size(); i++)
{
int x1 = myPoint[i].x()-mypos.x() + x;
int y1 = myPoint[i].y()-mypos.y() + y;
myPoint[i].setX(x1);
myPoint[i].setY(y1);
}
mypos = QPoint(x, y);
}
//添加方块坐标
void Item::AddPoints(povector &points)
{
for(int i=0;i<points.size();i++) // 遍历Point
{
if(!myPoint.contains(points[i])) //如果myPoint中没有
myPoint.append(points[i]); //添加进myPoint
}
}
//第nRow行以上的部分下移y行,用在消格之后
void Item::MoveDown(int nRow, int y)
{
for(int i=0;i<myPoint.size();i++) //遍历myPoint ( 方块类形坐标容噐)
{
if(myPoint[i].y()<nRow) //行坐标小于nRow 的
myPoint[i].setY(myPoint[i].y()+y); //行标加y,后回写
}
}
//删除第y行
void Item::Deleterow(int y)
{
QVector<QPoint> newPoints; //新建一个新的容器
for(int i=0;i<myPoint.size();i++) //遍历mPoints ( 方块类形坐标容噐)
{
if(myPoint[i].y()!=y) //如果行坐标不等于y,
newPoints.append(myPoint[i]); //添加到新的点容器
}
myPoint=newPoints; //新的容器回写到mPoints,等于y的方块便不再绘画
}
3.GameArea游戏窗口
3.1头文件
/*
* 俄罗斯方块的游戏区域文件
*/
#ifndef GAMEAREA_H
#define GAMEAREA_H
#include <QWidget>
#include "item.h"
#include <QTimerEvent>
#include <QMessageBox>
#include <QKeyEvent>
#include <QTime>
class GameArea : public QWidget
{
Q_OBJECT
public:
explicit GameArea(QWidget *parent = nullptr);
void DrawBKRects(); //画游戏区域
void DrawFixedRects(); //画下落后已固定不动的方块
void DrawCurItem(); //画当前下落中的方块
void NewGame(); //创建新游戏界面
void KeyPressed(int key); //收到按键值处理
bool HitSide(); //判断当前下落方块是否超左右边界
bool HitBottom(); //判断当前下落方块是否达到底部
bool HitTop(); //判断当前下落方块是否达到顶部
void AddToFixedRects(); //把当前方块加入到 固定方块
void Deleterow(); //删除完整的行
int GetLevelTime(int level); //获取不同等级关卡对应的定时器时间,关卡越高,时间越快(短)。比如1关=1s,2关=900ms,3关=800ms
signals:
void sigUpdateNextItem(ItemType type, int direction); //下一个方块刷新信号
void sigUpdateScore(int nScore); //刷新分数
void sigUpdateLevel(int nSpeed); //刷新等级
void sigPause(bool bPaused); //暂停信号
protected:
void paintEvent(QPaintEvent *e); //绘图事件
void timerEvent(QTimerEvent *e); //定时器事件
private:
Item myFixItems; //已落下、固定住了的方块们
Item myCurItem; //当前移动中的方块
Item myNextItem; //下一个方块
int myTimerID; //定时器ID
int myScore; //得分
int myLevel; //关卡
bool myStop; //是否暂停
};
#endif // GAMEAREA_H
3.2源文件
#include "gamearea.h"
#include <QDebug>
//默认游戏区域为15*20的单元格,每个单元格尺寸40*40像素
#define MAX_COLUME 15
#define MAX_ROW 20
#define RECT_WIDTH 40
#define RECT_HEIGHT 40
//GameArea类初始化
GameArea::GameArea(QWidget *parent) : QWidget(parent)
{
myScore = 0;
myLevel = 1;
myStop = false;
setMinimumSize(MAX_COLUME*RECT_WIDTH, MAX_ROW*RECT_HEIGHT);
}
//画游戏区域的背景
void GameArea::DrawBKRects()
{
//画背景边框
QPainter painter(this);
painter.setBrush(QColor("#696969"));
painter.setPen(Qt::NoPen);
for (int i = 0; i < MAX_COLUME; i++)
{
for (int j = 0; j < MAX_ROW; j++)
{
if (i == 0 || i == MAX_COLUME - 1 || j == 0 || j == MAX_ROW - 1)
{
painter.drawRect(i*RECT_WIDTH, j*RECT_HEIGHT, RECT_WIDTH, RECT_HEIGHT);
}
}
}
}
//画已经下落到底部固定的方块
void GameArea::DrawFixedRects()
{
QPainter painter(this);
painter.setBrush(QColor("#D3D3D3"));
painter.setPen(QPen(QColor(Qt::black), 1));
myFixItems.drawItem(painter,0,0,RECT_WIDTH,RECT_HEIGHT);
}
//画当前正在下落中的方块
void GameArea::DrawCurItem()
{
QPainter painter(this);
painter.setBrush(QColor("#FFDEAD"));
painter.setPen(QPen(QColor(Qt::black), 1));
myCurItem.drawItem(painter,0,0,RECT_WIDTH,RECT_HEIGHT);
}
//创建一个新的游戏界面
void GameArea::NewGame()
{
myFixItems.ClearPoints();
myCurItem.NewItem(QTime::currentTime().msec());//创建新的方块,当前的和下一个应不一样,所以随机数应不同
myCurItem.movetoItem(MAX_COLUME/2-1,1); //当前下落方块移动到中心位置
myNextItem.NewItem(QTime::currentTime().second());
emit sigUpdateNextItem(myNextItem.type(),myNextItem.direction());//发送信号刷新下一块区域
myScore=0;
myLevel=1;
myTimerID = startTimer(GetLevelTime(myLevel)); //开启定时器
}
//收到了按键信息
void GameArea::KeyPressed(int key)
{
int x=0,y=0;
switch (key) {
case Qt::Key_Up:
{
myCurItem.changedirection(1);
if (HitSide()||HitBottom())//左右下到了边界
{
myCurItem.changedirection(-1);
}
return;
}
case Qt::Key_Right:
{
x=1;
break;
}
case Qt::Key_Down:
{
y=1;
break;
}
case Qt::Key_Left:
{
x=-1;
break;
}
case Qt::Key_Space:
{
while (1)
{
myCurItem.moveItem(0,1);
if(HitBottom())
{
myCurItem.moveItem(0,-1);
break;
}
}
return;
}
case Qt::Key_Return:
{
if(myCurItem.myPoint.size()!=0)
{
if(myStop == true)
myStop = false;
else
myStop = true;
break;
}
}
}
myCurItem.moveItem(x,y);
if (HitSide()||HitBottom())//左右下到了边界
{
myCurItem.moveItem(-x, -y);
}
}
//如果碰到了左右边界
bool GameArea::HitSide()
{
for (int i=0;i<myCurItem.myPoint.size();i++)
{
QPoint pt=myCurItem.myPoint[i];
if(pt.x()<=0||pt.x()>=MAX_COLUME-1) //如果x座标小于等于1或大于等于MAX_COLUME-1,则表示撞上左右边界了
return true;
}
return false;
}
//如果到了底部
bool GameArea::HitBottom()
{
for (int i=0;i<myCurItem.myPoint.size();i++)
{
QPoint pt=myCurItem.myPoint[i];
if(pt.y()>=MAX_ROW-1) //如果y座标大于等于RECT_ROWS-1,则表示撞上下边界了
return true;
if(myFixItems.myPoint.contains(pt))// 如果固定不动的方块的座标包含当前下落方块的座标,则表示下到底了
return true;
}
return false;
}
//如果碰到了顶部
bool GameArea::HitTop()
{
for (int i=0;i<myCurItem.myPoint.size();i++)
{
QPoint pt=myCurItem.myPoint[i];
if(pt.y()<=1) //如果y座标大于等于RECT_ROWS-1,则表示撞上下边界了
return true;
}
return false;
}
//将当前的坐标给固定的方块
void GameArea::AddToFixedRects()
{
myFixItems.AddPoints(myCurItem.myPoint);
}
//删除完整的行
void GameArea::Deleterow()
{
int nRowsDeleted = 0; //记录消的行数
for (int i = 1; i<MAX_ROW-1; i++) //遍历游戏区座标
{
int nCount = 0;
for (int j = 1; j<MAX_COLUME-1; j++)
{
if (myFixItems.myPoint.contains(QPoint(j,i))) //判定每行有多少位置有方块
{
nCount++; // 每行方块的个数
}
}
if (nCount == MAX_COLUME-2)// 如果每行的个数等于MAX_COLUME-2, 则代表是满的
{
myFixItems.Deleterow(i); //将这一行删除
myFixItems.MoveDown(i,1); //消除行之上的内容下移一个单位
nRowsDeleted++;
}
}
//一次元素落下,最多可能消4行
//一次消除的越多,得分越多
if (nRowsDeleted == 1)
{
myScore += 20;
}
else if (nRowsDeleted == 2)
{
myScore += 60;
}
else if (nRowsDeleted == 3)
{
myScore += 120;
}
else if (nRowsDeleted == 4)
{
myScore += 200;
}
emit sigUpdateScore(myScore); //更新MainWindow界面得分
//粗略使用每1000分一关
if(myScore >= 1000 * myLevel)
{
myLevel++;
//随关卡增加下落速度,即把定时器加快
killTimer(myTimerID);
myTimerID = startTimer( GetLevelTime(myLevel));
emit sigUpdateLevel(myLevel); //更新MainWindow界面关卡
}
}
//当前等级的速度
int GameArea::GetLevelTime(int level)
{
if(level>10)
{
return 400;
}
else
{
return (19-level)*50;
}
}
//绘画事件重写
void GameArea::paintEvent(QPaintEvent *)
{
DrawBKRects();
DrawFixedRects();
DrawCurItem();
if(myStop)//暂停中
{
QFont font;
font.setPixelSize(100);
QPainter painter(this);
painter.setBrush(Qt::NoBrush);
painter.setFont(font);
painter.setPen(QPen(QColor("red"),1));
painter.drawText(rect(), Qt::AlignCenter, "暂停");
}
update();
}
//定时器重写
void GameArea::timerEvent(QTimerEvent *e)
{
if(myStop)
{
return;
}
else
{
if(myTimerID==e->timerId())
{
myCurItem.moveItem(0,1);
if (HitBottom())//碰到底部
{
myCurItem.moveItem(0, -1); //移动到原位
AddToFixedRects(); //将方块的坐标给固定方块
Deleterow();//判断是否有完整的行,然后删除
if(HitTop())//碰到了顶部,游戏结束
{
killTimer(myTimerID);
QMessageBox::information(NULL, "GAME OVER", "GAME OVER", QMessageBox::Yes, QMessageBox::Yes);
myFixItems.ClearPoints();
myCurItem.ClearPoints();
return;
}
myCurItem = myNextItem; //下一个方块给当前方块赋值
myCurItem.movetoItem(MAX_COLUME/2-1, 1);//移动到中心位置
myNextItem.NewItem(QTime::currentTime().msec());//下一个方块继续创建
emit sigUpdateNextItem(myNextItem.type(), myNextItem.direction());//发送信号下一块区域刷新方块
}
}
}
}
4.NextArea刷新下一块窗口
4.1头文件
#ifndef NEXTAREA_H
#define NEXTAREA_H
#include <QObject>
#include <QWidget>
#include "item.h"
class NextArea:public QWidget
{
Q_OBJECT
public:
explicit NextArea(QWidget *parent = nullptr);
private:
void paintEvent(QPaintEvent *event);
public slots:
void UpdateNextItem(ItemType type, int direction);//刷新方块
private:
Item myItem;
};
#endif // NEXTAREA_H
4.2源文件
#include "nextarea.h"
NextArea::NextArea(QWidget *parent): QWidget(parent)
{
}
void NextArea::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setBrush(QColor("#FFDEAD"));
painter.setPen(QPen(QColor(Qt::black),1));
int xStart = 0; //为了绘制在显示下一个方块区域的中部
int yStart = 80;
int w = 30;
int h = 30;
for(int i=0;i<myItem.myPoint.size();i++)
{
QPoint pt = myItem.myPoint[i];
int x = xStart + pt.x() * w;
int y = yStart + pt.y() * h;
painter.drawRect(x, y, w, h);
}
update();
}
void NextArea::UpdateNextItem(ItemType type, int direction)
{
myItem.initpoint(type,direction);
}
5.主窗口
5.1头文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMediaPlayer>
#include <QMediaPlaylist>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
void keyPressEvent(QKeyEvent *e);//按键事件重写
private slots:
void UpdateLevel(int Level);//刷新等级
void UpdateScore(int Score);//刷新分数
void on_pbPuase_clicked();//开始按钮
void on_checkBox_stateChanged(int arg1);//音乐播放
private:
Ui::MainWindow *ui;
QMediaPlayer *player;
QMediaPlaylist *Playlist;
};
#endif // MAINWINDOW_H
5.2源文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
setFixedSize(1000,800); //设置窗体为固定大小
setWindowTitle(tr("俄罗斯方块"));//设置窗体标题
connect(ui->widgetGameArea,&GameArea::sigUpdateLevel,this,&MainWindow::UpdateLevel);//等级
connect(ui->widgetGameArea,&GameArea::sigUpdateScore,this,&MainWindow::UpdateScore);//分数
connect(ui->widgetGameArea,&GameArea::sigUpdateNextItem,ui->widgetNextArea,&NextArea::UpdateNextItem);//下一块
Playlist =new QMediaPlaylist; //创建新的播放清单
player=new QMediaPlayer; //创建新的播放器
Playlist->addMedia(QUrl::fromLocalFile("F:/MyQT/Teris/media/1.mp3")); //往播放清单中添加音乐文件
Playlist->addMedia(QUrl::fromLocalFile("F:/MyQT/Teris/media/2.mp3"));
Playlist->addMedia(QUrl::fromLocalFile("F:/MyQT/Teris/media/3.mp3"));
Playlist->setCurrentIndex(0); //设置默认播放开始位置
Playlist->setPlaybackMode(QMediaPlaylist::Loop); //设置循环播放
player->setPlaylist(Playlist); //播放清单导入播放器
player->play(); //播放器开播
}
MainWindow::~MainWindow()
{
delete ui;
}
//按键由窗口接收,所以传递过去
void MainWindow::keyPressEvent(QKeyEvent *e)
{
ui->widgetGameArea->KeyPressed(e->key());
QMainWindow::keyPressEvent(e);
}
void MainWindow::UpdateLevel(int level)
{
ui->labelLevel->setText(QString::number(level));
}
void MainWindow::UpdateScore(int score)
{
ui->labelScore->setText(QString::number(score));
}
//开始游戏
void MainWindow::on_pbPuase_clicked()
{
ui->widgetGameArea->NewGame();
}
//音乐是否播放槽函数
void MainWindow::on_checkBox_stateChanged(int arg1)
{
if(arg1)
player->play();
else
player->stop();
}
三、概述
对这个游戏来看,我自己的理解很直白的就是对数组的应用。在这个程序中,最核心的一点在于QVector<QPoint>这个坐标容器,在这个容器中,保存着所有需要画的方块的坐标,这个游戏的运行就是对这个容器里面的坐标增删改查的操作。
1.增
具体表现就是在程序中落到底部的固定方块,方块到了底部以后,将坐标加入到这个容器中,也就实现了,方块的堆积。
2.删
这个的直观表现就是完整行的消除,遍历整个游戏区域,每行是有方块限制的,当满了以后,便可以删除相关的坐标,便实现了消除。
3.改
方块的形状改变便是更改的坐标,在设计中,每一个方块都是由各自的坐标的,当需要改变形状时,返回了当前形状的坐标。
4.查
在下落的过程中,会一直遍历整个区域的坐标,当下落的方块中有存在了与固定方块相同的坐标时,便代表着该停止了,已经触碰了。