先来看下效果:
一、资源导入
在主场景中其实还有一个配置项没有实现,也就是窗口左上角的那个图标资源
那么接下来我们将游戏中的资源进行导入并且设置游戏图标。
资源导入步骤(如果觉得资源太大,可以生成二进制的文件):
- 生成qrc文件
- 项目同级目录下创建res文件夹并将资源粘贴过来
- 编辑qrc,加入前缀和文件
- 利用qrc生成二进制文件rcc
- rcc文件放入到debug同级目录下
- 注册二进制文件
- 添加图标资源
qrc文件生成:
- 当资源过大时(但是我这个游戏的资源还不大,此处用于资源过大时才用),会提示错误:
- 这个错误也就是“编译器的堆空间不足”;
- 由于资源文件qrc过大,超出分配的内存范围
- 因此我们需要利用二进制资源,而生成二进制资源就需要我们刚刚的qrc文件
- 利用cmd打开终端,定位到res.qrc的目录下,输入命令
rcc -binary .\res.qrc -o plane.rcc
注册二进制文件;
- 在config.h中追加配置数据
-
#define GAME_RES_PATH "./plane.rcc"
- 在main.cpp中修改代码:
#include "mainscene.h"
#include <QApplication>
#include <QResource>
#include "confing.h"
int main(int argc,char *argv[])
{
QApplication a(argc,argv);
//注册外部的二进制资源文件
QResource::refisterResource(GAME_RES_PATH);
MainScene w;
w.show();
return a.exec();
}
-
此时,qrc文件已经没用了,删除即可!
二、添加图标资源
- 配置文件config.h中追加代码
- 虚拟资源路径语法如下:
“:+前缀名 + 文件路径”
#define GAME_ICON ":/res/app.ico"
- 在mainScene.cpp的initScene函数中追加代码:
//设置图标资源
setWindowIcon(QIcon(GAME_ICON)); //加头文件 #include <QIcon>
- 运行测试
三、地图滚动
步骤:
- 创建地图文件和类
- 添加成员函数和成员属性,实现成员函数
- 游戏运行调用定时器
- 启动定时器,监听定时器信号实现游戏循环
- 计算游戏内元素坐标
- 绘制到屏幕中
- 测试运行游戏,实现地图滚动
来看下地图滚动的代码:
其实需要两张一样的图片,拼接在一起的;视觉上就会产生滚动的效果。
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;
}
}
四、英雄飞机
步骤如下:
- 创建英雄文件和类
- 添加成员函数和成员属性
- 实现成员函数
- 创建飞机对象并显示
- 拖拽飞机
五、子弹制作
制作步骤如下:
- 创建子弹文件和类
- 添加子弹类中的成员函数和成员属性
- 实现成员函数
Bullet::Bullet()
{
//加载自动资源
m_Bullet.load(BULLET_PATH);
//子弹坐标初始化
m_x = GAME_WIDTH *0.5 - m_Bullet.width()/2;
m_y = GAME_HEIGHT;
//子弹的空闲状态
m_Free = true;
//子弹速度
m_Speed = BULLET_SPEED;
//子弹矩形边框(碰撞检测)
m_Rect.setWidth(m_Bullet.width());
m_Rect.setHeight(m_Bullet.height());
m_Rect.moveTo(m_x,m_y);
}
- 测试子弹
六、玩家发射子弹
玩家发射子弹制作步骤如下:
- 英雄飞机添加新的成员属性
- 实现发射成员函数
- 主场景控制子弹发射
七、敌机制作
敌机制作与子弹制作原理类似,也是每隔一定的时间让敌机出场
制作步骤如下:
- 创建敌机文件和类
- 添加敌机类中成员函数和成员属性
- 实现成员函数
EnemyPlane::EnemyPlane()
{
//敌机资源加载
m_enemy.load(ENEMY_PATH);
//敌机位置
m_x = 0;
m_y = 0;
//敌机状态
m_Free = true;
//敌机速度
m_Speed = ENEMY_SPEED;
//敌机矩形
m_Rect.setWidth(m_enemy.width());
m_Rect.setHeight(m_enemy.height());
m_Rect.moveTo(m_x,m_y);
}
- 敌机出场
- 测试敌机
八、碰撞检测
实现碰撞检测步骤如下:
- 添加并实现碰撞检测成员函数
- 调用并检测函数
//碰撞检测
void MainScene::collisionDetection()
{
//遍历所有非空闲的敌机
for(int i = 0;i < ENEMY_NUM; i++)
{
if(m_enemys[i].m_Free)
{
//空闲飞机 跳转下一次循环
continue;
}
//遍历所有非空闲的子弹
for(int j = 0;j < BULLET_NUM; j++)
{
if(m_hero.m_bullets[i].m_Free)
{
//空闲子弹 跳转下一次循环
continue;
}
//如果子弹矩形和敌机矩形相交,发生碰撞,同时变为空闲状态即可
if(m_enemys[i].m_Rect.intersects(m_hero.m_bullets[j].m_Rect))
{ //intersects函数是相交的意思
num++;
lb->setText(QString("分数:%1").arg(num));
//播放音效
QSound::play(SOUND_BOMB);
m_enemys[i].m_Free = true;
m_hero.m_bullets[j].m_Free = true;
//调用爆炸特效
//播放爆炸效果
for(int k = 0;k < BOMB_NUM; k++)
{
if(m_bombs[k].m_Free)
{
//爆炸状态设置为非空闲
m_bombs[k].m_Free = false;
//更新坐标
m_bombs[k].m_x = m_enemys[i].m_x;
m_bombs[k].m_y = m_enemys[i].m_y;
break;
}
}
}
}
}
}
九、爆炸效果
爆炸效果功能实现步骤如下:
- 创建爆炸文件和类
- 添加爆炸类中的成员函数和成员属性
- 实现爆炸类中的成员函数
- 调用并测试效果
十、播放音效
播放音效功能实现步骤如下:
- 添加多媒体模块
在工程文件planeWar.pro 中修改代码
QT += core gui multimedia
-
播放音效
在config.h中添加音效的配置路径
注意:qt中只能播放 后缀为 .wav格式的音效
QSound 使用时候要包含头文件#include <QSound>
#define SOUBD_BACKGROUND ":/res/bg.wav"
#define SOUBD_BOMB ":/res/bomb.wav"
-
在PlayGame中添加背景音乐
//启动背景音乐
QSound::play(SOUND_BACKGROUND);
十一、打包发布
- 确定环境变量配置好 PATH C:\Qt\Qt5.x.x/5.x.x\mingw53_32\bin
- 在QT中把运行模式切换成release 模式,编译,在外层目录中会有release版本的目录。
- 将目录中的rcc二进制资源文件,可执行程序文件(.exe)拷贝到另外一个单独的文件夹中。
- 进入cmd命令模式,切换到可执行程序所在的目录,执行以下命令,将可执行程序所需要的库文件拷贝到当前目录:
-
windeployqt planeWar.exe
- 额外可以将ioc图标也拷贝到当前可执行所在的目录。
- 启动Enigma Virtual Box软件,在软件中选择
- 为了让安装包安装软件也有快捷方式图标,在生成的脚本里,进行修改: