前文链接如下所示

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

QT飞机大战二(飞机类)

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

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

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

肯定有自己的资源图片

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

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

设想一下,假如需要一个子弹就 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);
}