【QT】飞机大战

0 项目简介

飞机大战是我们大家所熟知的一款小游戏,本教程就是教大家如何制作一款自己的飞机大战

首先我们看一下效果图

玩家控制一架小飞机,然后自动发射子弹,如果子弹打到了飞下来的敌机,则射杀敌机,并且有爆炸的特效

接下来再说明一下案例的需求,也就是我们需要实现的内容

  • 滚动的背景地图

  • 飞机的制作和控制

  • 子弹的制作和射击

  • 敌机的制作

  • 碰撞检测

  • 爆炸效果

  • 音效添加

1 设置主场景

(1)创建工程,class name为MainScene

(2)定义一个配置文件,专门定义一些相关的参数(config.h);

(3)主场景目前只需要固定界面的大小和标题即可,即config.h中定义以下数据:

cpp 复制代码
/***********************游戏数据配置***********************************/
#define GAME_WIDTH  512                             // 宽度
#define GAME_HEIGHT 768                             // 高度
#define GAME_TITLE "飞机大战 v1.0"                   // 标题

(4)在MainScene.h中定义初始化游戏场景的函数initScene,并在mainScene.cpp实现

cpp 复制代码
// 初始化游戏场景
void MainScene::initScene()
{
    //初始化窗口大小
    setFixedSize(GAME_WIDTH,GAME_HEIGHT);

    //设置窗口标题
    setWindowTitle(GAME_TITLE);
}

(5)在MainScene的构造函数中调用initScene函数。运行程序,此时界面出现

2 资源导入

(1)资源导入见:【QT】资源文件导入_复制其他项目中的文件到qt项目中_StudyWinter的博客-CSDN博客

(2)将qrc文件生成rcc二进制文件,利用cmd打开终端,定位到res.qrc的目录下,输入命令

bash 复制代码
rcc -binary .\res.qrc -o plane.rcc

(3)将生成好的rcc文件,放入到debug同级目录中一份;

(4)注册二进制文件。在config.h中追加

cpp 复制代码
#define GAME_RES_PATH "./plane.rcc"                 // 资源路径

在main.cpp中修改代码

cpp 复制代码
#include "mainscene.h"
#include <QResource>
#include <QApplication>
#include "config.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    // 注册外部的二进制资源文件,注意加入头文件
    QResource::registerResource(GAME_RES_PATH);
    MainScene w;
    w.show();
    return a.exec();
}

此时,qrc文件已经没用了,删除即可!最简单的删除方式就是 .pro工程文件中删除代码

cpp 复制代码
删除以下代码:
RESOURCES += \
    res.qrc

(5)添加图标资源。配置文件config.h中追加代码

虚拟资源路径语法如下:

" : + 前缀名 + 文件路径 "

cpp 复制代码
#define GAME_ICON ":/res/app.ico"                   // 图标路径

在mainScene.cpp的 initScene函数中追加代码:

cpp 复制代码
// 加载图片
setWindowIcon(QIcon(GAME_ICON));    // 加头文件 #include <QIcon>

运行测试:

3 地图滚动

(1)创建地图类Map;

(2)在Map.h中添加函数和成员属性

cpp 复制代码
#ifndef MAP_H
#define MAP_H
#include <QPixmap>


class Map
{
public:
    // 构造函数
    Map();

    // 地图滚动坐标计算
    void mapPosition();

public:
    // 地图图片对象
    QPixmap m_map1;
    QPixmap m_map2;

    // 地图Y轴坐标
    int m_map1_posY;
    int m_map2_posY;

    // 地图滚动幅度
    int m_scroll_speed;
};

#endif // MAP_H

(3)在配置文件config.h中添加参数

cpp 复制代码
/*************************地图信息***********************************/
#define MAP_PATH ":/res/img_bg_level_3.jpg"        // 地图1图片路径
#define MAP_SCROLL_SPEED 2                          // 地图滚动速度

(4)在Map.cpp中实现成员函数(这里就涉及了业务逻辑)

cpp 复制代码
#include "map.h"
#include "config.h"

Map::Map()
{
    // 加载地图对象,两张图无缝衔接
     m_map1.load(MAP_PATH);
     m_map2.load(MAP_PATH);

     // 设置地图起始y坐标
     // 窗口是(0.0)点,第一张图在上面,所以y轴的坐标是-GAME_HEIGHT
     m_map1_posY = -GAME_HEIGHT;
     m_map2_posY = 0;

     // 设置地图滚动速度
     m_scroll_speed = MAP_SCROLL_SPEED;
}

// 地图滚动坐标计算
void Map::mapPosition()
{
    // 图片是向下移动的
    // 处理第一张地图滚动
    m_map1_posY += m_scroll_speed;
    // 此时第一张图已经在界面中,重置
    if (m_map1_posY >= 0) {
        m_map1_posY = -GAME_HEIGHT;
    }

    // 处理第二张地图滚动
    m_map2_posY += m_scroll_speed;
    if (m_map2_posY > GAME_HEIGHT) {
        m_map2_posY = 0;
    }
}

(5)添加定时器

关于定时器详见:【QT】定时器_qt 定时器-CSDN博客

在mainScene.h中添加新的定时器对象

cpp 复制代码
QTimer m_Timer;

在 config.h中添加 屏幕刷新间隔

cpp 复制代码
#define GAME_RATE  10                               //刷新间隔,帧率 单位毫秒

在MainScene.cpp的initScene中追加代码

cpp 复制代码
  // 定时器设置
  m_timer.setInterval(GAME_RATE);

(6)启动定时器实现地图滚动

在MainScene.h中添加新的成员函数以及成员对象

cpp 复制代码
    // 启动游戏  用于启动定时器对象
    void playGame();
    // 更新坐标
    void updatePosition();
    // 绘图事件
    void paintEvent(QPaintEvent *event);

    // 地图对象
    Map m_map;

