Qt 实现 别踩白块儿。

一、实现思路

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();
}

四、源码:

Qt小游戏_别踩白块儿

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值