关于本章节中使用的图形绘制类,如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