QT实现塔防游戏5

最后一篇文章,主要是完善代码,增加其可玩性,主要有以下工作

  1. 实现地图的多样性
  2. 实现敌人的多样性
  3. 实现不同传奇子弹的多样性
  4. 实现不同地图传奇的多样性
  5. 创建文本界面来说明各个传奇功能

1.实现地图的多样性

在choose.cpp文件中添加

  //  开始第2关
        connect(ui->secondbtn,&QPushButton::clicked,[=](){
            Gamescene *game=new Gamescene(2);
            this->hide();
            game->setPath(":/image/map2.jpg");
            game->addWayPoint2();
            game->addLegend_location2();
            game->show();
        });

 在gamescene中添加

//.h
  //    添加新的航点
    void addWayPoint2();
    //    添加传奇坐标
    void addLegend_location2();
.cpp中添加
void Gamescene::addWayPoint2()
{
    WayPoint *WayPoint1=new WayPoint(QPoint(728,318));
    mynextWayPointlist.push_back(WayPoint1);

    WayPoint *WayPoint2=new WayPoint(QPoint(1522,318));
    WayPoint1->setNextWayPoint(WayPoint2);
    mynextWayPointlist.push_back(WayPoint2);

    WayPoint *WayPoint3=new WayPoint(QPoint(1522,605));
    WayPoint2->setNextWayPoint(WayPoint3);
    mynextWayPointlist.push_back(WayPoint3);

    WayPoint *WayPoint4=new WayPoint(QPoint(406,605));
    WayPoint3->setNextWayPoint(WayPoint4);
    mynextWayPointlist.push_back(WayPoint4);

    WayPoint *WayPoint5=new WayPoint(QPoint(406,870));
    WayPoint4->setNextWayPoint(WayPoint5);
    mynextWayPointlist.push_back(WayPoint5);

    WayPoint *WayPoint6=new WayPoint(QPoint(1195,870));
    WayPoint5->setNextWayPoint(WayPoint6);
    mynextWayPointlist.push_back(WayPoint6);

}
void Gamescene::addLegend_location2()
{
    //用二维数组实现传奇位置
    int location[9][2]=
    {
        {1145,406},{812,406},{518,406},{660,684},{970,684},{195,550},{966,134},{1290,134},{195,815}
    };

    QPoint legend_loc[9];
    for(int i=0;i<9;i++)
    {
        legend_loc[i]=QPoint(location[i][0],location[i][1]);
    }
    //用循环创建传奇列表
    int len=sizeof(legend_loc)/sizeof(legend_loc[0]);
    for(int i=0;i<len;i++)
    {
        mylegend_loclist.push_back(legend_loc[i]);
    }
}

顺便在构造函数中添加myround,便于后续使用,例如绘画函数

 //画出基地的图案,和基地血量图案
    QString homePath=":/image/Home.png";
    QString hpPath=":/image/life.png";
    if(myround==1)
    {
        painter.drawPixmap(1615,260,140,140,homePath);
        painter.drawPixmap(1768,297,85,85,hpPath);
    }
    else {
        painter.drawPixmap(1130,795,140,140,homePath);
        painter.drawPixmap(1278,832,85,85,hpPath);
    }

 

实现以下效果 

 2.实现敌人的多样性

enemy.cpp中添加

 //波数
    mywave(wave),
    //指向游戏界面
    mygame(game),
    //初始坐标
    mypos(startWayPoint->getPos())
{
    //初始化敌人的生命,图片,移动速度
    switch (mywave)
    {
    case 1:
    {
        mymaxHp=400;
        mypath=":/image/enemy1.png";
        mywalkingSpeed=11;
        mymoney=20;
    }   break;
    case 2:
    {
        mymaxHp=200;
        mypath=":/image/enemy2.png";
        mywalkingSpeed=17;
        mymoney=30;
    }   break;
    case 3:
    {
        mymaxHp=700;
        mypath=":/image/enemy3.png";
        mywalkingSpeed=9;
        mymoney=40;
    }   break;
    case 4:
    {
        mymaxHp=480;
        mypath=":/image/enemy4.png";
        mywalkingSpeed=13;
        mymoney=50;
    }   break;
    case 5:
    {
        mymaxHp=600;
        mypath=":/image/enemy5.png";
        mywalkingSpeed=15;
        mymoney=60;
    }   break;
    case 6:
    {
        mymaxHp=800;
        mypath=":/image/enemy1.png";
        mywalkingSpeed=12;
        mymoney=25;
    }   break;
    case 7:
    {
        mymaxHp=400;
        mypath=":/image/enemy2.png";
        mywalkingSpeed=18;
        mymoney=35;
    }   break;
    case 8:
    {
        mymaxHp=1400;
        mypath=":/image/enemy3.png";
        mywalkingSpeed=10;
        mymoney=45;
    }   break;
    case 9:
    {
        mymaxHp=960;
        mypath=":/image/enemy4.png";
        mywalkingSpeed=14;
        mymoney=55;
    }   break;
    case 10:
    {
        mymaxHp=1200;
        mypath=":/image/enemy5.png";
        mywalkingSpeed=16;
        mymoney=65;
    }   break;
    }
    //当前生命值初始化
    mycurrentHp=mymaxHp*round;
    //移动状态初始化
    myactive=false;
    //下一个航点初始化
    mydestinationWayPoint=startWayPoint->getNextWayPoint();
}

