【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

相关推荐
锦亦之22337 小时前
QT+OSG+OSG-earth如何在窗口显示一个地球
开发语言·qt
柳鲲鹏11 小时前
编译成功!QT/6.7.2/Creator编译Windows64 MySQL驱动(MinGW版)
开发语言·qt·mysql
三玖诶11 小时前
如何在 Qt 的 QListWidget 中逐行添加和显示数据
开发语言·qt
阳光开朗_大男孩儿17 小时前
DBUS属性原理
linux·服务器·前端·数据库·qt
Alphapeople18 小时前
Qt Modbus
开发语言·qt
竹林海中敲代码18 小时前
Qt Creator 集成开发环境 常见问题
qt·qt工具常见问题
竹林海中敲代码21 小时前
Qt安卓开发连接手机调试(红米K60为例)
android·qt·智能手机
长沙红胖子Qt1 天前
关于 Qt运行加载内存较大崩溃添加扩大运行内存 的解决方法
开发语言·qt·qt扩大运行内存
gopher95111 天前
qt相关面试题
开发语言·qt·面试
三玖诶1 天前
在 Qt 中使用 QLabel 设置 GIF 动态背景
开发语言·qt·命令模式