在MainScene.cpp中实现成员函数

cpp 复制代码
// 启动游戏  用于启动定时器对象
void MainScene::playGame()
{
    // 启动定时器
    m_timer.start();

    // 监听定时器
    connect(&m_timer, &QTimer::timeout, this, [=]() {
        // 更新游戏中元素的坐标
        updatePosition();
        // 重新绘制地图
        update();
    });
}

// 更新坐标
void MainScene::updatePosition()
{
    // 更新地图坐标
    m_map.mapPosition();
}

// 绘图事件
void MainScene::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    //绘制地图
    painter.drawPixmap(0, m_map.m_map1_posY , m_map.m_map1);
    painter.drawPixmap(0, m_map.m_map2_posY , m_map.m_map2);
}

在MainScene的构造函数中调用启动游戏函数

cpp 复制代码
MainScene::MainScene(QWidget *parent)
    : QWidget(parent)
{
    //初始化场景
    initScene();
    // 启动游戏
    playGame();
}

测试运行游戏,实现地图滚动

4 创建英雄飞机

(1)创建英雄飞机类HeroPlane;

(2)在英雄飞机中添加成员函数和属性

HeroPlane.h

cpp 复制代码
#ifndef HEROPLANE_H
#define HEROPLANE_H
#include <QPixmap>
#include <QRect>
#include "bullet.h"
#include "config.h"


class HeroPlane
{
public:
    HeroPlane();
    // 发射子弹
    void shoot();
    // 设置飞机位置
    void setPosition(int x, int y);

public:
    // 飞机资源对象
    QPixmap m_plane;

    // 飞机坐标
    int m_x;
    int m_y;

    // 飞机的矩形边框
    QRect m_rect;
};

#endif // HEROPLANE_H

(2)在配置文件config.h中添加参数

cpp 复制代码
/************************飞机配置数据***********************************/
#define HERO_PATH ":/res/hero2.png"                 // 飞机图片路径

(3)在heroPlane.cpp中实现函数

cpp 复制代码
#include "heroplane.h"
#include "config.h"

HeroPlane::HeroPlane()
{
    // 加载飞机资源
    m_plane.load(HERO_PATH);

    // 初始化飞机坐标
    m_x = GAME_WIDTH * 0.5 - m_plane.width() * 0.5;
    m_y = GAME_HEIGHT - m_plane.height();

    // 初始化矩形框
    m_rect.setWidth(m_plane.width());
    m_rect.setHeight(m_plane.height());
    m_rect.moveTo(m_x, m_y);
}

void HeroPlane::shoot()
{
    
}

// 设置飞机位置
void HeroPlane::setPosition(int x, int y)
{
    m_x = x;
    m_y = y;
    m_rect.moveTo(m_x, m_y);
}

(4)创建飞机并显示。MainScene.h中追加

cpp 复制代码
    // 飞机对象
    HeroPlane m_hero;

在MainScene.cpp的paintEvent中追加代码

cpp 复制代码
  // 绘制英雄飞机
  painter.drawPixmap(m_hero.m_x, m_hero.m_y, m_hero.m_plane);

此时测试,飞机已经可以显示在屏幕中了

(5)利用鼠标拖拽飞机。在MainScene.h中添加鼠标事件

cpp 复制代码
 // 鼠标移动事件
 void mouseMoveEvent(QMouseEvent*);

重写鼠标移动事件

cpp 复制代码
// 鼠标移动事件
void MainScene::mouseMoveEvent(QMouseEvent *event)
{
    int x = event->x() - m_hero.m_rect.width() * 0.5;       // 鼠标的位置 - 飞机矩形的一半
    int y = event->y() - m_hero.m_rect.height() * 0.5;

    // 边界检查
    if (x <= 0) {
        x = 0;
    }
    if (x >= GAME_WIDTH - m_hero.m_rect.width()) {
        x = GAME_WIDTH - m_hero.m_rect.width();
    }

    if (y <= 0) {
        y = 0;
    }
    if (y >= GAME_HEIGHT - m_hero.m_rect.height()) {
        y = GAME_HEIGHT - m_hero.m_rect.height();
    }
    m_hero.setPosition(x, y);
}

测试飞机可以拖拽

5 子弹制作

6 玩家发射子弹

7 敌机制作

8 碰撞检测

9 爆炸效果

10 音效添加

11 打包发布

资源来自:01 飞机大战项目演示以及需要分析_哔哩哔哩_bilibili

相关推荐
徒步僧7 小时前
ThingsBoard规则链节点:RPC Call Reply节点详解
qt·microsoft·rpc
可峰科技8 小时前
斗破QT编程入门系列之一:认识Qt:初步使用(四星斗师)
开发语言·qt
我喜欢就喜欢8 小时前
基于qt vs下的视频播放
开发语言·qt·音视频
CP-DD9 小时前
Qt的架构设计
qt
阿_旭9 小时前
基于YOLO11/v10/v8/v5深度学习的维修工具检测识别系统设计与实现【python源码+Pyqt5界面+数据集+训练代码】
人工智能·python·深度学习·qt·ai
Bruce小鬼14 小时前
QT创建按钮篇
开发语言·qt
martian66515 小时前
QT开发:掌握现代UI动画技术:深入解析QML和Qt Quick中的动画效果
开发语言·c++·qt·ui
墨染新瑞17 小时前
两个有趣的小东西(qt和类型转换)
开发语言·网络·qt
Bruce小鬼18 小时前
解决MAC安装QT启动项目不显示窗口问题
开发语言·qt·macos
云雨歇21 小时前
Qt学习笔记(三)网络编程
笔记·qt·学习