3.子弹多样性(与传奇多样性同时进行)


Legends::Legends(QPoint pos,Gamescene * game,int num)
{
    mynum=num;
    mypos=pos;
    mygame=game;;
    myattacking=false;
    mychooseEnemy=NULL;

    switch (mynum)
    {
    case 1:
    {
        Legend[mynum].myfireRate=1000;
        Legend[mynum].mydamage=75;
        Legend[mynum].myattackRange=300;
        Legend[mynum].mypath=":/image/ym.png";
        Legend[mynum].mymoney=100;
        Legend[mynum].mybulletPath=":/image/bullet1.png";
    }
        break;
    case 2:
    {
        Legend[mynum].myfireRate=2000;
        Legend[mynum].mydamage=200;
        Legend[mynum].myattackRange=450;
        Legend[mynum].mypath=":/image/pz.png";
        Legend[mynum].mymoney=180;
         Legend[mynum].mybulletPath=":/image/bullet2.png";
    }
        break;
    case 3:
    {
        Legend[mynum].myfireRate=500;
        Legend[mynum].mydamage=75;
        Legend[mynum].myattackRange=250;
        Legend[mynum].mypath=":/image/mm.png";
        Legend[mynum].mymoney=200;
         Legend[mynum].mybulletPath=":/image/bullet3.png";
    }
        break;
    case 4:
    {
        Legend[mynum].myfireRate=1500;
        Legend[mynum].mydamage=150;
        Legend[mynum].myattackRange=350;
        Legend[mynum].mypath=":/image/pn.png";
        Legend[mynum].mymoney=250;
         Legend[mynum].mybulletPath=":/image/bullet4.png";
    }
        break;
    case 5:
    {
        Legend[mynum].myfireRate=700;
        Legend[mynum].mydamage=150;
        Legend[mynum].myattackRange=375;
        Legend[mynum].mypath=":/image/gz.png";
        Legend[mynum].mymoney=300;
         Legend[mynum].mybulletPath=":/image/bullet5.png";
    }
        break;
    }
    myupdate1Money=Legend[mynum].mymoney*2-100;
    myfireRateTimer=new QTimer(this);
    connect(myfireRateTimer,SIGNAL(timeout()),this,SLOT(shootWeapon()));
}

简单修改bullet构造函数即可(难的是找素材和ps)

4.实现不同地图传奇多样性

