Qt之塔防游戏 c++ (三)
作者:互联网
在上两篇文章中,我们实现了一个简单的塔防游戏,但是游戏功能还比较单一。接下来,我们对该塔防游戏进行优化,让它有更多的功能。
在本篇文章中我们要完成如下功能:
1:实现多样化选择防御塔
2:对防御塔进行升级和移除
3:实现多关卡的绘制,供玩家选择
4:细微处的完善
我们开始吧!
实现多样化选择防御塔
要实现选择防御塔,我们要先构造一个选择框,即完成selectButton类。
先添加selectButton类文件
selectButton.h中的实现:
#ifndef SELECTBUTTON_H
#define SELECTBUTTON_H
#include <QPainter>
#include <QString>
#include <QPoint>
#include <QSize>
#include "mainwindow.h"
class MainWindow;
class selectButton
{
public:
selectButton(QPoint pos,MainWindow * game);
~selectButton();
void draw(QPainter * painter)const;//绘画选择框
void getRemoved();//选择框被点击了以后,就要被移除
bool containPos(QPoint pos);//判断鼠标的点击点,是否在选择框的内部
QPoint getPos();//得到选择框的左上店
private:
MainWindow * m_game;//指向mainwindow的指针
QPoint m_pos;//selectButton图片的左上角
QString m_selectBoxImagePath[3];//用来储存选择框内的防御塔的图片,我设置的三个防御塔可以选择,就储存三张图片
static const QSize m_fixedSize;
};
#endif // SELECTBUTTON_H
同时,在TowerPosition.h中进行相应的添加:
//类外
#include "selectbutton.h"
class selectButton;
//类内
public:
bool hasButton();//判断该位置有没有button
void setHasButton(bool hasButton=true);//设置是否有button
void setButton(selectButton * button);//设置button
selectButton * getButton();//得到该位置的button
bool hasTower1();//判断是否有第一种塔
void setHasTower1(bool hasTower1=true);//判断是否有第一种塔
bool hasTower2();
void setHasTower2(bool hasTower2=true);
bool HasTower3();
void setHasTower3(bool hasTower3=true);
private:
bool m_hasButton;
bool m_hasTower1;
bool m_hasTower2;
bool m_hasTower3;
selectButton * m_button;//私有化button
在TowerPosition.cpp中对其进行实现:
//构造函数中添加:
m_hasTower1(false),
m_hasTower2(false),
m_hasTower3(false),
m_hasButton(false)
//其他函数
bool TowerPosition::hasButton()
{
return m_hasButton;
}
void TowerPosition::setHasButton(bool hasButton)
{
m_hasButton=hasButton;
}
void TowerPosition::setButton(selectButton *button)
{
m_button=button;
}
selectButton * TowerPosition::getButton()
{
return m_button;
}
void TowerPosition::setHasTower1(bool hasTower1)
{
this->m_hasTower1=hasTower1;
setHasTower(hasTower1);
}
bool TowerPosition::hasTower1()
{
return m_hasTower1;
}
void TowerPosition::setHasTower2(bool hasTower2)
{
this->m_hasTower2=hasTower2;
setHasTower(hasTower2);
}
bool TowerPosition::hasTower2()
{
return m_hasTower2;
}
void TowerPosition::setHasTower3(bool hasTower3)
{
m_hasTower3=hasTower3;
setHasTower(hasTower3);
}
bool TowerPosition::hasTower3()
{
return m_hasTower3;
}
然后到mainwindow.h中,添加有关button的代码:
//类外
#include "selectbutton.h"
class selectButton;
//类内
public:
bool canBuyTower();//判断是否可以买第一种塔,这个我们原来已经写过了
bool canBuyTower2();//判断是否可以买第二种塔
bool canBuyTower3();//判断是否可以买第三种塔
void removeButton(selectButton * button);//在mainwindow中对button进行移除
private:
QList<selectButton * > m_selectButtonList;//用来储存selectButton的list
在mainwindow.cpp中对上面的代码进行实现:
#include "selectButton"
bool MainWindow::canBuyTower2()
{
if(m_playerGlod>=400)
{
return true;
}
return false;
}
bool MainWindow::canBuyTower3()
{
if(m_playerGlod>=500)
{
return true;
}
return false;
}
void MainWindow::removeButton(selectButton *button)
{
m_selectButtonList.removeOne(button);
}
ok,我们已经把button和其他的类做了一个连接,现在我们返回selectButton.cpp中,对selectButton类进行实现:
#include "selectbutton.h"
const QSize selectButton::m_fixedSize(105,35);
selectButton::selectButton(QPoint pos,MainWindow * game):
m_game(game),
m_pos(pos)
{
//三张图片的路径信息
m_selectBoxImagePath[0]=":/images/tower1.jpg";
m_selectBoxImagePath[1]=":/images/tower2.png";
m_selectBoxImagePath[2]=":/images/tower3.png";
}
selectButton::~selectButton()
{
m_game=NULL;
}
void selectButton::draw(QPainter *painter) const
{
painter->save();
painter->drawPixmap(m_pos.x(),m_pos.y(),m_selectBoxImagePath[0]);
painter->drawPixmap(m_pos.x()+35,m_pos.y(),m_selectBoxImagePath[1]);
painter->drawPixmap(m_pos.x()+70,m_pos.y(),m_selectBoxImagePath[2]);
painter->restore();
}
void selectButton::getRemoved()
{
m_game->removeButton(this);
}
bool selectButton::containPos(QPoint pos)
{
bool xInhere=pos.x()>m_pos.x() && pos.x()<m_pos.x()+m_fixedSize.width();
bool yInhere=pos.y()>m_pos.y() && pos.y()<m_pos.y()+m_fixedSize.height();
return xInhere && yInhere;
}
QPoint selectButton::getPos()
{
return this->m_pos;
}
现在对mainwindow.cpp中的mousePressEvent()进行改造使其能够完成防御塔的选择,在此之前,为了实现不同防御塔的不同图片,我们需要回到tower.h中,把tower的构造函数修改成:
Tower(QPoint pos,MainWindow * game,QString path,int damage);
同时在tower.cpp中,构造函数的实现也需要相应的修改,我只截取出修改的部分:
Tower::Tower(QPoint pos,MainWindow * game,QString path,int damage):
m_attacking(false),
m_damage(damage),
现在可以对mousePressEvent()进行改造啦,实现多样化防御塔的选择。
改造后的mousePressEvent()的while循环内部:
while(it!=m_towerPositionList.end())//遍历所有的防御塔坑
{
if(Qt::LeftButton==event->button())//如果是鼠标左键点击
{
if(!it->hasButton() && it->ContainPos(pressPos) && !it->hasTower())//如果没有button,点击的点在防御塔坑的内部
{
QPoint tmp(it->getPos().x()-35,it->getPos().y()-35);//得到该防御塔坑处的button的左上点
selectButton * button=new selectButton(tmp,this);//创建一个button
it->setHasButton(true);//设置该位置有button
it->setButton(button);//设置该位置的button
m_selectButtonList.push_back(button);//把这个button加入到mainwidnow中
update();
break;
}
else if(it->hasButton() && it->getButton()->containPos(pressPos) && !it->hasTower())//如果这个位置有button,并且没有防御塔
{
if(pressPos.x()<it->getButton()->getPos().x()+35 && canBuyTower())//如果鼠标点击的地方在第一张图片内,创造第一个防御塔
{
it->setHasTower1(true);
m_playerGlod-=tower1Cost;
QString path=":/images/tower1.jpg";
Tower * tower=new Tower(it->getCenterPos(),this,path,10);//攻击力为10的第一种防御塔
m_towerList.push_back(tower);
}
else if(pressPos.x()>it->getButton()->getPos().x()+35 && pressPos.x()<it->getButton()->getPos().x()+70
&& canBuyTower2())//鼠标点击点在第二张图片内,创建第二种防御塔
{
it->setHasTower2(true);
m_playerGlod-=tower2Cost;
QString path=":/images/tower2.png";
Tower * tower=new Tower(it->getCenterPos(),this,path,15);//攻击力为15的第二种防御塔
m_towerList.push_back(tower);
}
else if(pressPos.x()>it->getButton()->getPos().x()+70 && pressPos.x()<it->getButton()->getPos().x()+105
&& canBuyTower3())
{
it->setHasTower3(true);
m_playerGlod-=tower3Cost;
QString path=":/images/tower3.png";
Tower * tower=new Tower(it->getCenterPos(),this,path,20);
m_towerList.push_back(tower);
}
//构造完防御塔后,原来的button就要消失,下面对该button进行移除
it->getButton()->getRemoved();
it->setButton(NULL);
it->setHasButton(false);
update();
break;
}
}
++it;
}
同时在paintEvent()种添加对button的绘画:
foreach(const selectButton * button,m_selectButtonList)
button->draw(&painter);
运行上述代码,就可以对防御塔进行选择啦!涉及动态效果,我就不展示了。
对防御塔进行升级和移除
为了完成防御塔的升级的移除,我们同样需要构造一个button,来进行有选择地点击实现。我们命名为selectButton2类。创建文件selectButton2
selectButton2.h中的实现:
#ifndef SELECTBUTTON2_H
#define SELECTBUTTON2_H
#include <QPainter>
#include <QPoint>
#include <QRect>
#include <QSize>
#include "mainwindow.h"
#include "tower.h"
class MainWindow;
class Tower;
class selectButton2
{
public:
selectButton2(QPoint pos,MainWindow * game);
~selectButton2();
void draw(QPainter * painter)const;//绘画button
void getRemoved();//移除button2
Tower * getTower();//得到该button2地防御塔
void setTower(Tower * tower);//设置该button2地防御塔
bool containPos(QPoint pos);//判断点击点是否在button2的内部
QPoint getPos();//得到button2的左上点
private:
MainWindow * m_game;
Tower * m_tower;
QPoint m_pos;
static const QSize m_fixedSize;
};
#endif // SELECTBUTTON2_H
下面将selectButton2类和其他的类进行连接
在TowerPosition.h中:
//类外
#include "selectbutton2.h"
class selectButton2;
//类内
public:
bool hasButton2();//判断该位置有没有button2
void setHasButton2(bool hasButton2=true);//设置是否有button2
void setButton2(selectButton2 * button);//设置button2
selectButton2 * getButton2();//得到该位置的button2
void setHasUpdate1(bool hasUpdate1);//设置是否有第一次升级
bool hasUpdate1();
void setHasUpdate2(bool hasUpdate2);//设置是否有第二次升级
bool hasUpdate2();
void setTower(Tower * tower);
Tower * getTower();
void setRemoveTower();//设置移除防御塔
private:
bool m_hasButton2;
selectButton2 * m_button2;//私有化button2
bool m_hasUpdate1;
bool m_hasUpdate2;
Tower * m_tower;//私有化成员tower,为移除做准备
在TowerPosition.cpp中对上面的代码进行实现:
//构造函数截取部分
m_hasTower3(false),
m_hasUpdate1(false),
m_hasUpdate2(false),
m_hasButton(false),
m_hasButton2(false)
//其他函数
void TowerPosition::setHasButton2(bool hasButton2)
{
m_hasButton2=hasButton2;
}
bool TowerPosition::hasButton2()
{
return m_hasButton2;
}
void TowerPosition::setHasUpdate1(bool hasUpdate1)
{
m_hasUpdate1=hasUpdate1;
}
bool TowerPosition::hasUpdate1()
{
return m_hasUpdate1;
}
void TowerPosition::setHasUpdate2(bool hasUpdate2)
{
m_hasUpdate2=hasUpdate2;
}
bool TowerPosition::hasUpdate2()
{
return m_hasUpdate2;
}
void TowerPosition::setButton2(selectButton2 *button)
{
m_button2=button;
}
void TowerPosition::setTower(Tower *tower)
{
m_tower=tower;
}
Tower * TowerPosition::getTower()
{
return m_tower;
}
selectButton2 * TowerPosition::getButton2()
{
return m_button2;
}
void TowerPosition::setRemoveTower()
{
setTower(NULL);
setHasTower(false);
setHasTower1(false);
setHasTower2(false);
setHasTower3(false);
setHasUpdate1(false);
setHasUpdate2(false);
}
在mainwindow.h中进行连接:
//类外
#include "selectbutton2.h"
class selectButton2;
//类内
public:
void removeButton2(selectButton2 * button);//在mainwindow中对button2进行移除
void removeTower(Tower * tower);
bool canUpdate1();//判断是否可以第一次升级
bool canUpdate2();//判断是否可以第二次升级
private:
QList<selectButton2 *> m_selectButton2List;//用来储存selectButton2的list
在mainwindow.cpp中进行实现:
void MainWindow::removeTower(Tower *tower)
{
m_towerList.removeOne(tower);
}
void MainWindow::removeButton2(selectButton2 *button)
{
m_selectButton2List.removeOne(button);
}
bool MainWindow::canUpdate1()
{
if(m_playerGlod>=300)
{
return true;
}
return false;
}
bool MainWindow::canUpdate2()
{
if(m_playerGlod>=400)
{
return true;
}
return false;
}
下面我们对Tower进行改造,使其具备升级的移除的条件:
tower.h中:
//类外
#include "tower"
class Tower;
//类内
public:
void reSetDamage(int damage);//重新设置攻击力
int getDamgae();//得到防御塔的攻击力
void levelChange();//防御塔升级
int getLevel();//得到防御塔的等级
void getRemoved();//防御塔被移除
private:
int m_level;
在tower.cpp中对其实现:
//构造函数,截取部分
m_chooseEnemy(NULL),
m_level(1),
m_pos(pos),
//其他函数
void Tower::reSetDamage(int damage)
{
m_damage=damage;
}
int Tower::getDamgae()
{
return m_damage;
}
void Tower::levelChange()
{
m_level++;
}
int Tower::getLevel()
{
return m_level;
}
void Tower::getRemoved()
{
if(getAttackedEnemy())//这里要判断是不是空指针NULL
{
getAttackedEnemy()->getLostSight(this);//移除后,敌人被该防御塔丢失视野
}
m_game->removeTower(this);
}
好啦,我们完成了将selectButton2与其他的类连接,现在我们实现selectButton2.cpp:
#include "selectbutton2.h"
#include "mainwindow.h"
#include <QPainter>
#include <QRect>
#include <QPoint>
#include <QString>
static const int towerupdate1Cost=300;//塔第一次升级的价钱
static const int towerupdate2Cost=400;//第二次升级
const QSize selectButton2::m_fixedSize(100,50);
selectButton2::selectButton2(QPoint pos,MainWindow * game):
m_game(game),
m_pos(pos)
{
}
selectButton2::~selectButton2()
{
m_game=NULL;
m_tower=NULL;
}
QPoint selectButton2::getPos()
{
return m_pos;
}
void selectButton2::getRemoved()
{
m_game->removeButton2(this);
}
void selectButton2::setTower(Tower *tower)
{
m_tower=tower;
}
void selectButton2::draw(QPainter *painter) const
{
int level=m_tower->getLevel();
painter->save();
painter->setPen(Qt::red);
//不同等级升级的钱不一样,所以画出来也要不一样
if(level==1)
{//类似waves和hp的绘画
painter->drawText(QRect(m_pos.x(),m_pos.y(),100,25),QString("update: %1").arg(towerupdate1Cost));
}
else
{
painter->drawText(QRect(m_pos.x(),m_pos.y(),100,25),QString("update: %1").arg(towerupdate2Cost));
}
painter->drawText(QRect(m_pos.x(),m_pos.y()+25,100,25),QString("remove"));//画出移除框
painter->restore();
}
bool selectButton2::containPos(QPoint pos)
{
bool xInHere=pos.x()>m_pos.x() && pos.x()<m_pos.x()+m_fixedSize.width();
bool yInHere=pos.y()>m_pos.y() && pos.y()<m_pos.y()+m_fixedSize.height();
return xInHere && yInHere;
}
好啦,我们再对mousePressEvent()进行添加改造,就可以实现防御塔的移除和升级了:
//先设立一个和左键点击对立的右键点击事件:
//这个else时和左键点击事件的if对立的
else if(Qt::RightButton==event->button())//如果是鼠标右键点击
{//在有防御塔的情况下,右键会出现选择框,升级还有移除
if(it->ContainPos(pressPos) && (!it->hasButton2()) && it->hasTower())
{
it->setHasButton2(true);
QPoint tmp(it->getPos().x()+35,it->getPos().y());//我是把防御塔坑的右上顶点当作button2的端点
selectButton2 * button2=new selectButton2(tmp,this);
button2->setTower(it->getTower());//我写这个setTower()的目的是得到防御塔的等级,不同等级的updatecost不一样
m_selectButton2List.push_back(button2);
it->setButton2(button2);
update();
break;
}
}
//再添加
//下面这个else if结构添加在第二层的if中,详情可见源代码中的mousePressEvent函数
//下面的判断语句,要先判断hasbutton2,不能先判断containPos.因为如果没有button2,在进入这个判断框的时候,会先getbutton2,但是button2是NULL,程序会异常结束。
else if(it->hasButton2() && it->getButton2()->containPos(pressPos) && !it->hasButton() && !it->ContainPos(pressPos) &&it->hasTower())
{//在有button2的情况下,点击button2的内部
if(pressPos.y()<(it->getButton2()->getPos().y()+25))//我直接设置了第一个选择框的height是25,这里就直接用25了
{//对防御塔进行升级
if(canUpdate1() && !it->hasUpdate1() && it->hasTower())
{
it->setHasUpdate1(true);
m_playerGlod-=towerupdate1Cost;
it->getTower()->reSetDamage(it->getTower()->getDamage()+10);
it->getTower()->levelChange();
}
else if(canUpdate2() && it->hasUpdate1() && !it->hasUpdate2())
{
it->setHasUpdate2(true);
m_playerGlod-=towerupdate2Cost;
it->getTower()->reSetDamage(it->getTower()->getDamage()+20);
it->getTower()->levelChange();
}
}
else if(pressPos.y()>it->getButton2()->getPos().y()+25)
{//对防御塔进行移除
awardGlod();//移除防御塔奖励200
it->getTower()->getRemoved();//这个移除和前面写的几个移除都是一样的
it->setRemoveTower();//设置移除防御塔带来的其他变化
}
//点击了button2的内部,button2就要被移除
it->getButton2()->getRemoved();
it->setButton2(NULL);
it->setHasButton2(false);
update();
break;
}
然后再到paintEvent()中,添加对button2的绘画:
foreach(const selectButton2 * button2,m_selectButton2List)
button2->draw(&painter);
ok,运行上述代码,我们就可以成功完成防御塔的升级和移除了。其中的主要代码分为两块,一个是button和其他类的连接,另外就是再mousePressEvent()中对他们进行鼠标上的点击实现。下面我们开始不同关卡的绘制。
实现多关卡的绘制,供玩家选择
为实现多关卡,我们要另外构造一个界面,让玩家进行选择。我们创建一个startFrom类(和创建mainwindow的方式一样)。
在startFrom.h中进行实现:
#ifndef STARTFROM_H
#define STARTFROM_H
#include <QWidget>
#include "mainwindow.h"//包含mainwindow文件
namespace Ui {
class startFrom;
}
class startFrom : public QWidget
{
Q_OBJECT
public:
explicit startFrom(QWidget *parent = nullptr);
~startFrom();
void paintEvent(QPaintEvent *event);//只用添加这个绘画类函数就可以了
private:
Ui::startFrom *ui;
};
#endif // STARTFROM_H
好啦,现在我们需要在startFrom.ui界面添加按钮,使其可以完成和mainwindow之间的转换。
把左边的Push Button拖动到右边的界面。
这里我们涉及了四个关卡,制作者可以根据自己的需要再制作更多的关卡,方法是一样的。由于我们新增了三个关卡,和关卡1一样,我们需要对其他的关卡进行绘制。因此再mainwindow.h中添加对其他地图的绘制:
//类外
#include <QString>
//类内
public:
void addWayPoint2();
void loadTowerPosition2();
void loadTowerPosition3();
void addWayPoint3();
void loadTowerPosition4();
void addWayPoint4();
QString getPath();//得到地图图片路径
void setPath(QString path);//设置地图图片路径
private:
QString m_path;
再到mainwindow.cpp中对他们进行实现:
绘制这三个地图的方法和绘制第一张地图的方法是一样的,需要制作者耐心地寻找航点和防御塔坑点。
由于篇幅关系,我就不把三个地图的具体绘制方法放出来了,就列举一个例子。如果你需要其他地图的具体绘制数据的话,在我第一篇文章中有我源代码的链接。
void MainWindow::loadTowerPosition2()
{
QPoint pos[]=
{
QPoint(171,240),
QPoint(251,240),
QPoint(325,240),
QPoint(270,170),
QPoint(345,170),
QPoint(420,170),
QPoint(245,100),
QPoint(520,170),
};
for(int i=0;i<8;i++)
{
m_towerPositionList.push_back(pos[i]);
}
}
void MainWindow::addWayPoint2()
{
wayPoint * waypoint1=new wayPoint(QPoint(177,371));
m_wayPointList.push_back(waypoint1);
wayPoint * waypoint2=new wayPoint(QPoint(177,292));
waypoint1->setNextWayPoint(waypoint2);
m_wayPointList.push_back(waypoint2);
wayPoint * waypoint3=new wayPoint(QPoint(388,292));
waypoint2->setNextWayPoint(waypoint3);
m_wayPointList.push_back(waypoint3);
wayPoint * waypoint4=new wayPoint(QPoint(388,222));
waypoint3->setNextWayPoint(waypoint4);
m_wayPointList.push_back(waypoint4);
wayPoint * waypoint5=new wayPoint(QPoint(248,222));
waypoint4->setNextWayPoint(waypoint5);
m_wayPointList.push_back(waypoint5);
wayPoint * waypoint6=new wayPoint(QPoint(248,151));
waypoint5->setNextWayPoint(waypoint6);
m_wayPointList.push_back(waypoint6);
wayPoint * waypoint7=new wayPoint(QPoint(481,151));
waypoint6->setNextWayPoint(waypoint7);
m_wayPointList.push_back(waypoint7);
wayPoint * waypoint8=new wayPoint(QPoint(481,223));
waypoint7->setNextWayPoint(waypoint8);
m_wayPointList.push_back(waypoint8);
wayPoint * waypoint9=new wayPoint(QPoint(598,223));
waypoint8->setNextWayPoint(waypoint9);
m_wayPointList.push_back(waypoint9);
wayPoint * waypoint10=new wayPoint(QPoint(598,149));
waypoint9->setNextWayPoint(waypoint10);
m_wayPointList.push_back(waypoint10);
}
void MainWindow::setPath(QString path)
{
m_path=path;
}
QString MainWindow::getPath()
{
return m_path;
}
再到paintEvent()中,对地图绘画进行改造:
QString path=getPath();
painter.drawPixmap(0,0,750,375,path);
startFrom.cpp中的功能实现:
//构造函数中的添加
ui->setupUi(this);
this->setFixedSize(750,375);
setWindowTitle("start from");
//打开第一关
connect(ui->pushButton,&QPushButton::clicked,[=]()
{
MainWindow * mainwindow=new MainWindow(parent);
mainwindow->setPath(":/images/background1.jpg");
mainwindow->loadTowerPosition1();
mainwindow->addWayPoint1();
mainwindow->show();
});
//打开第二关
connect(ui->pushButton_2,&QPushButton::clicked,[=]()
{
MainWindow * mainwindow=new MainWindow(parent);
mainwindow->setPath(":/images/background2.jpg");
mainwindow->loadTowerPosition2();
mainwindow->addWayPoint2();
mainwindow->show();
});
//打开第三关
connect(ui->pushButton_3,&QPushButton::clicked,[=]()
{
MainWindow * mainwindow=new MainWindow(parent);
mainwindow->setPath(":/images/background4.jpg");
mainwindow->loadTowerPosition3();
mainwindow->addWayPoint3();
mainwindow->show();
});
//打开第四关
connect(ui->pushButton_4,&QPushButton::clicked,[=]()
{
MainWindow * mainwindow=new MainWindow(parent);
mainwindow->setPath(":/images/background5.jpg");
mainwindow->loadTowerPosition4();
mainwindow->addWayPoint4();
mainwindow->show();
});
//其他函数
void startFrom::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QString path(":/images/background.jpg");
painter.drawPixmap(0,0,750,375,path);
}
注意上面代码的connect的使用方法!!!
ok,现在我们到main.cpp中,修改显示界面。
//把使用mainwindow的地方,替换成startFrom
#include "startfrom.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
startFrom w;
w.show();
return a.exec();
}
到这里,我们就实现了多地图的绘制了。一个较为成熟的塔防游戏就诞生了!下面我们再对一些细节进行完善吧!
再有防御塔的情况下,将防御塔坑进行隐藏
我们把TowerPosition.h中的bool hasTower()函数改为 bool hasTower()const
再进入paintEvent()函数中, 将防御塔的绘画改成:
foreach(const TowerPosition towerposition,m_towerPositionList)
{
if(!towerposition.hasTower())//没有防御塔,画出防御塔坑
{
towerposition.draw(&painter);
}
}
敌人从不同路口出现的绘制
把mainwindow.cpp中的loadWaves()函数改成:
bool MainWindow::loadWaves()
{
if(m_waves>=6)
{
return false;
}
int enemyStartInterval[]={100,500,600,1000,3000,6000};
for(int i=0;i<6;++i)
{
wayPoint * startWayPoint;
if(getPath()==":/images/background4.jpg")//该地图中,敌人有多种运动方法
{
int a=rand()%100;//随机数
if(a<50)
{
startWayPoint=m_wayPointList.first();
}
if(a>=50)
{
startWayPoint=m_wayPointList[7];
}
}
else
{
startWayPoint=m_wayPointList.first();
}
Enemy * enemy=new Enemy(startWayPoint,this);
m_enemyList.push_back(enemy);
//enemy->reSetHp(40+35*(0+m_waves));//波数增加,怪物的血量增加,一次加30点,这里可以进行重新设置敌人血量的操作
//还可以增加修改速度的函数
QTimer::singleShot(enemyStartInterval[i],enemy,SLOT(doActive()));
}
return true;
}
出了以上我说到了两种完善,制作者还有很大的发挥空间。比如升级后,防御塔的体型变大,攻击速度等;或者是敌人随着波数的增加,移动速度加快等等。总之还有很大的发挥空间,但是其基本方法和我上面的方法是一样的,都是一个reSet的过程。
这是我平生第一次写游戏,以前想都不敢想的事情,在自己的慢慢摸索下实现了,还挺有成就感的。虽然过程挺艰难的,在无数次debug中想要放弃,但还是尽力坚持下来了。这三篇文章也许还有很多不足的地方,若有谬误,也还请各位海涵,我也希望你们私信我,指出我不足的地方,慢慢提高吧!
编程真的是一件痛并快乐着的事情,希望各位代码小伙伴们在编程中都找到属于自己的快乐和幸福吧!
最后再附上源代码的链接:
https://pan.baidu.com/s/1BS7tiiyCWQxgZDsm8QhMgA
提取码:9307
完结撒花!
标签:Qt,button,pos,c++,mainwindow,bool,之塔防,QPoint,void 来源: https://blog.csdn.net/m0_47055280/article/details/106956412