最后一篇文章,主要是完善代码,增加其可玩性,主要有以下工作
- 实现地图的多样性
- 实现敌人的多样性
- 实现不同传奇子弹的多样性
- 实现不同地图传奇的多样性
- 创建文本界面来说明各个传奇功能
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中磨练自己,在查资料中丰厚自己,这也许就是学习程序的快乐叭!