在gamescene的鼠标事件修改

  else if(legend_locationList->hasButton() && !legend_locationList->hasLegend())
            {
                //如果鼠标点击的地方在第一张图片内,创造第一个传奇
                if(presspos.x()<legend_locationList->getButton()->getPos().x()+120 && canBuy())
                {
                    legend_locationList->setHasLegend1(true);
                    Legends * legend=new Legends(legend_locationList->getCenterPos(),this,1);
                    myMoney-=legend->getMoney();
                    legend_locationList->setLegend(legend);
                    mylegendlist.push_back(legend);
                }
                //鼠标点击点在第二张图片内,创建第二种传奇
                else if(presspos.x()>legend_locationList->getButton()->getPos().x()+125
                        && presspos.x()<legend_locationList->getButton()->getPos().x()+245
                        && ((myround==1&& canBuy2())||(myround==2&&canBuy4())))
                {
                    legend_locationList->setHasLegend2(true);
                    Legends * legend=new Legends(legend_locationList->getCenterPos(),this,(myround==1?2:4));
                    myMoney-=legend->getMoney();
                    legend_locationList->setLegend(legend);
                    mylegendlist.push_back(legend);
                }
                //鼠标点击点在第二张图片内,创建第三种传奇
                else if(presspos.x()>legend_locationList->getButton()->getPos().x()+250 && presspos.x()<legend_locationList->getButton()->getPos().x()+375
                        && ((myround==1&& canBuy3())||(myround==2&&canBuy5())))
                {
                    legend_locationList->setHasLegend3(true);
                    Legends * legend=new Legends(legend_locationList->getCenterPos(),this,(myround==1?3:5));
                    myMoney-=legend->getMoney();
                    legend_locationList->setLegend(legend);
                    mylegendlist.push_back(legend);
                }

selectbutton中的绘画函数也要修改

void SelectButton::draw(QPainter *painter) const
{
    painter->save();
    painter->drawPixmap(mypos.x(),mypos.y(),120,120,myselectBoxImagePath[0]);
    if(myround==1)
    {
        painter->drawPixmap(mypos.x()+125,mypos.y(),120,120,myselectBoxImagePath[1]);
        painter->drawPixmap(mypos.x()+250,mypos.y(),120,120,myselectBoxImagePath[2]);
    }
    else {
        painter->drawPixmap(mypos.x()+125,mypos.y(),120,120,myselectBoxImagePath[3]);
        painter->drawPixmap(mypos.x()+250,mypos.y(),120,120,myselectBoxImagePath[4]);
    }
    painter->restore();
}

5.实现文件读取传奇介绍

创建file类,设计ui、

///.h
#ifndef FILE_H
#define FILE_H

#include <QWidget>
#include<qfiledialog.h>
#include<qfile.h>

namespace Ui {
class File;
}

class File : public QWidget
{
    Q_OBJECT

public:
    explicit File(QWidget *parent = nullptr);
    ~File();

private:
    Ui::File *ui;
};
#endif // FILE_H
//.cpp
#include "file.h"
#include "ui_file.h"

File::File(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::File)
{
    ui->setupUi(this);
    this->setWindowTitle("APEX");
//    固定窗口大小
    this->setFixedSize(1200,500);
    //点击选取文件按钮,弹出文件对话框
    connect(ui->pushButton,&QPushButton::clicked,[=](){
//设置文件路径
        QString path = QFileDialog::getOpenFileName(this,"打开文件","E:\\QT\\QTcode\\main");
//定义文件路径
        QFile file(path); //参数就是读取文件的路径
        //设置打开方式,只读
        file.open(QIODevice::ReadOnly);
        //设置按照行读
        QByteArray array;
        while( !file.atEnd())
        {
            array += file.readLine();
        }
        //将读取到的数据 放入textEdit中
        ui->textEdit->setText(array);
        //对文件对象进行关闭
        file.close();
    });
}
File::~File()
{
    delete ui;
}

与choose界面连接

//打开英雄介绍界面
    connect(ui->pushButton,&QPushButton::clicked,[=](){
       File *file=new File;
       file->show();
    });

}

实现以下效果 

 ok,大功告成,修改以下数据增加可玩性,小白的第一个游戏就完成啦!

总述:首先是收获方面,通过这一次游戏的设计,我将之前所讲的许多知识点有机地串联起来,又对知识间千丝万缕的联系有了新的认识。通过上网查阅资料,我又了解了Qt的许多强大的功能,并将其中的一部分应用到我自己的程序中,这让我非常有成就感。 另一方面,游戏数据的设计之难也远远超出了我的想象。这次大作业也暴露出我的许多问题。首先,对c++面向对象的变成不熟悉,在前期常常无法熟练的将各个类成功联系,但这一点随着代码的进行越来越熟练。其次,之前我一直都是先编程,再照着程序写我的设计图,这让我吃了不少苦头,导致程序经历许多次的“大换血”,有一些其实是可以避免的。我之前应该设计得再充分一点,就能避免许多低效的事情发生,毕竟补丁时常是越打越多的,最后程序的可读性不高。 总而言之,作为学习c++后的第一次实践,自己还是很满意的,在构建中提升自己,在改bug中磨练自己,在查资料中丰厚自己,这也许就是学习程序的快乐叭!

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值