【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…...

【python 生成器 面试必备】yield关键字,协程必知必会系列文章--自己控制程序调度,体验做上帝的感觉 1
python生成器系列文章目录 第一章 yield — Python (Part I) 文章目录 python生成器系列文章目录前言1. Generator Function 生成器函数2.并发和并行,抢占式和协作式2.Let’s implement Producer/Consumer pattern using subroutine: 生成器的状态 generator’s st…...

头哥实践平台之MapReduce基础实战
一. 第1关:成绩统计 编程要求 使用MapReduce计算班级每个学生的最好成绩,输入文件路径为/user/test/input,请将计算后的结果输出到/user/test/output/目录下。 先写命令行,如下: 一行就是一个命令 touch file01 echo Hello World Bye Wor…...

Linux基础知识——tmux和vim
Linux基础知识——tmux和vim 文章目录 Linux基础知识——tmux和vim一、tmux1. 功能2. 结构3. 操作 二、vim功能模式操作 一、tmux tmux配置:~/.tmux.conf修改为如下 set-option -g status-keys vi setw -g mode-keys visetw -g monitor-activity on# setw -g c0-cha…...

Java Web——TomcatWeb服务器
目录 1. 服务器概述 1.1. 服务器硬件 1.2. 服务器软件 2. Web服务器 2.1. Tomcat服务器 2.2. 简单的Web服务器使用 1. 服务器概述 服务器指的是网络环境下为客户机提供某种服务的专用计算机,服务器安装有网络操作系统和各种服务器的应用系统服务器的具有高速…...

Zookeeper 命令使用和数据说明
文章目录 一、概述二、命令使用2.1 登录 ZooKeeper2.2 ls 命令,查看目录树(节点)2.3 create 命令,创建节点2.4 delete 命令,删除节点2.5 set 命令,设置节点数据2.6 get 命令,获取节点数据 三、数…...

索尼RSV文件怎么恢复为MP4视频
索尼相机RSV是什么文件? 如果您的相机是索尼SONY A7S3,A7M4,FX3,FX3,FX6,或FX9等,有时录像会产生一个RSV文件,而没有MP4视频文件。RSV其实是MP4的前期文件,经我对RSV文件…...

pytorch-gpu(Anaconda3+cuda+cudnn)
文章目录 下载Anaconda3安装,看着点next就行比较懒所以自动添加path测试 cuda安装的时候不能改路径如果出现报错,关闭杀毒软件一直下一步就好取消勾选“CUDA”中的“Visual Studio Intergration”一直下一步即可测试安装成功 cudnn解压后将这三个文件夹复…...

解析数据洁净之道:BI中数据清理对见解的深远影响
本文由葡萄城技术团队发布。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 前言 随着数字化和信息化进程的不断发展,数据已经成为企业的一项不可或缺的重要资源。然而,这…...

efcore反向共工程,单元测试
1.安装efcore需要的nuget <PackageReference Include"Microsoft.EntityFrameworkCore" Version"6.0.24" /> <PackageReference Include"Microsoft.EntityFrameworkCore.SqlServer" Version"6.0.24" /> <PackageRefere…...

利用IP风险画像强化金融行业网络安全防御
在数字化时代,金融行业日益依赖互联网和技术创新,但这也使得金融机构成为网络攻击的主要目标。为了应对日益复杂的网络威胁,金融机构迫切需要采用先进的安全技术和工具。其中,IP风险画像技术成为提升网络安全的一项重要策略。 1.…...