一、实现思路
QPainter 绘制 游戏界面
PS:根据方块坐标链表绘制所有方块
支持两种操作方式
PS:鼠标事件 和 键盘事件(Q,W,E,R,T)
定时器(10ms) 刷新 方块坐标数据
根据得分修改方块的步进速度
PS:简单的 step = sum % 10;【自己可以修改成喜欢的规则】
二、实际效果
三、关键代码分析
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = whiteblock
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp \
blockdata.cpp \
testwidget.cpp
HEADERS += mainwindow.h \
blockdata.h \
testwidget.h
FORMS += mainwindow.ui \
testwidget.ui
#ifndef BLOCKDATA_H
#define BLOCKDATA_H
#include <stdio.h>
struct BData{
int x;
int y;
int width;
int height;
BData *next;
};
class BlockData
{
public:
BlockData();
~BlockData();
void init(BData **d,int x=0,int y=0,int width=0,int height=0); //初始化
void insert(BData *d); //插入数据
bool remove(int x,int y); //删除数据
bool remove(int x); //删除数据
void updata(int step); //更新数据
bool judge(int y); //判断数据
void clear(); //清空数据
BData* get(){ return head;} //读取数据
void show(); //显示数据
private:
BData *head;
BData *tail;
};
#endif // BLOCKDATA_H
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#ifndef TESTWIDGET_H
#define TESTWIDGET_H
#include <QWidget>
#include <QMouseEvent>
#include <QKeyEvent>
#include <QTimer>
#include "blockdata.h"
namespace Ui {
class TestWidget;
}
class TestWidget : public QWidget
{
Q_OBJECT
public:
explicit TestWidget(QWidget *parent = 0);
~TestWidget();
void setDSize(int width,int height); //设置方块宽高
void start(); //开始游戏
void restart(); //重新开始
protected:
void paintEvent(QPaintEvent *event); //绘制界面
void mousePressEvent(QMouseEvent *event); //点击事件
void keyReleaseEvent(QKeyEvent *event); //键盘事件
signals:
void failure(); //失败信号
void value(int value); //成绩信号
private slots:
void updateData(); //更新数据
private:
Ui::TestWidget *ui;
QTimer timer; //定时器
BlockData bData; //方块坐标数据类
int step; //步进速度
int Dwidth; //小方块宽度
int Dheight; //小方块高度
bool isfailure; //失败标志
int sum; //总分
};
#endif // TESTWIDGET_H
#include "blockdata.h"
BlockData::BlockData()
{
head = NULL;
tail = NULL;
}
BlockData::~BlockData()
{
clear();
}
void BlockData::init(BData **d, int x, int y, int width, int height)
{
BData *n = *d;
n->x = x;
n->y = y;
n->width = width;
n->height = height;
n->next = NULL;
}
void BlockData::insert(BData *d)
{
if(!tail) {
head = d;
tail = d;
return;
}
tail->next = d;
tail = tail->next;
}
bool BlockData::remove(int x,int y)
{
if(!head)
return false;
if(x < head->x || head->x + head->width < x
|| y < head->y || head->y + head->height < y)
return false;
BData *n = head;
//头尾相同
if(n == tail) {
head = tail = NULL;
} else {
head = head->next;
}
delete n;
return true;
}
bool BlockData::remove(int x)
{
if(!head)
return false;
if(x < head->x || head->x + head->width < x)
return false;
BData *n = head;
//头尾相同
if(n == tail) {
head = tail = NULL;
} else {
head = head->next;
}
delete n;
return true;
}
void BlockData::updata(int step)
{
BData *n = head;
while(n) {
n->y += step;
n = n->next;
}
}
bool BlockData::judge(int y)
{
if(head && head->y >= y)
return false;
return true;
}
void BlockData::clear()
{
BData *n = head;
while(n) {
head = head->next;
delete n;
n = head;
}
tail = 0;
}
void BlockData::show()
{
BData *n = head;
while(n) {
printf("%d,%d,%d,%d\n",n->x,n->y,n->width,n->height);
n = n->next;
}
printf("====================\n");
fflush(stdout);
}
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
MainWindow::setWindowTitle(tr("钢琴块儿"));
connect(ui->widget,&TestWidget::value,this,[=](int value){
ui->label->setText(QString::number(value));
});
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
ui->widget->start();
ui->widget->setFocus();
}
void MainWindow::on_pushButton_2_clicked()
{
ui->widget->restart();
ui->widget->setFocus();
}
#include "testwidget.h"
#include "ui_testwidget.h"
#include <QPainter>
#include <QTime>
#include <QDebug>
TestWidget::TestWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::TestWidget)
{
ui->setupUi(this);
connect(&timer,&QTimer::timeout,this,&TestWidget::updateData);
timer.setInterval(10);
isfailure = false;
step = 1;
sum=0;
QTime time = QTime::currentTime();
qsrand(QTime(0,0,0).secsTo(time));
QTimer::singleShot(10,this,[=](){
setDSize(width()/5,height()/5);
});
}
TestWidget::~TestWidget()
{
delete ui;
}
void TestWidget::setDSize(int width, int height)
{
Dwidth = width;
Dheight = height;
}
void TestWidget::start()
{
timer.start();
}
void TestWidget::restart()
{
timer.stop();
bData.clear();
isfailure = false;
step = 1;
sum = 0;
emit value(sum);
timer.start();
}
void TestWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.fillRect(rect(),Qt::white);
painter.setBrush(Qt::black);
if(isfailure) {
int w = 200;
int h = 30;
QFont f;f.setPixelSize(32);
painter.setFont(f);
painter.drawText((width()-w)/2,(height()-h)/2,w,h,Qt::AlignCenter,"你已失败");
}else {
BData* d = bData.get();
while(d){
painter.drawRect(d->x,d->y,d->width,d->height);
d = d->next;
}
}
}
void TestWidget::mousePressEvent(QMouseEvent *event)
{
QPoint point = event->pos();
if(bData.remove(point.x(),point.y())) {
sum++;
emit value(sum);
//刷新速度
if(sum%10 == 0)
step++;
}
}
void TestWidget::keyReleaseEvent(QKeyEvent *event){
if(event->isAutoRepeat())
return;
bool _sum = false;
switch(event->key())
{
case Qt::Key_Q: _sum = bData.remove(Dwidth-1);break;
case Qt::Key_W: _sum = bData.remove(2*(Dwidth-1));break;
case Qt::Key_E: _sum = bData.remove(3*(Dwidth-1));break;
case Qt::Key_R: _sum = bData.remove(4*(Dwidth-1));break;
case Qt::Key_T: _sum = bData.remove(5*(Dwidth-1));break;
default:break;
}
if(_sum) {
sum++;
emit value(sum);
//刷新速度
if(sum%10 == 0)
step++;
}
}
void TestWidget::updateData()
{
static int _step = Dheight;
// 插入新值
if(_step >= Dheight) {
BData *d = new BData;
int x = qrand() % 4;
bData.init(&d,x*Dwidth,-Dheight,Dwidth,Dheight);
bData.insert(d);
_step = 0;
}
// 更新数据
bData.updata(step);
//判断失败条件
if(!bData.judge(height())) {
isfailure = true;
emit failure();
timer.stop();
}
_step+=step;
//刷新界面
update();
}