QT FC坦克大战(附源码)

时间:2024-03-01 08:30:12

QT FC坦克大战

QT设计的类似FC坦克大战的程序。暂时只完成了单人模式,双人模式可以后续自行添加。

源码以及图片音频资源下载地址:上传暂时还在审核中...后续更新

目录

QT FC坦克大战

程序描述

程序基本思路

程序的基本框架

主要思路

部分算法

我方坦克移动控制

敌方坦克移动,子弹发射

子弹移动

子弹发射

我方子弹与敌方坦克的碰撞检测

 敌方坦克与敌方坦克的碰撞检测

 界面设计

程序窗口基本框架

菜单界面

实际运行效果


程序描述

关卡为26*26的方格,背景为黑色。

关卡内,场景对象包括环境:砖块,铁块,草,水,大本营;角色:我方坦克,敌方坦克;

移动:我方坦克,可以通过WASD四个按键,实现方向控制,敌方坦克,会随机移动。坦克遇到砖块,铁块与水,会无法继续前行,遇到草会隐藏在草丛下方。敌方坦克的行为规则:如果能继续前进,则坦克以0.7的概率前进,0.3的概率向其他三个方向转向。如果被挡住,四个方向各以0.25的概率转向。任何时刻,坦克都以0.3的概率向当前方向发射子弹。

发射子弹:我方坦克通过按鼠标左键,发射子弹,敌方坦克,随机发射子弹。子弹以恒定速度前行。

子弹击中砖块,会令砖块消失,同时子弹消失。击中铁块,子弹消失,铁块不变。击中水与草,会穿过。子弹碰到四周边界会消失。子弹击中对方坦克,会令对方坦克消失,并显示0.5秒钟爆炸特效。

子弹击中大本营,会判定失败。

关卡开始后,会随机在最顶行刷新20只坦克,刷新时,会显示0.5秒钟出生特效,我方坦克出生时会显示无敌特效。

敌方坦克有三种,分别为被子弹击中一次,两次,三次击杀。我方坦克被击中三次后死亡。敌方坦克彼此击中不会死亡。

当对方二十辆坦克都被击杀后,我方胜利。当我方被击杀三次,或者大本营被摧毁后,敌方胜利。

实现多关卡,主要为原任天堂游戏地图。

添加部分音效,为原游戏音效。

实现动态显示剩余坦克数、关卡数、我方坦克生命值,与原任天堂游戏相似。

实现游戏结束画面,与原任天堂游戏相似。

程序运行效果如下(GIF):

程序基本思路

程序的基本框架

对程序进行板块划分,划分为地图、坦克类、我方坦克类(继承坦克类、调用子弹类)、敌方坦克类(继承坦克类、调用子弹类)、子弹类以及两个窗口(菜单窗口和游戏窗口)。

地图:使用26*26的二维int数组(地图块种类:nothing 0, wall 1, steel 2, sand 3, water 4, grass 5, boss 6,boss boom 7)。地图由13*13个30*30像素的大地图块组成,每个大地图块由四个15*15像素的小地图块组成。

计时器(timer)每100ms刷新一次。

坦克类

坦克为30*30像素的图片;

成员变量:横纵坐标(x,y)、坦克方向(dir)、坦克速度(speed)、生命值(hp)、坦克等级(level)、坦克是否存活(isAlive)、坦克是否隐藏(mask)、地图数组(map);

坦克是否隐藏(mask)用于判断坦克碰撞到草地(grass)后,是否隐藏;

生命值(hp)用于判断坦克剩余受击次数,位0时,坦克爆炸;

坦克等级主要用于判断敌方坦克的类型,被子弹击中一次,两次,三次后击杀爆炸。

子弹类:

成员变量:横纵坐标(x,y)、子弹数量(count)、子弹方向(dir)、子弹速度(speed)、子弹碰撞类型(collision)、子弹是否存活(isAlive);

子弹碰撞类型用于表示子弹击中的目标类型(地图块、子弹、坦克、边界、营地五种情况),方便判断被击中目标的下一步绘制方法。

我方坦克类(继承坦克类、调用子弹类):

子弹类类对象(bullet),自定义子弹类vector容器(bullet_vector);

成员函数:void fire() 我方坦克的发射子弹函数;

成员变量:计时器(timer)、判断上下左右(up、down、left、right);

槽函数:void move()  我方坦克移动的槽函数。

敌方坦克类(继承坦克类、调用子弹类):

成员函数:void run() 敌方坦克的移动函数;

子弹类类对象(en_bullet),自定义子弹类vector容器(en_bullet_vector)。

菜单界面:

槽函数:void on_pushButton_clicked();

        void on_L_Reco_clicked();

        void on_EXIT_clicked();

分别对应开始游戏、帮助和退出游戏。

我方坦克(JPG)

敌方坦克(JPG)

level1  level2 level3

地图块(JPG)

grass  wall  ice  iron  river

子弹(JPG)

子弹爆炸(JPG)

坦克爆炸(JPG)

游戏音频(WAV)

主要思路

游戏开始时播放对应音频(.wav);

首先根据地图数组进行绘制地图,然后通过我方坦克类中的定时器(timer)进行我方子弹和敌方子弹、我方子弹和敌方坦克、敌方坦克和敌方坦克、敌方子弹和我方子弹、敌方子弹和敌方子弹的碰撞检测,制造敌方坦克,营地击中检测、地图更新;

