基于Qt5图形视图框架的“俄罗斯方块”

本文介绍了如何利用Qt5的图形视图框架QGraphicsView实现俄罗斯方块游戏。详细讲解了图形视图框架的核心组件和原理,包括QGraphicsItem、QGraphicsScene和QGraphicsView的使用。此外,还探讨了俄罗斯方块的逻辑、方块类型,并给出了代码实现的概要,包括onePiece、pieceBox和界面类panel的头文件和源码。
摘要由CSDN通过智能技术生成

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;   //存放新方块组的四个方块
};

#
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值