C++ QT大作业:飞机大战升级版

下面将由我来向大家介绍我本学期C++大作业飞机大战的具体内容:

首先,我向大家介绍一下游戏的玩法。点击开始游戏,我们可以通过移动鼠标来操控英雄飞机击杀敌机。击杀敌机后金币数量增加,当英雄战机与敌机碰撞后生命值会减少,生命值小于0时游戏结束。
请添加图片描述
然后,在击杀一定数量的敌机后,英雄战机触发武器升级,在这里我设置了两次升级:第一次为开启英雄战机的副弹夹;

请添加图片描述

第二次为增加战机子弹的射速。
请添加图片描述

在游戏进行的过程中,战机会随机进入流星雨副本,在通过流星雨副本后,英雄战机会被赋予一层保护罩。这个保护罩的功能就是在英雄战机遇到大BOSS可以每隔1.5s恢复一点生命值。有了这个保护罩以后,击杀BOSS成功的概率会大大增加,当然通过这个副本也需要玩家一定的技术,下图便是战机穿过流星雨副本的状态。
请添加图片描述

最后,随着战斗的深入进行,英雄战机终于到达了最终关卡——BOSS战机。BOSS战机会连续且不定时的发射大量子弹。英雄战机此时不仅要躲避BOSS发出的子弹,还要击杀随机飞来的小怪敌机。直到BOSS血量小于0,BOSS被击败,游戏通关。
请添加图片描述

接下来是游戏的一些辅助功能:暂停按钮、购买生命按钮、主菜单界面下的切换关卡功能、选择战机和弹药功能。
请添加图片描述请添加图片描述
我设计该游戏的新颖之处在于
自主实现了:
1.战机的两次升级;2.流星雨副本;3.飞机保护伞及其回血功能;4.BOSS关卡以及BOSS动态子弹的发射;5.游戏关卡的切换;6.战机配置的切换

然后我来带这大家体验一下我的飞机大战游戏…

体验过飞机大战后我来向大家介绍一下游戏实现的核心代码:

1.初始化场景void initScene();:在该函数中我进行了初始化窗口大小、设置窗口标题、设置用于地图滚动刷新的定时器间隔、初始化敌机、BOSS、流星雨出场时间间隔、以及我们刚刚看到游戏主界面的一些按钮。

	//初始化窗口大小
    setFixedSize(GAME_WIDTH,GAME_HEIGHT);

    //设置窗口标题
    setWindowTitle(GAME_TITLE);

    //设置定时器间隔:用于地图滚动刷新
    m_Timer.setInterval(GAME_RATE);

    //初始化敌机出场时间间隔
    m_recorder = 0;

    //初始化boss出场时间间隔
    b_recorder = 0;

    //随机数种子(解决rand伪随机)
    srand((unsigned int)time(NULL));  //头文件  #include <ctime>


    //战机升级提示
    test1 = new QLabel(this);
    test1->setText("# 战机升级👆两翼弹夹打开 #");
    test1->setStyleSheet("color:yellow");
    test1->move(BUTTON_X - 50, GAME_HEIGHT * 0.3);
    test1->hide();   

2.启动游戏 用于启动定时器对象void playGame();:该函数的核心在于启动一个定时器并且监听定时器的信号,并在监听信号的过程中调用
敌机出场、更新游戏中所有元素的坐标updatePosition();、将游戏中的元素绘制到屏幕中、以及飞机与子弹元素的碰撞检测功能,这样就可以实现游戏的动态效果。