通过对我方坦克的移动控制(即W、S、A、D、鼠标左键的点击),实现我方坦克的移动和发射子弹。当碰撞到草地(grass)时,停止绘制我方坦克,但横纵坐标依然更新,直到坦克完全移出草地(grass)。当我方坦克被击中三次后,爆炸,游戏结束;

子弹射出时,压入到对应的vector中,包括子弹的速度、方向、横纵坐标等信息。子弹射出后,根据一定规则运动。当子弹发生碰撞时,通过判断碰撞的对象,从而改变子弹碰撞类型(collision)的值,根据不同的碰撞类型值在更新绘制时实现对子弹、坦克和地图块的更新,同时该子弹从vector中清除。如果子弹所属的坦克没有存活,该子弹从vector中清除;

首先创建3个敌方坦克到地图中,同时压入到自定义敌方坦克类vector容器中,且开始移动。当vector中的坦克数小于5时,在三个固定出生点随机创造一个敌方坦克,同时创建子弹压入对应vector中,以此循环,直至地图中坦克数等于5。敌方坦克的等级随机刷新。敌方坦克根据一定的规则移动和发射子弹。当碰撞到草地(grass)时,停止绘制敌方坦克,但横纵坐标依然更新,直到坦克完全移出草地(grass)。

绘制时根据地图数组依次绘制地图块,根据自定义敌方坦克类vector容器依次绘制敌方坦克,根据自定义子弹类依次绘制子弹,根据我方坦克横纵坐标绘制我方坦克;

游戏结束时绘制游戏结束画面并播放对应的音频(.wav)。

部分算法

我方坦克移动控制

通过四个bool型数据,分别代表上下左右(up、down、left、right)。如果某一数据为true,则表示向该方向移动。通过对键盘事件的响应,即mouseEvent的重写,来改变这四个bool类型的值。

每当计时器(timer)运行一次,就对这四个数据进行判断。当只有某一个数据为true时,我方坦克就根据在该方向上的移动规则移动。

向上的移动规则:

首先判断是否出现上移越界的情况,即纵坐标大于5。如果有,则坦克不移动;如果没有,则继续判断坦克与地图块的碰撞。

坦克与地图块的碰撞分为以下情况:地图为空、地图为草地、地图为沙地等。

地图为空:正常前进;

地图为草地:坦克隐藏,继续前进;

地图为沙地:加速前进;

其余情况:不前进;

对于具体的碰撞检测,原理是将坦克的横纵坐标转换为地图数组中的元素,再判断该元素的各个方向的地图块种类。有以四下种情况(以图示说明):

其他方向的规则类比向上的规则;

当检测到为草地时,是否隐藏(mask)为true,否则为false;

敌方坦克移动,子弹发射

首先判断坦克是否存活(isAlive);

再通过swithc判断坦克的方向(dir):

Case 0:

If(坦克没有上移越界)

根据算法1中坦克与地图块的碰撞检测原理,判断坦克是否移动;

If 移动

随机生成一个大于0小于10的数,根据书的大小,坦克有0.3的概率转向,0.7的概率直行;

Else

随机转向;

Case 1:原理同case 0;

Case 2:原理同case 0;

Case 3:原理同case 0;

子弹移动

子弹为6*6像素大小的图片;

判断子弹存活时:

Switch(子弹方向(dir))

Case 0:

根据算法1中坦克与地图块的碰撞检测原理,判断子弹是否移动;

碰撞类型有:

空白、草地、沙地、河流:正常移动;

铁块、砖块:停止移动,并返回对应的碰撞类型值(collision),同时子弹移除;

Case 1:原理同case 0;

Case 2:原理同case 0;

Case 3:原理同case 0;

 

如果边界越界,返回对应的碰撞类型值(collision),同时子弹移除;

子弹发射

坦克向各个方向发射子弹示意图(以向上为例):

子弹发射时,子弹的方向立即确定,且不被改变,即为发射时坦克的方向;

我方子弹与敌方坦克的碰撞检测

槽函数,当计时器更新时调用;

If(我方坦克存活){

For循环,遍历每一个我方坦克子弹(最多为2个)

对每一个我方坦克发射的子弹:

For循环,遍历每一个敌方坦克

If(敌方坦克存活)

根据一定的规则,判断我方子弹是否击中敌方坦克,规则如下图

}

子弹击中目标后,目标和子弹移除;

 敌方坦克与敌方坦克的碰撞检测

碰撞原理如图:

敌方坦克1向上与敌方坦克2向下碰撞后:坦克1、2均反向;

敌方坦克1向上与敌方坦克2向左或右碰撞后:坦克1在上则坦克2反向,反之,坦克1反向;

敌方坦克1向下与敌方坦克2向左或右碰撞后:坦克1在上则坦克1反向,反之,坦克2反向;

 界面设计

程序窗口基本框架

菜单界面

去掉标题栏,设置三个按钮,分别对应开始游戏、帮助、退出游戏,通过QPalette设置背景图片。

游戏界面:

去掉标题栏;

将游戏界面分为两部分,一个为游戏主体,一个为游戏信息实时显示;

游戏主题设置背景图(纯黑色);

游戏信息实时显示部分以灰色为背景图,主要分为敌方坦克数量、关卡数、我方坦克生命值的显示。敌方坦克数以2*10的排列方式显示,每减少一个敌方坦克,对应减少一个敌方坦克标志。关卡数以“旗帜”图案和数字的方式显示,每前进一关,数字加一。我方坦克数量以我方坦克标志和数字的方式显示,该数字随坦克生命值(hp)的变化为变化。

      

实际运行效果

 

营地被击中:

 

通过草地: