关于本章节中使用的图形绘制类,如QGraphicsView、QGraphicsScene等的详细使用说明请参见我的另一篇文章:
《图形绘制QGraphicsView、QGraphicsScene、QGraphicsItem、Qt GUI-CSDN博客》
本文将模仿坦克大战游戏,目前只绘制出一辆坦克,并能发射炮弹
源代码下载地址:https://download.csdn.net/download/zhouhui1982/88784330
main.cpp文件中代码
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QKeyEvent>
#include <QTimer>
//坦克类对象,构建坦克主体
class Tank : public QGraphicsRectItem {
public:
Tank() {
// 坦克身体
setRect(0, 0, 30, 50);
setBrush(Qt::blue);
// 炮塔
turret = new QGraphicsRectItem(10, -20, 10, 30);
turret->setParentItem(this);
// 设置炮塔颜色
turret->setBrush(Qt::red);
}
//重写键盘事件,判断上下左右、空格按钮
void keyPressEvent(QKeyEvent *event) override {
// Handle key presses to control the tank
switch (event->key()) {
case Qt::Key_Left:
moveBy(-10, 0);
break;
case Qt::Key_Right:
moveBy(10, 0);
break;
case Qt::Key_Up:
moveBy(0, -10);
break;
case Qt::Key_Down:
moveBy(0, 10);
break;
case Qt::Key_Space: //如果是空格键,发射炮弹
//绘制第一发炮弹
QGraphicsEllipseItem *bulletItem = new QGraphicsEllipseItem(0, 0, 5, 10);
bulletItem->setPos(mapToScene(12, -50));
bulletItem->setBrush(Qt::red);
scene()->addItem(bulletItem);
//记录第一发炮弹位置
QPointF pos = bulletItem->pos();
//每隔500ms,发射下一发炮弹,看着像连续的动画效果
QTimer::singleShot(500, [=]() {
//移除第一发炮弹
scene()->removeItem(bulletItem);
//绘制第二发炮弹
QGraphicsEllipseItem *bulletItem1 = new QGraphicsEllipseItem(0, 0, 5, 10);
bulletItem1->setPos(pos.x(), pos.y() - 30);
bulletItem1->setBrush(Qt::red);
scene()->addItem(bulletItem1);
QTimer::singleShot(500, [=]() {
//移除第二发炮弹
scene()->removeItem(bulletItem1);
//绘制第三发炮弹
QGraphicsEllipseItem *bulletItem2 = new QGraphicsEllipseItem(0, 0, 5, 10);
bulletItem2->setPos(pos.x(), pos.y() - 80);
bulletItem2->setBrush(Qt::red);
scene()->addItem(bulletItem2);
QTimer::singleShot(500, [=]() {
//移除第三发炮弹
scene()->removeItem(bulletItem2);
});
});
});
break;
// default:
// break;
}
}
private:
QGraphicsRectItem *turret; // 炮塔
};
//绘制主画布
class TankGame : public QGraphicsView {
public:
TankGame() {
scene = new QGraphicsScene(this); // 2D 图形 画布
setScene(scene);
//创建tank实例
tank = new Tank();
//加载tank实例到画布
scene->addItem(tank);
//抗锯齿渲染 减少图形边缘的锯齿状效果 使得图形看起来更加清晰和平滑
setRenderHint(QPainter::Antialiasing);
//平滑的像素变换渲染 用于对图片进行变换(如旋转、缩放等)时保持图片的平滑性
setRenderHint(QPainter::SmoothPixmapTransform);
//边界框发生变化时进行更新
setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
//高质量抗锯齿渲染 与上边的代码类似 但是这个设置更加强调图形的质量而不是性能
setRenderHint(QPainter::HighQualityAntialiasing);
//设置了 画布 的大小为 800x600 像素
setFixedSize(800, 600);
}
//画布的键盘事件,调用tank类中的键盘事件
protected:
void keyPressEvent(QKeyEvent *event) override {
// Forward key events to the tank
tank->keyPressEvent(event);
}
private:
QGraphicsScene *scene; //画布实例
Tank *tank; //坦克实例
};
//主函数
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//声明画布
TankGame tankGame;
//显示画布
tankGame.show();
return a.exec();
}
tank.pro文件中代码
QT -= core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target