void MainScene::playGame()
{
    //启动背景音乐
    QSound::play(SOUND_BACKGROUND);

    //玩游戏 启动定时器
    m_Timer.start();

    //监听定时器的信号
    if(ii == 0)//解决从新启动速度叠加问题
    {
        //解决从新启动速度叠加问题,ii置1后便不会在原有的基础上再次打开定时器造成速度叠加
        ii = 1;
        connect(&m_Timer , &QTimer::timeout,[=](){
            //敌机出场
            enemyToScene();
            //boss出场
            bossToScene();
            //fboss出场
            finalBossToScene();
            //更新游戏中所有元素的坐标
            updatePosition();
            //游戏中的元素 绘制到屏幕中
            update(); //再调用paintEvent函数(重新绘制窗口中所有信息)

            //碰撞检测
            collisionDetection();
            bossCollisiondetection();
            FinalBossCollisionDetection();

        });
    }
}

3.更新游戏中所有元素的坐标void updatePosition();:这个函数是上一个函数元素动态更新的基础,在该函数中,通过调用每个类对象中有关的更新位置坐标函数,如: m_map.mapPosition(); m_hero.m_bullets[i].updatePosition(); m_bombs[i].updateInfo();这些函数,这些类对象的函数主要功能是计算每个类对象的坐标,而我们的绘图函数是依赖元素在界面中的坐标进行的,通过用 updatePosition()函数调用每个类对象的位置坐标更新函数,就可以实现游戏元素动态更新的功能

void MainScene::updatePosition()
{
    //更新地图坐标
    m_map.mapPosition();

    //发射子弹
    m_hero.shoot();

    //计算子弹坐标
    for(int i = 0 ;i < BULLET_NUM;i++)
    {
        //如果子弹状态为非空闲,计算发射位置
        if(m_hero.m_bullets[i].m_Free == false)
        {
            m_hero.m_bullets[i].updatePosition();
        } 
    }

    //敌机坐标计算
    for(int i = 0 ; i< ENEMY_NUM;i++)
    {
        //非空闲敌机 更新坐标
       if(m_enemys[i].m_Free == false)
       {
          m_enemys[i].updatePosition();
       }
    }

    //boss坐标计算
    for(int i = 0 ; i< BOSS_NUM;i++)
    {
        //非空闲敌机 更新坐标
       if(b_enemys[i].b_Free == false)
       {
          b_enemys[i].updateBossPosition();
       }
    }

    //计算爆炸播放的图片
    for(int i = 0 ; i < BOMB_NUM;i++)
    {
        if(m_bombs[i].m_Free == false)
        {
            //更新切图信息
           m_bombs[i].updateInfo();
        }
    }

}

4.碰撞检测void collisionDetection();:如飞机、子弹这些类对象,我在类对象的创建时都为其设置了一个QRect的矩形边框,其大小近似于元素图片的大小,当两个元素如:飞机和子弹的矩形边框相交时,即定义为“碰撞”,在碰撞发生后我通过修改子弹的状态m_Free,(m_Free=TRUE时停止绘制;为FALSE时绘制),停止其绘制。由此实现了诸如子弹击中敌机后敌机爆炸的功能。

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[j].m_Free)
            {
                continue;
            }

            //如果子弹矩形框和敌机矩形框相交,发生碰撞,同时变为空闲状态即可
            if(m_enemys[i].m_Rect.intersects(m_hero.m_bullets[j].m_Rect))
            {
                //播放音效
                //QSound::play(SOUND_BOMB);
				m_hero.m_bullets[j].m_Free = true;
            }
       }
}

5.信号和槽函数的使用:本游戏中通过QT设计师界面设计出的窗口于主窗口的关联大多以信号和槽函数的使用为主,比如当鼠标单机“开始游戏”按钮后游戏开始,就是通过在鼠标点击事件发生后向定时器发送一个信号,这个信号负责开启游戏启动定时器,使游戏开始。

 //初始界面按钮
    btn1 = new QPushButton("开始游戏",this);

    btn1->move(BUTTON_X,GAME_HEIGHT * 0.5);
    connect(btn1,&QPushButton::clicked,[=](){
        //隐藏按钮
        btn1->close();
        btn2->close();
        ChoosePlane->close();
        Choose_Map->hide();
        //启动游戏
        playGame();
    });

以上就是本次C++大作业的主要内容,谢谢大家观看!

  • 7
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值