如图所示,在子弹碰到敌机时,同时产生爆炸特效,显得不那么突兀
那么怎么做到的呢??
其实也很简单,爆炸特效由一些图片组成,每当我们检测到子弹和敌机相交时
就在这个位置播放一个爆炸特效,那么爆炸也可以封装为一个类
而且,爆炸类和敌机类,子弹类也没什么两样!!!
爆炸类肯定要有自己的坐标
需要有自己的资源图片,但是动画需要很多资源图片连起来播放,所以
我们用一个 v e c t o r vector vector来存
需要有自己的图片索引,不然怎么知道现在在展示第几张图片呢
需要记录更换图片的间隔,主场景的定时器出发一次换一张图是不现实的(太快了)
需要有布尔类型表示闲置状态,原理和子弹类一样,为了循环利用
需要有更新图片索引的函数,调用这个函数,让更换图片的间隔加加,到了一定的值
我们就可以让图片索引加一,如果图片播放完毕,我们就让闲置状态变成 t r u e true true
爆炸类 B o m b Bomb Bomb
bomb.h
#ifndef BOMB_H
#define BOMB_H
#include <QPixmap>
class Bomb
{
public:
Bomb();
void updateInfo();
public:
//爆炸的资源图片数组
QVector<QPixmap>vector;
//爆炸位置
int m_x,m_y;
//爆炸状态
bool m_Free;
//爆炸切图时间间隔
int boom_record;
//当前爆炸显示图片下标
int m_index;
};
#endif // BOMB_H
bomb.cpp
#include "bomb.h"
#include <config.h>
Bomb::Bomb()
{
//将所有爆炸的pixmap装进去
for(int i=1;i<=BOMB_NUM;i++)
vector.push_back( QPixmap(QString(BOMB_PATH).arg(i)) );
//坐标
m_x = 0, m_y = 0;
//空闲状态
m_Free = true;
//当前播放图片下标
m_index = 0;
//爆炸间隔
boom_record = 0;
}
//更新图片索引的函数
void Bomb::updateInfo()
{
//空闲状态下的爆炸效果,不需要更新
if( m_Free ) return;
if( ++boom_record<BOMB_INTERVAL ) return;
//重置记录
boom_record = 0;
//图片下标
m_index++;
if( m_index>BOMB_NUM-1 )
{
m_index = 0;
m_Free = true;
}
}
然后在主场景 M a i n S c e n e MainScene MainScene中添加一个爆炸类的数组
那么在子弹和敌机的碰撞检测中检测到了,就找一个闲置的爆炸效果改成非闲置
然后每次调用定时器,遍历所有非闲置爆炸效果更新图片索引
然后在 p a i n t e r E v e n t painterEvent painterEvent中绘制即可
MainScene.cpp
#include "mainscene.h"
#include "ui_mainscene.h"
#include <config.h>
#include <QDebug>
#include <QTimer>
#include <QPainter>
#include <bullet.h>
#include <QSound>
MainScene::MainScene(QWidget *parent) :
QWidget(parent),
ui(new Ui::MainScene)
{
ui->setupUi(this);
initScene();
}
MainScene::~MainScene()
{
delete ui;
}
void MainScene::initScene()
{
//播放背景音乐
QSound::play(SOUND_BACKGROUND);
//设置随机数种子
srand( (unsigned int)time(NULL) );
//设置窗口的固定尺寸,设置标题
setFixedSize(GAME_WIDTH,GAME_HEIGHT);
setWindowTitle(GAME_TITLE);
setWindowIcon(QIcon(":/res/app.ico") );
m_map = new map(":/res/img_bg_level_1.jpg");
//场景定时器设置
timer.setInterval(10);
//敌机出场间隔
enemy_record = 0;
playGame();
}
void MainScene::playGame()
{
//监听定时器发送的信号
connect(&timer,&QTimer::timeout,[=](){
//敌机出场
enemyToScene();
//更新所有元素的坐标
updatePosition();
//碰撞检测
collisionDetection();
//绘制所有元素
update();
});
//启动定时器
timer.start();
}
void MainScene::paintEvent(QPaintEvent *)
{
QPainter painter(this);
//绘制地图
painter.drawPixmap(0,m_map->map1_posY,m_map->map1);
painter.drawPixmap(0,m_map->map2_posY,m_map->map2);
//绘制英雄飞机
painter.drawPixmap(m_hero.m_x,m_hero.m_y,m_hero.m_Plane);
//绘制子弹
for(int i=0;i<BULLET_NUM;i++)
{
if( m_hero.bullets[i].m_Free==false )
painter.drawPixmap(m_hero.bullets[i].m_x,m_hero.bullets[i].m_y,m_hero.bullets[i].m_Bullet);
}
//绘制敌机
for(int i=0;i<ENEMY_NUM;i++)
{
if( enemys[i].m_Free==false )
painter.drawPixmap(enemys[i].m_x,enemys[i].m_y,enemys[i].img_enemy);
}
//绘制爆炸图案
for(int i=0;i<BOMB_NUM;i++)
{
if( bombs[i].m_Free==false )
painter.drawPixmap(bombs[i].m_x,bombs[i].m_y,bombs[i].vector[bombs[i].m_index]);
}
}
void MainScene::updatePosition()
{
//更新地图坐标
m_map->mapPosition();
//发射子弹
m_hero.shoot();
for(int i=0;i<BULLET_NUM;i++)
{
if( m_hero.bullets[i].m_Free==false )
m_hero.bullets[i].updatePosition();
}
//敌机出场
for(int i=0;i<ENEMY_NUM;i++)
{
if( enemys[i].m_Free==false )
enemys[i].updatePosition();
}
//更新爆炸图片的下标
for(int i=0;i<BOMB_NUM;i++)
{
if( bombs[i].m_Free==false )
bombs[i].updateInfo();
}
}
void MainScene::mouseMoveEvent(QMouseEvent *event)
{
int x = event->x()-m_hero.m_Rect.width()/2;
int y = event->y()-m_hero.m_Rect.height()/2;
if( x<0 ) x = 0;
if( y<0 ) y = 0;
if( x>this->width()-m_hero.m_Rect.width() ) x = this->width()-m_hero.m_Rect.width();
if( y>this->height()-m_hero.m_Rect.height() ) y = this->height()-m_hero.m_Rect.height();
m_hero.setPosition(x,y);
}
void MainScene::enemyToScene()
{
if( ++enemy_record<ENEMY_INTERVAL ) return;
enemy_record = 0;
for(int i=0;i<ENEMY_NUM;i++)
{
if( enemys[i].m_Free==false ) continue;//非空闲,不能使用
enemys[i].m_Free = false;
enemys[i].m_x = rand()%(GAME_WIDTH-enemys[i].m_Rect.width());
enemys[i].m_y = -enemys[i].m_Rect.height();
break;
}
}
//碰撞检测
void MainScene::collisionDetection()
{
//遍历所有非空闲敌机
for(int i=0;i<ENEMY_NUM;i++)
{
if( enemys[i].m_Free ) continue;
for(int j=0;j<BULLET_NUM;j++)
{
if( m_hero.bullets[j].m_Free ) continue;
QRect res = m_hero.bullets[j].m_Rect;
if( res.intersects(enemys[i].m_Rect) )
{
enemys[i].m_Free = true;
m_hero.bullets[j].m_Free = true;
//播放爆炸效果
for(int k = 0;k<BOMB_NUM;k++ )
{
if( bombs[k].m_Free==false ) continue;
bombs[k].m_Free = false;//非空闲
//更新爆炸坐标
QSound::play(SOUND_BOMB);
bombs[k].m_x = enemys[i].m_x;
bombs[k].m_y = enemys[i].m_y;
break;
}
break;
}
}
}
}