Qt文档阅读笔记-Tetrix Example解析

文章详细介绍了俄罗斯方块游戏的实现,包括TetrixWindow类负责界面展示,TetrixBoard类包含游戏逻辑和界面渲染,以及TetrixPiece类处理分数信息。游戏的控制通过键盘输入,如左右键移动,上下键旋转,D键加速下落,空格键立即落地。文章还展示了各个类的关键函数和游戏流程的控制方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文的俄罗斯方块实例官方的一个经典实例。

俄罗斯方块这个游戏就是从顶部落下方块到底部,把每行都填充满。当一行被填充满,这行就会被移除,玩家就会获取分数。顶部的方块都会依次落下,如果有多行被填充满了,那么会移除多行,获取对应的分数。

键盘左键控制方块向左移动,键盘右键控制方块向右移动,键盘上键使得方块逆时针旋转90°,键盘下键使得方块顺时针旋转90°。

键盘D键使得方块加速落下,键盘空格使得方块立即落下。

本俄罗斯方块实例由3个类构成:

TetrixWindow:构造游戏的整体界面,也就是肉眼看到的东西(不含游戏逻辑)都是这个类负责。

TetrixBoard:包含游戏逻辑、键盘、展示方块、游戏区域。

TetrixPiece:统计分数信息等。

从中可以知道,本实例最复杂的类就是TetrixBoard,包含游戏逻辑和一些界面渲染。TetrixWindow和TetrixPiece就比较简单了。

TetrixWindow类定义

TetrixWindow类用于展示游戏信息并且画出游戏区域:

 class TetrixWindow : public QWidget
 {
     Q_OBJECT

 public:
     TetrixWindow();

 private:
     QLabel *createLabel(const QString &text);

     TetrixBoard *board;
     QLabel *nextPieceLabel;
     QLCDNumber *scoreLcd;
     QLCDNumber *levelLcd;
     QLCDNumber *linesLcd;
     QPushButton *startButton;
     QPushButton *quitButton;
     QPushButton *pauseButton;
 };

在类的private中有几个成员变量,包括前端画线,各种挂机和按钮,按钮有开始游戏,暂停当前游戏和退出。

TetrixWindow继承了QWidget,但QWidget父类不能构造自己想创建的结构,所以,一般用上面这种方式创建程序员想要的界面。

TetrixWindow类声明

构造函数为游戏创建元素:

 TetrixWindow::TetrixWindow()
 {
     board = new TetrixBoard;

在构造函数里面创建TetrixBoard的实例,用于画出游戏区域,标签,下一个方块。标签初始为空。

3个QLCDNumber对象用于展示分数、等级、移除了多少行。程序运行时给他们一个初始值,当游戏开始时,再给数据进行填充。

scoreLcd = new QLCDNumber(5);
scoreLcd->setSegmentStyle(QLCDNumber::Filled);

创建了3个按钮并且绑定了快捷键,用于开始新游戏,暂停当前游戏,退出应用:

startButton = new QPushButton(tr("&Start"));
startButton->setFocusPolicy(Qt::NoFocus);
quitButton = new QPushButton(tr("&Quit"));
quitButton->setFocusPolicy(Qt::NoFocus);
pauseButton = new QPushButton(tr("&Pause"));
pauseButton->setFocusPolicy(Qt::NoFocus);

上面的代码说明3个按钮不接受键盘的聚焦;但他需要和TetrixBoard示例的槽函数关联。虽然设置了Qt::NoFocus,但是如果带上键盘Alt的按键,仍然会收到。

按钮的clicked()信号关联TextrixBoard的Start和Pause,并且关联QCoreApplication::quit()

     connect(startButton, &QPushButton::clicked, board, &TetrixBoard::start);
     connect(quitButton , &QPushButton::clicked, qApp, &QApplication::quit);
     connect(pauseButton, &QPushButton::clicked, board, &TetrixBoard::pause);
 #if __cplusplus >= 201402L
     connect(board, &TetrixBoard::scoreChanged,
             scoreLcd, qOverload<int>(&QLCDNumber::display));
     connect(board, &TetrixBoard::levelChanged,
             levelLcd, qOverload<int>(&QLCDNumber::display));
     connect(board, &TetrixBoard::linesRemovedChanged,
             linesLcd, qOverload<int>(&QLCDNumber::display));
 #else
     connect(board, &TetrixBoard::scoreChanged,
             scoreLcd, QOverload<int>::of(&QLCDNumber::display));
     connect(board, &TetrixBoard::levelChanged,
             levelLcd, QOverload<int>::of(&QLCDNumber::display));
     connect(board, &TetrixBoard::linesRemovedChanged,
             linesLcd, QOverload<int>::of(&QLCDNumber::display));
 #endif

board中有些信号关联了LCD关键的一些槽函数,用于更新分数、等级、游戏区域移除了多少行。

将标签、LCD挂件、board、一些使用createLabel函数创建的label放到QGridLayout:

     QGridLayout *layout = new QGridLayout;
     layout->addWidget(createLabel(tr("NEXT")), 0, 0);
     layout->addWidget(nextPieceLabel, 1, 0);
     layout->addWidget(createLabel(tr("LEVEL")), 2, 0);
     layout->addWidget(levelLcd, 3, 0);
     layout->addWidget(startButton, 4, 0);
     layout->addWidget(board, 0, 1, 6, 1);
     layout->addWidget(createLabel(tr("SCORE")), 0, 2);
     layout->addWidget(scoreLcd, 1, 2);
     layout->addWidget(createLabel(tr("LINES REMOVED")), 2, 2);
     layout->addWidget(linesLcd, 3, 2);
     layout->addWidget(quitButton, 4, 2);
     layout->addWidget(pauseButton, 5, 2);
     setLayout(layout);

     setWindowTitle(tr("Tetrix"));
     resize(550, 370);
 }

最后将grid放到widget中,并设置程序的标题,应用程序的大小。

createLabel()这个函数在堆区创建label,并且将label居中,最后返回

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT1995

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值