前文链接如下所示

​QT飞机大战一(游戏场景配置)​

​QT飞机大战二(飞机类)​


QT飞机大战三(子弹类)_ico

如图所示,子弹会不断从飞机的位置射出来

那么子弹这个类肯定有自己的位置坐标

肯定有自己的资源图片

既然子弹需要"射"出去,也需要发射的速率,也就是更新一次几像素

然后子弹需要有一个布尔变量:闲置状态

设想一下,假如需要一个子弹就 n e w new new一个发射出去,那么内存开销是不敢想象的

所以我们给飞机类一个"弹夹",就是一个类型是子弹类的数组

飞机每次发射子弹就从弹夹里找一个闲置的子弹发射出去

然后子弹飞出屏幕后,就又恢复到闲置状态

这样,在主场景中也只需要绘制那些非闲置的子弹即可

子弹需要有一个函数来修改当前位置,飞出屏幕就修改闲置状态

所以,发射子弹的原理只是把子弹状态改为非闲置状态而已

子弹类 B u l l e t Bullet Bullet

​bullet.h​

#ifndef BULLET_H
#define BULLET_H
#include <config.h>
#include <QPixmap>

class Bullet
{
public:
Bullet();
//更新子弹的坐标
void updatePosition();

public:
//子弹图片
QPixmap m_Bullet;
//子弹坐标
int m_x,m_y;
//子弹移动速度
int m_speed;
//标注子弹当前是否在移动
bool m_Free;
//子弹边框(碰撞检测)
QRect m_Rect;
};

#endif // BULLET_H

​bullet.cpp​

#include "bullet.h"

Bullet::Bullet()
{
//加载子弹图片
m_Bullet.load(BULLET_PATH);
//初始子弹坐标(其实没什么意义,因为飞机发射子弹的时候会去初始化)
m_x = GAME_WIDTH/2-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);
}

void Bullet::updatePosition()
{
if( m_Free ) return;//空闲子弹,不需要管
//子弹向上移动
m_y -= m_speed;
m_Rect.moveTo(m_x,m_y);

if( m_y<=-m_Rect.height() )//子弹超过窗口,变成空闲
m_Free = true;
}

然后再回过头来看一下主场景中的设置,是如何利用飞机和子弹的

​MainScene.h​

#ifndef MAINSCENE_H
#define MAINSCENE_H

#include <QWidget>
#include <QTimer>
#include <QPainter>
#include <map.h>
#include <heroplane.h>
#include <QMouseEvent>
#include <bullet.h>
namespace Ui {
class MainScene;
}

class MainScene : public QWidget
{
Q_OBJECT

public:
explicit MainScene(QWidget *parent = 0);
~MainScene();
//初始化场景
void initScene();
//启动游戏
void playGame();
//绘制函数
void paintEvent(QPaintEvent *);
//每秒需要更新的内容
void updatePosition();
//捕捉鼠标移动的函数
void mouseMoveEvent(QMouseEvent *event);

public:
//地图对象
map *m_map;
//飞机对象
HeroPlane m_hero;
//启动游戏更新场景的定时器
QTimer timer;

private:
Ui::MainScene *ui;
};

#endif // MAINSCENE_H

​MainScene.cpp​

#include "mainscene.h"
#include "ui_mainscene.h"
#include <config.h>
#include <QDebug>
#include <QTimer>
#include <QPainter>
#include <bullet.h>
MainScene::MainScene(QWidget *parent) :
QWidget(parent),
ui(new Ui::MainScene)
{
ui->setupUi(this);
initScene();
}

MainScene::~MainScene()
{
delete ui;
}

void MainScene::initScene()
{
//设置窗口的固定尺寸,设置标题
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);
playGame();
}

void MainScene::playGame()
{
//监听定时器发送的信号
connect(&timer,&QTimer::timeout,[=](){
updatePosition();//更新飞机,子弹,地图的位置信息
update();//调用painterEvent重新绘制
});
//启动定时器
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);
}
}

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();
}
}

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);
}