【QT】飞机大战
0 项目简介
飞机大战是我们大家所熟知的一款小游戏,本教程就是教大家如何制作一款自己的飞机大战
首先我们看一下效果图
玩家控制一架小飞机,然后自动发射子弹,如果子弹打到了飞下来的敌机,则射杀敌机,并且有爆炸的特效
接下来再说明一下案例的需求,也就是我们需要实现的内容
-
滚动的背景地图
-
飞机的制作和控制
-
子弹的制作和射击
-
敌机的制作
-
碰撞检测
-
爆炸效果
-
音效添加
1 设置主场景
(1)创建工程,class name为MainScene
(2)定义一个配置文件,专门定义一些相关的参数(config.h);
(3)主场景目前只需要固定界面的大小和标题即可,即config.h中定义以下数据:
/***********************游戏数据配置***********************************/
#define GAME_WIDTH 512 // 宽度
#define GAME_HEIGHT 768 // 高度
#define GAME_TITLE "飞机大战 v1.0" // 标题
(4)在MainScene.h中定义初始化游戏场景的函数initScene,并在mainScene.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的目录下,输入命令
rcc -binary .\res.qrc -o plane.rcc
(3)将生成好的rcc文件,放入到debug同级目录中一份;
(4)注册二进制文件。在config.h中追加
#define GAME_RES_PATH "./plane.rcc" // 资源路径
在main.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工程文件中删除代码
删除以下代码:
RESOURCES += \res.qrc
(5)添加图标资源。配置文件config.h中追加代码
虚拟资源路径语法如下:
" : + 前缀名 + 文件路径 "
#define GAME_ICON ":/res/app.ico" // 图标路径
在mainScene.cpp的 initScene函数中追加代码:
// 加载图片
setWindowIcon(QIcon(GAME_ICON)); // 加头文件 #include <QIcon>
运行测试:
3 地图滚动
(1)创建地图类Map;
(2)在Map.h中添加函数和成员属性
#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中添加参数
/*************************地图信息***********************************/
#define MAP_PATH ":/res/img_bg_level_3.jpg" // 地图1图片路径
#define MAP_SCROLL_SPEED 2 // 地图滚动速度
(4)在Map.cpp中实现成员函数(这里就涉及了业务逻辑)
#include "map.h"
#include "config.h"Map::Map()
{// 加载地图对象,两张图无缝衔接m_map1.load(MAP_PATH);m_map2.load(MAP_PATH);// 设置地图起始y坐标// 窗口是(0.0)点,第一张图在上面,所以y轴的坐标是-GAME_HEIGHTm_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中添加新的定时器对象
QTimer m_Timer;
在 config.h中添加 屏幕刷新间隔
#define GAME_RATE 10 //刷新间隔,帧率 单位毫秒
在MainScene.cpp的initScene中追加代码
// 定时器设置m_timer.setInterval(GAME_RATE);
(6)启动定时器实现地图滚动
在MainScene.h中添加新的成员函数以及成员对象
// 启动游戏 用于启动定时器对象void playGame();// 更新坐标void updatePosition();// 绘图事件void paintEvent(QPaintEvent *event);// 地图对象Map m_map;
在MainScene.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的构造函数中调用启动游戏函数
MainScene::MainScene(QWidget *parent): QWidget(parent)
{//初始化场景initScene();// 启动游戏playGame();
}
测试运行游戏,实现地图滚动
4 创建英雄飞机
(1)创建英雄飞机类HeroPlane;
(2)在英雄飞机中添加成员函数和属性
HeroPlane.h
#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中添加参数
/************************飞机配置数据***********************************/
#define HERO_PATH ":/res/hero2.png" // 飞机图片路径
(3)在heroPlane.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中追加
// 飞机对象HeroPlane m_hero;
在MainScene.cpp的paintEvent中追加代码
// 绘制英雄飞机painter.drawPixmap(m_hero.m_x, m_hero.m_y, m_hero.m_plane);
此时测试,飞机已经可以显示在屏幕中了
(5)利用鼠标拖拽飞机。在MainScene.h中添加鼠标事件
// 鼠标移动事件void mouseMoveEvent(QMouseEvent*);
重写鼠标移动事件
// 鼠标移动事件
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
相关文章:

【QT】飞机大战
0 项目简介 飞机大战是我们大家所熟知的一款小游戏,本教程就是教大家如何制作一款自己的飞机大战 首先我们看一下效果图 玩家控制一架小飞机,然后自动发射子弹,如果子弹打到了飞下来的敌机,则射杀敌机,并且有爆炸的特…...
linux最全基础入门命令(简单明了建议收藏)
Linux是一种开源的操作系统,它有许多强大的命令行工具,可以让用户对系统进行各种操作和管理。本文将介绍一些Linux最常见最全的命令,以及它们的用法和示例。 目录 ls:用于列出目录中的文件和子目录cd:用于切换当前工作目录pwd:于显示当前工作…...

dgl 的cuda 版本 环境配置(dgl cuda 版本库无法使用问题解决)
1. 如果你同时有dgl dglcu-XX.XX 那么,应该只会运行dgl (DGL的CPU版本),因此,你需要把dgl(CPU)版本给卸载了 但是我只卸载CPU版本还不够,我GPU 版本的dglcu依旧不好使,因此吧GPU版本的也得卸载…...
回文数和复利的威力(C#)
题目:回文数 回⽂数指正序(从左到右)和倒序(从右到左)读都是⼀样的整数。 输⼊⼀个数,判断是否是回⽂数 样例输⼊ 2397 输出no 样例输⼊ 2992 样例输出yes 输⼊的整数⼤于0,⼩于1000000。如…...
【Java】面向对象程序设计 课程笔记 Java核心类
🚀Write In Front🚀 📝个人主页:令夏二十三 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝 📣系列专栏:Java 💬希望你看完之后,能对你有所帮助࿰…...
16个值得推荐的.NET ORM框架
什么是ORM? ORM 是 Object Relational Mapping 的缩写,译为“对象关系映射”,是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。它解决了对象和关系型数据库之间的数据交互问题,ORM的作用是在关系型…...

Git 进阶使用
一. Git图形化操作 1.1.什么是图形化管理工具 图形化管理工具是一种通过可视化界面来操作计算机系统或应用程序的软件工具。在软件开发中,它通常用于管理和操作版本控制系统(如Git、SVN等)以及代码开发环境(如IDE)。与…...
【微软技术栈】C#.NET 泛型数学
本文内.NET 7 为基类库引入了新的数学相关泛型接口。 提供这些接口意味着可以将泛型类型或方法的类型参数约束为“类似于数字”。 此外,C# 11 及更高版本允许定义 static virtual 接口成员。 由于必须将运算符声明为 static,因此这一新的 C# 功能可用于在…...
【nlp】1.1文本处理的基本方法
文本处理的基本方法 1 什么是分词2 什么是命名实体识别3 什么是词性标准1 什么是分词 分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。在英文的行文中,单词之间是以空格作为自然分界符的,而中文只是字、句和段能通过明显的分界符来简单划界,唯独词没有一个形…...

流量分析(信息安全铁人三项赛分区赛2-5.18)
题目描述 目录 题目描述 黑客的IP是多少 服务器1.99的web服务器使用的CMS及其版本号(请直接复制) 服务器拿到的webshell的网址(请输入url解码后的网址) 服务器1.99的主机名 网站根目录的绝对路径(注意最后加斜杠) 黑客上传的第一个文件名称是什么 黑客进行内网扫描&am…...

云服务器如何选?腾讯云2核2G3M云服务器88元一年!
作为一名程序员,在选择云服务器时,我们需要关注几个要点:网络稳定性、价格以及云服务商的规模。这些要素将直接影响到我们的使用体验和成本效益。接下来,我将为大家推荐一款性价比较高的轻应用云服务器。 腾讯云双11活动 腾讯云…...

【Hello Go】初识Go语言
初识Go语言 Go语言介绍Go语言是什么Go语言优势Go语言能用来做什么 Go语言环境安装第一个GO语言程序运行Go语言程序 Go语言介绍 Go语言是什么 go语言是是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言. 静态类型:在静态类型…...

计算机视觉:人脸识别与检测
目录 前言 识别检测方法 本文方法 项目解析 完整代码及效果展示 前言 人脸识别作为一种生物特征识别技术,具有非侵扰性、非接触性、友好性和便捷性等优点。人脸识别通用的流程主要包括人脸检测、人脸裁剪、人脸校正、特征提取和人脸识别。人脸检测是从获取的图…...

【NLP】理解 Llama2:KV 缓存、分组查询注意力、旋转嵌入等
LLaMA 2.0是 Meta AI 的开创性作品,作为首批高性能开源预训练语言模型之一闯入了 AI 场景。值得注意的是,LLaMA-13B 的性能优于巨大的 GPT-3(175B),尽管其尺寸只是其一小部分。您无疑听说过 LLaMA 令人印象深刻的性能,但您是否想知…...

ctyunos 与 openeuler
ctyunos-2.0.1-220311-aarch64-dvd ctyunos-2.0.1-220329-everything-aarch64-dvd glibc python3 对应openEuler 20.03 LTS SP1...
跟着GPT学设计模式之工厂模式
工厂模式(Factory Design Pattern)分为三种更加细分的类型:简单工厂、工厂方法和抽象工厂。在这三种细分的工厂模式中,简单工厂、工厂方法原理比较简单,在实际的项目中也比较常用。而抽象工厂的原理稍微复杂点…...

VScode+python开发,多个解释器切换问题
内容:主要VScode使用多个解释器 环境准备 VScode编辑器,两个版本python解释器 python3.7.2 python3.11.6 问题: 目前我们的电脑安装了python3.7.2、python3.11.6两个解释器,在vscode编辑器中,无法切换解释器使用如…...

c++ 经典服务器开源项目Tinywebserver如何运行
第一次直接按作者的指示,运行sh ./build.sh,再运行./server,发现不起作用,localhost:9006也是拒绝访问的状态,后来摸索成功了发现,运行./server之后,应该是启动状态,就是不会退出,而…...

c++之xml的创建,增删改查
c之xml的创建,增删改查 1.创建写入2.添加3.删除4.修改: 1.创建写入 #include <stdio.h> #include <typeinfo> #include "F:/EDGE/tinyxml/tinyxml.h" #include <iostream> #include <string> #include <Winsock2.…...

【前端开发】JS Vue React中的通用递归函数
目录 前言 一、递归函数的由来 二、功能实现 1.后台数据 2.处理数据 3.整体代码 总结 🙂博主:冰海恋雨. 🙂文章核心:【前端开发】JS Vue React中的通用递归函数 前言 大家好,今天和大家分享一下在前端开发中j…...

IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...

VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...