目录
一.游戏大致内容
1.玩家角色
2.怪物
3.可触发的物品
4.不可触发的物品
5.地图
6.(玩家与怪物的技能)
二.实现逻辑
三.具体实现
1.角色类声明
2.怪物类声明
3.地图类声明
4.主界面声明
5.玩家角色的构造
6.怪物的构造
7.地图的构造
8.主界面构造
9.开始按钮的槽函数与绘图事件
10.键盘事件处理
11.初始化地图界面
12.刷新地图界面
13.角色移动处理
14.运算战斗结果
15.边栏角色信息
16.主函数
四.注意事项
1.头文件
2.图片与音乐文件
3.项目整体
五.游戏效果
1.开始界面(简陋)
2.第一层(新手大剑)
3.第二层(开始正常游戏)
4.后续层
5.奖励层
6.最后一层(暂时还没写结束结算)
最近系统学习了Qt的程序界面开发,所以用Qt尝试写了一个简单的魔塔小游戏。
下述括号内内容暂未编写
一.游戏大致内容
1.玩家角色
玩家角色拥有:角色名字,血量,攻击,防御,金钱,钥匙,剑,盾,(技能,经验,等级)
通过玩家角色保存层数
2.怪物
怪物拥有:怪物名字,血量,攻击,防御,金钱,(技能,经验,等级)
怪物名字不方便在代码中使用,所以给怪物添加一个“类型”变量
3.可触发的物品
可与玩家互动的物品
如:血瓶,(蓝瓶),钥匙,宝石,剑,盾,门等
4.不可触发的物品
地面,墙等
5.地图
初始地图与当前地图
6.(玩家与怪物的技能)
(技能拥有等级,加成,蓝耗等属性)
二.实现逻辑
除去暂时不想写的内容,将玩家角色写为一个类,怪物一个类,地图一个类,主界面一个类
玩家的活动可以写在玩家类中,也可以写在主界面类中——更方便刷新主界面;玩家应有移动,战斗等事件;主界面应有初始化,刷新界面,接收键盘按键事件等功能
使用Qt中的QLable控件装载地图的各种图标,用QPainter绘制游戏背景,用QMediaPlayer播放游戏背景音乐
地图用三维数组存储,每一张地图都是一个二维数组,则会将地图分割成网格状,通过多个QLable控件拼接成整张地图界面
三.具体实现
所有类的成员变量都写成了公有成员,方便在类外部通过该类对象使用这些变量
1.角色类声明
class Hero
{
public:Hero(QString);~Hero();int blood; //血量int attack; //攻击力int defense; //防御力int money; //金钱int floor; //楼层int b_key; //蓝钥匙int y_key; //黄钥匙bool sword; //持剑标志bool shield; //持盾标志QString name;
};
2.怪物类声明
class Monster
{
public:Monster(int);~Monster();QString name;int blood; //生命值int attack; //攻击力int defense; //防御力int money; //金钱int type; //类型 8-蓝史莱姆 9-黄史莱姆 10-蝙蝠 11-骷髅 12-法师
};
3.地图类声明
三维数组若声明未赋值则后续不方便赋值,需使用三重for循环赋值,不方便脑补绘制地图,所以在类中声明时就为其赋值
class Map
{
public:Map();//0-墙1-地板 2-蓝门 3-黄门 4-蓝钥匙 5-黄钥匙 6-小血瓶 7-大血瓶//8-蓝史雷姆 9-黄史雷姆 10-蝙蝠 11-骷髅 12-法师 13-红宝石 14-蓝宝石//15-英雄 16-上楼 17-下楼 18-剑 19-盾
/* //空地图,用于复制{0,0,0,0,0,0,0,0,0,0,0,0,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,0,0,0,0,0,0,0,0,0,0,0,0}
*/int map[TOWER_LAYER][ONCE_WIDTH][ONCE_HEIGHT]={{{0,0,0,0,0,0,0,0,0,0,0,0,0},{0,16,5,1,1,1,1,1,1,1,1,14,0},{0,5,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,18,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,6,1,1,1,1,1,1,1,1,1,15,0},{0,0,0,0,0,0,0,0,0,0,0,0,0}},{{0,0,0,0,0,0,0,0,0,0,0,0,0},{0,16,1,9,8,8,1,1,1,1,1,1,0},{0,0,0,0,0,0,0,0,0,0,0,1,0},{0,5,1,1,3,1,0,1,5,1,0,1,0},{0,1,11,1,0,1,0,14,6,1,0,1,0},{0,0,3,0,0,1,0,0,0,3,0,1,0},{0,5,1,1,0,1,3,10,11,10,0,1,0},{0,1,11,1,0,1,0,0,0,0,0,1,0},{0,0,3,0,0,1,1,1,1,1,1,1,0},{0,1,1,1,0,0,3,0,0,0,3,0,0},{0,6,1,5,0,1,1,1,0,1,10,1,0},{0,6,13,5,0,17,15,1,0,9,7,8,0},{0,0,0,0,0,0,0,0,0,0,0,0,0}},{{0,0,0,0,0,0,0,0,0,0,0,0,0},{0,5,14,0,5,7,5,0,1,0,1,6,0},{0,1,6,0,7,5,7,0,1,3,10,1,0},{0,12,1,0,5,4,5,0,1,0,0,0,0},{0,3,0,0,0,1,0,0,1,0,1,12,0},{0,1,1,10,1,1,1,9,1,1,1,1,0},{0,3,0,0,1,1,1,0,1,0,0,0,0},{0,11,1,0,0,1,0,0,1,0,1,6,0},{0,1,5,0,1,1,1,0,1,3,12,5,0},{0,6,6,0,1,1,1,0,1,0,0,0,0},{0,0,0,0,0,1,0,0,9,0,1,1,0},{0,17,15,1,1,1,1,0,1,3,1,16,0},{0,0,0,0,0,0,0,0,0,0,0,0,0}},{{0,0,0,0,0,0,0,0,0,0,0,0,0},{0,1,5,1,0,1,1,1,0,1,12,1,0},{0,6,13,4,0,1,12,1,0,5,1,7,0},{0,1,1,1,0,1,1,1,0,1,11,1,0},{0,0,3,0,0,0,2,0,0,0,3,0,0},{0,1,12,1,3,1,1,1,1,1,1,1,0},{0,1,1,1,0,0,0,0,0,0,0,0,0},{0,9,1,8,1,1,1,1,1,1,1,1,0},{0,3,0,0,3,0,0,0,3,0,0,3,0},{0,1,0,9,10,5,0,1,12,1,0,1,0},{0,1,0,5,1,5,0,9,6,9,0,15,0},{0,16,0,8,8,5,0,1,9,8,0,17,0},{0,0,0,0,0,0,0,0,0,0,0,0,0}},{{0,0,0,0,0,0,0,0,0,0,0,0,0},{0,17,1,2,1,1,1,1,1,1,1,1,0},{0,15,1,0,1,1,12,1,12,1,1,1,0},{0,1,0,0,0,0,0,1,0,0,0,0,0},{0,1,0,5,5,0,1,1,1,0,5,12,0},{0,1,0,5,5,3,1,1,1,3,1,5,0},{0,1,0,0,0,0,1,1,1,0,0,0,0},{0,1,0,12,11,0,1,1,1,0,5,7,0},{0,1,0,1,1,3,1,1,1,3,1,5,0},{0,1,0,0,0,0,1,1,1,0,0,0,0},{0,1,0,7,7,0,1,1,1,0,12,19,0},{0,16,0,7,14,3,1,1,1,3,12,12,0},{0,0,0,0,0,0,0,0,0,0,0,0,0}},{{0,0,0,0,0,0,0,0,0,0,0,0,0},{0,16,0,1,10,3,1,0,1,1,3,1,0},{0,1,0,1,1,0,5,0,11,12,0,2,0},{0,1,3,11,1,0,1,0,5,5,0,1,0},{0,0,0,0,3,0,10,0,5,5,0,1,0},{0,5,5,12,12,0,1,0,0,0,0,1,0},{0,5,1,1,11,0,1,12,1,1,1,1,0},{0,0,11,0,0,0,1,0,0,0,0,12,0},{0,1,12,1,1,0,10,0,1,1,1,1,0},{0,13,5,7,5,0,1,0,1,0,0,0,0},{0,0,0,0,0,0,5,0,1,0,7,14,0},{0,17,15,1,1,1,1,0,1,3,1,1,0},{0,0,0,0,0,0,0,0,0,0,0,0,0}},{{0,0,0,0,0,0,0,0,0,0,0,0,0},{0,17,15,7,7,7,7,7,7,7,7,7,0},{0,1,1,14,14,14,14,14,14,14,14,14,0},{0,1,1,13,13,13,13,13,13,13,13,13,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,16,0},{0,0,0,0,0,0,0,0,0,0,0,0,0}},{{0,0,0,0,0,0,0,0,0,0,0,0,0},{0,17,15,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,1,1,1,1,1,0},{0,1,1,1,1,1,1,12,12,12,12,12,0},{0,1,1,1,1,1,1,12,12,12,12,12,0},{0,1,1,1,1,1,1,12,12,12,12,12,0},{0,1,1,1,1,1,1,12,12,12,12,12,0},{0,1,1,1,1,1,1,12,12,12,12,12,0},{0,1,1,1,1,1,1,12,12,12,12,12,0},{0,0,0,0,0,0,0,0,0,0,0,0,0}}};
};
4.主界面声明
class Widget : public QWidget
{Q_OBJECT
public slots:void startGame(); //开始按钮所实现的自定义槽函数
public:Widget(QWidget *parent = 0);~Widget();void keyPressEvent(QKeyEvent *event); //键盘事件重写,上下左右与WASD键的改写void paintEvent(QPaintEvent *event); //绘图事件重写,素材背景为白板,需要绘制背景void initMap(); //初始化游戏地图函数void updateMap(int type,int preValue=0); //刷新游戏地图函数void heroMove(int type,int preValue); //角色移动判断函数void heroCombat(int preValue); //角色战斗判断函数void showHeroInfo(); //显示角色信息函数
private:QPushButton *start_bt; //开始按钮bool combate_signal; //角色战斗标志bool restart_signal; //死亡重开标志bool start_background_signal; //更新背景图标志QMediaPlayer *bgm; //播放背景音乐QMediaPlaylist *bgmlist; //背景音乐列表,用于循环播放QLabel *mapLabel[13][13]; //当前地图QLabel *infoLabel; //角色信息背景QLabel *nameLabel; //角色名字QLabel *moneyValueLabel; //金币QLabel *floorValueLabel; //楼层QLabel *bloodLabel; //生命值QLabel *attackLabel; //攻击力QLabel *defenseLabel; //防御力QLabel *bKeyLabel; //蓝钥匙QLabel *yKeyLabel; //黄钥匙Map *dynamic_map=new Map; //当前游戏的地图Map *static_map=new Map; //不会去更改的地图,其实也可以用Map::map来调用Hero *hero; //声明角色int heroX; //角色的模拟X坐标int heroY; //角色的模拟Y坐标//声明定义怪物Monster *blueSlime=new Monster(8);Monster *yellowSlime=new Monster(9);Monster *smallBat=new Monster(10);Monster *skeletonKnight=new Monster(11);Monster *exorcist=new Monster(12);
};
5.玩家角色的构造
Hero::Hero(QString name_):name(name_)
{//根据传入角色名生成指定角色if(name.compare("英雄")){blood=200;attack=20;defense=15;}else if(name.compare("勇者")){blood=100;attack=16;defense=10;}else if(name.compare("村民")){blood=60;attack=10;defense=8;}else {blood=40;attack=10;defense=5;}money=0;floor=0;b_key=0;y_key=0;
}
6.怪物的构造
Monster::Monster(int type){this->type=type;//根据传入类型生成指定小怪switch (type){case 8:blood=30;attack=12;defense=5;money=2;name="黄史莱姆";break;case 9:blood=50;attack=13;defense=5;money=3;name="蓝史莱姆";break;case 10:blood=50;attack=15;defense=8;money=5;name="蝙蝠";break;case 11:blood=100;attack=18;defense=12;money=20;name="骷髅";break;case 12:blood=200;attack=26;defense=10;money=30;name="法师";break;default:break;}
}
7.地图的构造
因为地图数组在声明时就赋值了,所以不需要重写地图的构造函数
8.主界面构造
Widget::Widget(QWidget *parent): QWidget(parent)
{this->grabKeyboard();//设置接收键盘事件this->setFixedSize((ONCE_WIDTH+1.5)*60,ONCE_HEIGHT*60);//背景音乐bgm=new QMediaPlayer();bgmlist=new QMediaPlaylist();//用QMediaPlaylist装入背景音乐,使其能循环播放bgmlist->addMedia(QUrl("qrc:/bgm/morning.mp3"));bgmlist->setPlaybackMode(QMediaPlaylist::Loop);bgm->setPlaylist(bgmlist);bgm->setVolume(30);//设置音量大小bgm->play();//开始按钮start_bt=new QPushButton("start game");start_bt->setFixedSize(140,50);start_bt->setFont(QFont("KaiTi",16));start_bt->setStyleSheet("QPushButton{ color:rgb(255,255,255);}""QPushButton{ selection-color:rgb(181,181,181);}""QPushButton{ border-radius:18px;}""QPushButton{ background-color:rgb(0,128,255);}");start_bt->move(this->width()/2-70,this->height()/2-25);start_bt->setParent(this);//初始化各个标志restart_signal=false;combate_signal=false;start_background_signal=false;//定义角色并初始化其内容hero=new Hero("英雄");heroX=0;heroY=0;hero->sword=false;hero->shield=false;//for循环初始化地图lablefor(int i=0;i<ONCE_WIDTH;i++){for(int j=0;j<ONCE_HEIGHT;j++){mapLabel[i][j]=new QLabel(this);mapLabel[i][j]->setFixedSize(60,60);}}connect(start_bt,SIGNAL(clicked(bool)),this,SLOT(startGame()));
}
9.开始按钮的槽函数与绘图事件
//开始按钮点击后隐藏按钮,跟新地图,立即刷新绘图事件,显示角色信息
void Widget::startGame(){start_background_signal=true;start_bt->hide();repaint();initMap();showHeroInfo();
}
//绘图事件,绘制窗口背景图
void Widget::paintEvent(QPaintEvent *event){QPainter p(this);event->accept();//进入游戏后背景改为全游戏地面背景if(start_background_signal==true){for(int i=0;i<ONCE_HEIGHT;i++){for(int j=0;j<ONCE_WIDTH+1;j++){p.drawPixmap(j*60,i*60,60,60,QPixmap(":/image/1.png"));}}}//未进入游戏设置开始背景else{p.drawPixmap(0,0,60*(ONCE_WIDTH+1.5),60*ONCE_HEIGHT,QPixmap(":/image/back.jpeg"));}
}
10.键盘事件处理
void Widget::keyPressEvent(QKeyEvent *event){if(!combate_signal){int type=4; //记录移动类型(0-上 1-下 2-左 3-右)int preValue=0; //记录走到的位置有什么东西switch (event->key()){case Qt::Key_Up:case Qt::Key_W:type=0;preValue=dynamic_map->map[hero->floor][heroX-1][heroY];heroMove(type,preValue);break;case Qt::Key_Down:case Qt::Key_S:type=1;preValue=dynamic_map->map[hero->floor][heroX+1][heroY];heroMove(type,preValue);break;case Qt::Key_Left:case Qt::Key_A:type=2;preValue=dynamic_map->map[hero->floor][heroX][heroY-1];heroMove(type,preValue);break;case Qt::Key_Right:case Qt::Key_D:type = 3;preValue=dynamic_map->map[hero->floor][heroX][heroY+1];heroMove(type,preValue);break;default:break;}showHeroInfo();//刷新角色信息的显示}
}
11.初始化地图界面
void Widget::initMap(){if(restart_signal){//将不变的地图赋予可变地图for(int k=0;k<TOWER_LAYER;k++){for(int i=0;i<ONCE_WIDTH;i++){for(int j=0;j<ONCE_HEIGHT;j++){dynamic_map->map[k][i][j]=static_map->map[k][i][j];}}}//判断角色死亡,是否重新开始。restart_signal=false;}//绘制当前地图for(int i=0;i<ONCE_HEIGHT;i++){for(int j=0;j<ONCE_WIDTH;j++){//每次更新一层,需要刷新当前层的图片mapLabel[i][j]->clear();mapLabel[i][j]->move(j*60,i*60);mapLabel[i][j]->setPixmap(QPixmap(tr(":/image/%1.png").arg(dynamic_map->map[hero->floor][i][j])));mapLabel[i][j]->setScaledContents(true);mapLabel[i][j]->show();//检索角色位置if(dynamic_map->map[hero->floor][i][j]==15){heroX=i;heroY=j;}}}//计分板背景infoLabel=new QLabel(this);infoLabel->setFixedSize(60*1.5,ONCE_HEIGHT*60);infoLabel->setPixmap(QPixmap(tr(":/image/20.jpeg")));infoLabel->setScaledContents(true);infoLabel->move(ONCE_WIDTH*60,0);infoLabel->show();//设置字体QPalette palette;palette.setColor(QPalette::WindowText,Qt::black);QFont font;font.setPointSize(12);font.setBold(true);//角色名字nameLabel=new QLabel(this);nameLabel->setFixedSize(60*1.5,50);nameLabel->move(ONCE_WIDTH*60,0);nameLabel->setPalette(palette);nameLabel->setFont(font);nameLabel->show();//金币显示moneyValueLabel=new QLabel(this);moneyValueLabel->setFixedSize(60*1.5,50);moneyValueLabel->move(ONCE_WIDTH*60,60*1.5);moneyValueLabel->setPalette(palette);moneyValueLabel->setFont(font);moneyValueLabel->show();//楼层显示floorValueLabel=new QLabel(this);floorValueLabel->setFixedSize(60*1.5,50);floorValueLabel->move(ONCE_WIDTH*60,60*3);floorValueLabel->setPalette(palette);floorValueLabel->setFont(font);floorValueLabel->show();//生命值bloodLabel=new QLabel(this);bloodLabel->setFixedSize(60*1.5,50);bloodLabel->move(ONCE_WIDTH*60,60*4.5);bloodLabel->setPalette(palette);bloodLabel->setFont(font);bloodLabel->show();//攻击力attackLabel=new QLabel(this);attackLabel->setFixedSize(60*1.5,50);attackLabel->move(ONCE_WIDTH*60,60*6);attackLabel->setPalette(palette);attackLabel->setFont(font);attackLabel->show();//防御力defenseLabel=new QLabel(this);defenseLabel->setFixedSize(60*1.5,50);defenseLabel->move(ONCE_WIDTH*60,60*7.5);defenseLabel->setPalette(palette);defenseLabel->setFont(font);defenseLabel->show();//黄钥匙yKeyLabel=new QLabel(this);yKeyLabel->setFixedSize(60*1.5,50);yKeyLabel->move(ONCE_WIDTH*60,60*9);yKeyLabel->setPalette(palette);yKeyLabel->setFont(font);yKeyLabel->show();//蓝钥匙bKeyLabel=new QLabel(this);bKeyLabel->setFixedSize(60*1.5,50);bKeyLabel->move(ONCE_WIDTH*60,60*10.5);bKeyLabel->setPalette(palette);bKeyLabel->setFont(font);bKeyLabel->show();
}
12.刷新地图界面
void Widget::updateMap(int type,int preValue){dynamic_map->map[hero->floor][heroX][heroY]=1;//先前角色所在地置为地面mapLabel[heroX][heroY]->setPixmap(QPixmap(tr(":/image/%1.png").arg(dynamic_map->map[hero->floor][heroX][heroY])));switch(type){case 0:heroX-=1;break;case 1:heroX+=1;break;case 2:heroY-=1;break;case 3:heroY+=1;break;default:break;}//角色移动后位置显示角色dynamic_map->map[hero->floor][heroX][heroY]=15;mapLabel[heroX][heroY]->setPixmap(QPixmap(tr(":/image/15.png")));//攻击怪物,实现图像闪烁if(preValue==8||preValue==9||preValue==10||preValue==11||preValue==12){//战斗中,记录战斗状态combate_signal=true;//定时器显示怪物图片QTimer *timer1=new QTimer(this);connect(timer1,&QTimer::timeout,this,[=](){mapLabel[heroX][heroY]->setPixmap(QPixmap(tr(":/image/%1.png").arg(preValue)));});//定时器显示角色图片QTimer *timer2=new QTimer(this);connect(timer2,&QTimer::timeout,this,[=](){mapLabel[heroX][heroY]->setPixmap(QPixmap(tr(":/image/15.png")));});timer1->start(100);QThread::msleep(50);//线程实现短暂休眠timer2->start(100);//500毫秒定时器,定时器结束,闪烁结束QTimer *timer=new QTimer(this);connect(timer,&QTimer::timeout,this,[=](){timer1->stop();timer2->stop();timer->stop();combate_signal=false;//如果角色战斗失败,则显示怪物图片if(hero->blood==0){mapLabel[heroX][heroY]->setPixmap(QPixmap(tr(":/image/%1.png").arg(preValue)));}//英雄胜利,则显示角色图片else{dynamic_map->map[hero->floor][heroX][heroY]=15;mapLabel[heroX][heroY]->setPixmap(QPixmap(tr(":/image/15.png")));}});timer->start(500);}
}
13.角色移动处理
void Widget::heroMove(int type,int preValue){if(hero->sword){hero->attack+=12;hero->sword=false;}if(hero->shield){hero->defense+=8;hero->shield=false;}if(preValue==0){//墙return;}else if(preValue==1){//空地updateMap(type);}else if(preValue==3&&hero->y_key>0){//黄门updateMap(type);hero->y_key--;}else if(preValue==5){//黄钥匙updateMap(type);hero->y_key++;}else if(preValue==2&&hero->b_key>0){//蓝门updateMap(type);hero->b_key--;}else if(preValue==4){//蓝钥匙updateMap(type);hero->b_key++;}else if(preValue==6){//小血瓶updateMap(type);hero->blood+=30;}else if(preValue==7){//大血瓶updateMap(type);hero->blood+=80;}else if(preValue==13){//红宝石updateMap(type);hero->attack+=3;}else if(preValue==14){//蓝宝石updateMap(type);hero->defense+=2;}else if(preValue==16){//上楼hero->floor+=1;initMap();}else if(preValue==17){//下楼hero->floor-=1;initMap();}else if(preValue==18){//剑updateMap(type);hero->sword=true;}else if(preValue==19){//盾updateMap(type);hero->shield=true;}else if(preValue==8||preValue==9||preValue==10||preValue==11||preValue==12){//怪物heroCombat(preValue);updateMap(type,preValue);showHeroInfo();// 碰见怪物,攻击结束之后判断血量if(hero->blood==0){int select=QMessageBox::information(this,tr("游戏结束"),tr("是否重新开始"),QMessageBox::Yes|QMessageBox::No);if(select==QMessageBox::Yes){//重新开始hero=new Hero("英雄");restart_signal=true;initMap();}else{this->close();}}}
}
14.运算战斗结果
void Widget::heroCombat(int preValue){int change_blood; //战斗后减少的血量int monster_blood; //当前怪物血量int hero_atk_def; //角色与怪物的攻防差int monster_atk_def; //怪物与角色的攻防余数switch (preValue){case 8:monster_blood=blueSlime->blood;hero_atk_def=hero->attack-blueSlime->defense;monster_atk_def=blueSlime->attack-hero->defense;hero->money+=blueSlime->money;break;case 9:monster_blood=yellowSlime->blood;hero_atk_def=hero->attack-yellowSlime->defense;monster_atk_def=yellowSlime->attack-hero->defense;hero->money+=yellowSlime->money;break;case 10:monster_blood=smallBat->blood;hero_atk_def=hero->attack-smallBat->defense;monster_atk_def=smallBat->attack-hero->defense;hero->money+=smallBat->money;break;case 11:monster_blood=skeletonKnight->blood;hero_atk_def=hero->attack-skeletonKnight->defense;monster_atk_def=skeletonKnight->attack-hero->defense;hero->money+=skeletonKnight->money;break;case 12:monster_blood=exorcist->blood;hero_atk_def=hero->attack-exorcist->defense;monster_atk_def=exorcist->attack-hero->defense;hero->money+=exorcist->money;break;default:break;}//角色防御高于怪物攻击if(monster_atk_def<=1){monster_atk_def=1;}//角色防御低于怪物攻击过多else if(monster_atk_def>10){monster_atk_def=10;}//角色攻击低于怪物防御if(hero_atk_def<0){change_blood=hero->blood;}else{//角色攻击高于怪物防御过多if(hero_atk_def>monster_blood){hero_atk_def=monster_blood;}change_blood=(monster_blood/hero_atk_def)*monster_atk_def;}//将要改变的血量高于原始血量if(change_blood>hero->blood){change_blood=hero->blood;}hero->blood-=change_blood;
}
15.边栏角色信息
void Widget::showHeroInfo(){QString text;//角色名字text.append("角色名字\n");text.append(hero->name);nameLabel->setText(text);nameLabel->setAlignment(Qt::AlignCenter);//居中显示text.clear();//用完清空,方便下次使用//金币text.append("金币\n");text.append(QString::number(hero->money));moneyValueLabel->setText(text);moneyValueLabel->setAlignment(Qt::AlignCenter);text.clear();//楼层text.append("楼层\n");text.append(QString::number(hero->floor));floorValueLabel->setText(text);floorValueLabel->setAlignment(Qt::AlignCenter);text.clear();//生命值text.append("生命值\n");text.append(QString::number(hero->blood));bloodLabel->setText(text);bloodLabel->setAlignment(Qt::AlignCenter);text.clear();//攻击力text.append("攻击力\n");text.append(QString::number(hero->attack));attackLabel->setText(text);attackLabel->setAlignment(Qt::AlignCenter);text.clear();//防御力text.append("防御力\n");text.append(QString::number(hero->defense));defenseLabel->setText(text);defenseLabel->setAlignment(Qt::AlignCenter);text.clear();//蓝钥匙text.append("蓝钥匙\n");text.append(QString::number(hero->b_key));bKeyLabel->setText(text);bKeyLabel->setAlignment(Qt::AlignCenter);text.clear();//黄钥匙text.append("黄钥匙\n");text.append(QString::number(hero->y_key));yKeyLabel->setText(text);yKeyLabel->setAlignment(Qt::AlignCenter);text.clear();
}
16.主函数
所有需要操作的都写在了主界面中,不需要更改Qt默认生成的主函数
四.注意事项
1.头文件
主界面所需的头文件
#include <QWidget>
#include <QMessageBox>
#include <QLabel>
#include <QKeyEvent>
#include <QTimer>
#include <QThread>
#include <QPushButton>
#include <QPainter>
#include <QPoint>
#include <QMediaPlayer>
#include <QMediaPlaylist>
#include <QString>#include "map.h"
#include "hero.h"
#include "monster.h"
玩家类和怪物类只需要QString的头文件
2.图片与音乐文件
素材图片最好是.png格式的,背景图片任何类型都可以
背音乐文件一般为.wav格式,若想要使用其他格式则需要安装插件
当音乐文件放在项目.qrc文件下时,写音乐路径时必须在分号前写上"qrc"
如:QUrl("qrc:/bgm/morning.mp3");
当文件未放入项目中时,该路径必须是绝对路径