C++ EGE 实现坦克大战小游戏

因为有过一次用EGE写小游戏的经验,所以这一次写坦克大战快了很多。并且使用对象编程也简化了很多编程时繁琐的步骤。
写出坦克大战使我在学习编程的道路上又迈出了一大步。

如果您需要图片素材的,我可以单独发给您。

技术环节:
编译环境:Windows VS2019

需求:
控制坦克移动发射炮弹,炮弹可以消灭敌军坦克,且可以消灭砖块。坦克遇到方块会被挡住。敌军消灭我军三次或基地被毁则游戏失败,共摧毁十次敌方坦克游戏胜利。

思路:
先写出坦克的父类,我方坦克类和敌方坦克类继承坦克父类,实例化我方坦克和敌方坦克。地图使用list容器存储。

在代码注释中标注了每一步是怎么实现的。

注意:
因为我在程序中用了一些不规范的写法,所以要在VS中正常编译运行,需要右键源文件->属性->C/C+±>符合模式,改为否。

包含<graphics.h>图形库需要提前配置EGE图形库。
如要在其他graphics图形库下编译,可能需要修改某些地方。

运行效果:


#include <graphics.h>  //图形库
#include <ctime>      //time();
#include <list>           //list容器using namespace std;    //标准命名空间 list等//设置图片对象中图片的宽高  全局函数
//参数:宽、高、对象名
void setimage(int pwidth, int pheight, PIMAGE img_1);//地图全局结构
struct mapstr
{int m_x;   //xy坐标int m_y;int prop; //属性
};//地图类
class Mymap
{private:list<mapstr> listmap;     //地图容器,存储全地图信息,全地图1350个20*20的格子public://设置地图Mymap(){mapstr temp;//构造函数为链表容器中的地图赋值//全地图横向45个格子 竖向30个格子//基地部分{temp.prop = 0;for (int i = 0; i < 4; i++) { temp.m_x = 380 + i * 20; temp.m_y = 540; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 380 + i * 20; temp.m_y = 520; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 380; temp.m_y = 560 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 360; temp.m_y = 520 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 440; temp.m_y = 560 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 460; temp.m_y = 520 + i * 20; listmap.push_back(temp); }temp.prop = 4, temp.m_x = 400, temp.m_y = 560;  listmap.push_back(temp);}//左上角部分{temp.prop = 0;//左上角单独砖块for (int i = 0; i < 2; i++) { temp.m_x = 40 + i * 20; temp.m_y = 80; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 40 + i * 20; temp.m_y = 100; listmap.push_back(temp); }//竖铁块for (int i = 0; i < 4; i++) { temp.m_x = 160; temp.m_y = i * 20; temp.prop = 1; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 180; temp.m_y = i * 20; listmap.push_back(temp); }//砖块for (int i = 0; i < 4; i++) { temp.m_x = 160; temp.m_y = 160 + i * 20; temp.prop = 0; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 180; temp.m_y = 160 + i * 20; listmap.push_back(temp); }//草块for (int i = 0; i < 4; i++) { temp.m_x = 0; temp.m_y = 200 + i * 20; temp.prop = 2; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 20; temp.m_y = 200 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 40 + i * 20; temp.m_y = 240; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 40 + i * 20; temp.m_y = 260; listmap.push_back(temp); }}//中上部分{//铁块for (int i = 0; i < 2; i++) { temp.m_x = 320; temp.m_y = i * 20; temp.prop = 1; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 340; temp.m_y = i * 20; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 280 + i * 20; temp.m_y = 160; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 280 + i * 20; temp.m_y = 180; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 400 + i * 20; temp.m_y = 200; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 400 + i * 20; temp.m_y = 220; listmap.push_back(temp); }//砖块for (int i = 0; i < 4; i++) { temp.m_x = 320; temp.m_y = 40 + i * 20; temp.prop = 0; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 340; temp.m_y = 40 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 240; temp.m_y = 200 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 260; temp.m_y = 200 + i * 20; listmap.push_back(temp); }}//右上部分{//砖块for (int i = 0; i < 4; i++) { temp.m_x = 480; temp.m_y = 40 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 500; temp.m_y = 40 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 480; temp.m_y = 160 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 500; temp.m_y = 160 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 600; temp.m_y = 40 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 620; temp.m_y = 40 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 600; temp.m_y = 160 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 620; temp.m_y = 160 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 6; i++) { temp.m_x = 680 + i * 20; temp.m_y = 200; listmap.push_back(temp); }for (int i = 0; i < 6; i++) { temp.m_x = 680 + i * 20; temp.m_y = 220; listmap.push_back(temp); }for (int i = 0; i < 6; i++) { temp.m_x = 760; temp.m_y = 0 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 6; i++) { temp.m_x = 780; temp.m_y = 0 + i * 20; listmap.push_back(temp); }//草块for (int i = 0; i < 6; i++) { temp.m_x = 560; temp.m_y = 160 + i * 20; temp.prop = 2; listmap.push_back(temp); }for (int i = 0; i < 6; i++) { temp.m_x = 580; temp.m_y = 160 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 520; temp.m_y = 160 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 540; temp.m_y = 160 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 860; temp.m_y = 80 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 880; temp.m_y = 80 + i * 20; listmap.push_back(temp); }//铁块for (int i = 0; i < 4; i++) { temp.m_x = 520 + i * 20; temp.m_y = 80; temp.prop = 1; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 520 + i * 20; temp.m_y = 100; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 640 + i * 20; temp.m_y = 160; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 640 + i * 20; temp.m_y = 180; listmap.push_back(temp); }for (int i = 0; i < 6; i++) { temp.m_x = 800 + i * 20; temp.m_y = 200; listmap.push_back(temp); }for (int i = 0; i < 6; i++) { temp.m_x = 800 + i * 20; temp.m_y = 220; listmap.push_back(temp); }}//左下部分{//铁块for (int i = 0; i < 2; i++) { temp.m_x = i * 20; temp.m_y = 360; temp.prop = 1; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = i * 20; temp.m_y = 380; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 160; temp.m_y = 320 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 180; temp.m_y = 320 + i * 20; listmap.push_back(temp); }//砖块for (int i = 0; i < 12; i++) { temp.m_x = 40; temp.m_y = 360 + i * 20; temp.prop = 0; listmap.push_back(temp); }for (int i = 0; i < 12; i++) { temp.m_x = 60; temp.m_y = 360 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 8; i++) { temp.m_x = 40 + i * 20; temp.m_y = 280; listmap.push_back(temp); }for (int i = 0; i < 8; i++) { temp.m_x = 40 + i * 20; temp.m_y = 300; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 160; temp.m_y = 400 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 180; temp.m_y = 400 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 160; temp.m_y = 560 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 180; temp.m_y = 560 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 240 + i * 20; temp.m_y = 240; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 240 + i * 20; temp.m_y = 260; listmap.push_back(temp); }for (int i = 0; i < 8; i++) { temp.m_x = 280; temp.m_y = 320 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 8; i++) { temp.m_x = 300; temp.m_y = 320 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 8; i++) { temp.m_x = 320; temp.m_y = 320 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 8; i++) { temp.m_x = 340; temp.m_y = 320 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 360; temp.m_y = 400 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 380; temp.m_y = 400 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 400; temp.m_y = 400 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 420; temp.m_y = 400 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 8; i++) { temp.m_x = 440; temp.m_y = 320 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 8; i++) { temp.m_x = 460; temp.m_y = 320 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 8; i++) { temp.m_x = 480; temp.m_y = 320 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 8; i++) { temp.m_x = 500; temp.m_y = 320 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 8; i++) { temp.m_x = 520; temp.m_y = 320 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 8; i++) { temp.m_x = 540; temp.m_y = 320 + i * 20; listmap.push_back(temp); }//草块for (int i = 0; i < 10; i++) { temp.m_x = 200 + i * 20; temp.m_y = 280; temp.prop = 2; listmap.push_back(temp); }for (int i = 0; i < 10; i++) { temp.m_x = 200 + i * 20; temp.m_y = 300; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 200 + i * 20; temp.m_y = 320; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 200 + i * 20; temp.m_y = 340; listmap.push_back(temp); }}//右下部分{//砖块for (int i = 0; i < 8; i++) { temp.m_x = 600; temp.m_y = 320 + i * 20; temp.prop = 0; listmap.push_back(temp); }for (int i = 0; i < 8; i++) { temp.m_x = 620; temp.m_y = 320 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 560; temp.m_y = 520 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 580; temp.m_y = 520 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 8; i++) { temp.m_x = 600 + i * 20; temp.m_y = 560; listmap.push_back(temp); }for (int i = 0; i < 8; i++) { temp.m_x = 600 + i * 20; temp.m_y = 580; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 680 + i * 20; temp.m_y = 520; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 680 + i * 20; temp.m_y = 540; listmap.push_back(temp); }for (int i = 0; i < 7; i++) { temp.m_x = 760 + i * 20; temp.m_y = 320; listmap.push_back(temp); }for (int i = 0; i < 7; i++) { temp.m_x = 760 + i * 20; temp.m_y = 340; listmap.push_back(temp); }for (int i = 0; i < 8; i++) { temp.m_x = 800; temp.m_y = 320 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 8; i++) { temp.m_x = 820; temp.m_y = 320 + i * 20; listmap.push_back(temp); }//铁块for (int i = 0; i < 4; i++) { temp.m_x = 640; temp.m_y = 320 + i * 20; temp.prop = 1; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 660; temp.m_y = 320 + i * 20; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 680; temp.m_y = 320 + i * 20; temp.prop = 1; listmap.push_back(temp); }for (int i = 0; i < 2; i++) { temp.m_x = 700; temp.m_y = 320 + i * 20; temp.prop = 1; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 820 + i * 20; temp.m_y = 480; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 820 + i * 20; temp.m_y = 500; listmap.push_back(temp); }//草块for (int i = 0; i < 4; i++) { temp.m_x = 560; temp.m_y = 360 + i * 20; temp.prop = 2; listmap.push_back(temp); }for (int i = 0; i < 4; i++) { temp.m_x = 580; temp.m_y = 360 + i * 20; listmap.push_back(temp); }}}//显示地图void printmap(list<mapstr>& listmap){PIMAGE mapprop_0 = newimage();getimage(mapprop_0, "坦克大战完整素材\\砖块.png");setimage(20, 20, mapprop_0);PIMAGE mapprop_1 = newimage();getimage(mapprop_1, "坦克大战完整素材\\铁块.png");setimage(20, 20, mapprop_1);PIMAGE mapprop_2 = newimage();getimage(mapprop_2, "坦克大战完整素材\\草块.png");setimage(20, 20, mapprop_2);PIMAGE mapprop_4 = newimage();getimage(mapprop_4, "坦克大战完整素材\\老鹰_1.png");setimage(40, 40, mapprop_4);PIMAGE mapprop_5 = newimage();getimage(mapprop_5, "坦克大战完整素材\\老鹰_2.png");setimage(40, 40, mapprop_5);for (list<mapstr>::iterator it = listmap.begin(); it != listmap.end(); it++){switch (it->prop){case 0:putimage(it->m_x, it->m_y, mapprop_0);break;case 1:putimage(it->m_x, it->m_y, mapprop_1);break;case 2:putimage(it->m_x, it->m_y, mapprop_2);break;case 4:putimage(it->m_x, it->m_y, mapprop_4);break;case 5:putimage(it->m_x, it->m_y, mapprop_5);break;}}delimage(mapprop_0);delimage(mapprop_1);delimage(mapprop_2);delimage(mapprop_4);delimage(mapprop_5);}//获取地图容器list<mapstr> getmapves(){return listmap;}
};//坦克父类
class Tank
{public:virtual void move(const list<mapstr>& tempves) = 0;   //坦克移动函数int getlauch_x()    //获取子弹x坐标{return b_m_x;}int getlauch_y()    //获取子弹y坐标{return b_m_y;}void setlauch_xy()  //设置子弹坐标{b_m_x = m_x + 18;    //重置位置为坦克中间b_m_y = m_y + 18;key1 = key2;     //key1 = key2避免炮弹一直发射}int getTank_x()      //获取坦克x坐标{return m_x;}int getTank_y()       //获取坦克y坐标{return m_y;}char getkey2()        //返回发射时的坦克方向信息{return key2;}//坦克攻击子弹位置爆炸void exploed(){PIMAGE explimg_1 = newimage();getimage(explimg_1, "坦克大战完整素材\\爆炸效果1.png");setimage(10, 10, explimg_1);PIMAGE explimg_2 = newimage();getimage(explimg_2, "坦克大战完整素材\\爆炸效果2.png");setimage(20, 20, explimg_2);PIMAGE explimg_3 = newimage();getimage(explimg_3, "坦克大战完整素材\\爆炸效果3.png");setimage(40, 40, explimg_3);PIMAGE explimgarr[3] = { explimg_1, explimg_2, explimg_3 };for (int i = 0; i < 3; i++){if (key2 == 'd' || key2 == 'a')//根据坦克的攻击朝向确定爆炸的位置putimage(b_m_x, b_m_y - 6 * i, explimgarr[i]);elseputimage(b_m_x - 6 * i, b_m_y, explimgarr[i]);delay_fps(42);}delimage(explimg_1);delimage(explimg_2);delimage(explimg_3);}//构造函数Tank()  {m_x = 0; m_y = 0;m_health = 0; m_damage = 0;path_1 = NULL; path_2 = NULL;path_3 = NULL; path_4 = NULL;b_m_x = 0; b_m_y = 0;key1 = '0'; key2 = '0';}protected://从文件中获取坦克图片void gettank(const char *path)    {PIMAGE tankimg = newimage();  //创建图片对象getimage(tankimg, path);        //在文件中获取图片到图片对象setimage(40, 40, tankimg);       //设置图片对象大小putimage(this->m_x, this->m_y, tankimg);//在坐标处输出图片delimage(tankimg);                //释放图片对象}//输出显示坦克void printtank(const char key2){//根据当前的键值,输出坦克switch (key2){case 'w':gettank(path_1); break;      //输出坦克case 's':gettank(path_2); break;case 'a':gettank(path_3); break;case 'd':gettank(path_4); break;}}//发射子弹void launch(){printtank(key2);setfillcolor(WHITE);switch (key2){case 'w':b_m_y -= 10;bar(b_m_x, b_m_y, b_m_x + 4, b_m_y + 8);break;case 'a':b_m_x -= 10;bar(b_m_x, b_m_y, b_m_x + 8, b_m_y + 4);break;case 's':b_m_y += 10;bar(b_m_x, b_m_y, b_m_x + 4, b_m_y + 8);break;case 'd':b_m_x += 10;bar(b_m_x, b_m_y, b_m_x + 8, b_m_y + 4);break;}//子弹越界目标则子弹坐标刷新if (b_m_x >= 900 || b_m_x <= 0 || b_m_y >= 600 || b_m_y <= 0)setlauch_xy();       //重置子弹位置}int m_x;       //坦克xy坐标int m_y;int m_health;   //坦克血量int m_damage; //子弹伤害量char* path_1;    //四张不同方向的坦克图片,由派生类决定图片路径char* path_2;char* path_3;char* path_4;int b_m_x;        //子弹坐标xyint b_m_y;char key1;        //用于接收键盘信息char key2;        //用于存储上一条键值,也是发射时的坦克的朝向};//游戏失败结束全局函数  在生命为0 和 基地被攻击时调用
void gameoverfalse()
{cleardevice();PIMAGE gameoverbackimg = newimage();    getimage(gameoverbackimg, "坦克大战完整素材\\游戏结束背景.jpg");setimage(900,600,gameoverbackimg);putimage(0, 0, gameoverbackimg);  //输出背景图片PIMAGE gameoverimg = newimage();getimage(gameoverimg, "坦克大战完整素材\\游戏结束.png");setimage(200, 200, gameoverimg);putimage_withalpha(NULL, gameoverimg, 350, 200); //透明格式输出游戏结束图片delimage(gameoverbackimg);delimage(gameoverimg);              //释放内存getch();getch();
}//我方坦克,可被操控移动
class TankFriend :public Tank
{private:int Fridienum = 0;
public://构造函数初始化坦克坐标TankFriend(){m_x = 300;        //我方坦克的初始坐标为屏幕中下方m_y = 560;m_health = 100;    //坦克血量m_damage = 90;   //坦克伤害b_m_x = m_x + 18;b_m_x = m_x + 18;path_1 = "坦克大战完整素材\\己方坦克上.png";  //赋值需要将源文件属性语言中符合模式改为否path_2 = "坦克大战完整素材\\己方坦克下.png";path_3 = "坦克大战完整素材\\己方坦克左.png";path_4 = "坦克大战完整素材\\己方坦克右.png";key1 = 'w';      //初始化key1用于输出初始的坦克}int getTankdamage()      //获取坦克伤害{return m_damage;}int getTankhealth()       //获取坦克血量{return m_health;}void setTankhealth(const int health)  //设置坦克血量{m_health = health;}int getFridienumfun()  //获取我方坦克被消灭次数{return Fridienum;}//坦克被操控移动virtual void move(const list<mapstr>& tempves){if (key1 != 'j')key2 = key1;    //key2记录上一个key1的值if (kbhit()){//用临时变量接收键值,如果键值为wasdj中的一个则赋给使用的变量char tempkey = getch();switch (tempkey){case 'w': case 'a':case 's': case 'd':case 'j':key1 = tempkey;break;//接收的键盘值不是wasdj直接returndefault:return;}//判断坦克撞墙情况,坦克撞墙可以改变方向,但不会移动坐标for (list<mapstr>::const_iterator it = tempves.begin(); it != tempves.end(); it++){switch (tempkey){//这里的大于小于号一个都不能错case 'w':if ((//判断坦克原xy点(m_x >= it->m_x && m_x < it->m_x + 20) && (m_y - 20 == it->m_y) ||//判断坦克右xy点(m_x + 40 > it->m_x&& m_x + 40 <= it->m_x + 20) && (m_y - 20 == it->m_y))//判断方块属性&& (it->prop == 0 || it->prop == 1)//判断地图边界范围|| (m_y - 20 < 0))return;break;case 'a':if ((//判断坦克原xy点(m_y >= it->m_y && m_y < it->m_y + 20) && (m_x - 20 == it->m_x) ||//判断坦克右xy点(m_y + 40 > it->m_y && m_y + 40 <= it->m_y + 20) && (m_x - 20 == it->m_x))//方块属性&& (it->prop == 0 || it->prop == 1)//判断地图边界范围|| (m_x - 20 < 0))return;break;case 's':if ((//判断坦克原xy点(m_x >= it->m_x && m_x < it->m_x + 20) && (m_y + 40 == it->m_y) ||//判断坦克右xy点(m_x + 40 > it->m_x&& m_x + 40 <= it->m_x + 20) && (m_y + 40 == it->m_y))//判断方块属性&& (it->prop == 0 || it->prop == 1)//判断地图边界范围|| (m_y + 60 > 600))return;break;case 'd':if ((//判断坦克原xy点(m_y >= it->m_y && m_y < it->m_y + 20) && (m_x + 40 == it->m_x) ||//判断坦克右xy点(m_y + 40 > it->m_y&& m_y + 40 <= it->m_y + 20) && (m_x + 40 == it->m_x))//方块属性&& (it->prop == 0 || it->prop == 1)//判断地图边界范围|| (m_x + 60 > 900))return;break;}}//根据key1值修改坦克坐标switch (key1){case 'w':m_y -= 20; break;case 'a':m_x -= 20; break;case 's':m_y += 20; break;case 'd':m_x += 20; break;}}//如果键值为j则发射炮弹,如果键值为wasd则移动坦克if (key1 == 'j')launch();else{printtank(key1);        //根据键值输出显示坦克b_m_x = m_x + 18;     //移动时也重置子弹坐标b_m_y = m_y + 18;     //这里key1值不能重置为key2值}//如果我军坦克被消灭,则被消灭次数+1,并重置坦克if (m_health <= 0)     {Fridienum++;m_x = 300;  //坐标m_y = 560;m_health = 100; //血量}}
};//统计所有敌军坦克次数全局变量
int Endienum;//敌军坦克
class TankEnemy :public Tank
{private:int pathsch;    //路线方案int contdir;bool Entankdie = true;   //标记敌军坦克的死亡状态public://构造函数接收初始坦克坐标TankEnemy(const int x ,const int y, const int pathsch)            //构造函数初始化坦克坐标{m_x = x;         //敌方坦克初始坐标m_y = y;b_m_x = m_x + 18;  //坦克子弹坐标b_m_x = m_x + 18;m_health = 300;     //坦克血量m_damage = 90;       //坦克伤害contdir = 0;this->pathsch = pathsch; //路线path_1 = "坦克大战完整素材\\敌方坦克上.png";  //赋值需要将源文件属性语言中符合模式改为否path_2 = "坦克大战完整素材\\敌方坦克下.png";path_3 = "坦克大战完整素材\\敌方坦克左.png";path_4 = "坦克大战完整素材\\敌方坦克右.png";gettank(path_1);//输出一个坦克图片}int getTankdamage()      //获取坦克伤害{return m_damage;}int getTankhealth()       //获取坦克血量{return m_health;}void setTankhealth(const int health)  //设置坦克血量{m_health = health;}bool getEntadist()                     //获取坦克的死亡状态{return Entankdie;}void setpathsch(const int tanknum)                        //修改坦克行动路线{switch (tanknum) //判断坦克编号{case 1:pathsch = 5;   //坦克1路线切换为路线2break;case 2:pathsch = 6;break;case 3:pathsch = 7;break;case 4:pathsch = 8;break;}}//重置坦克void setEntank(const int tanknum){if (Entankdie == false && (pathsch == 5 || pathsch == 6 || pathsch == 7 || pathsch == 8))return;       //如果这个坦克的路线已经被修改过,且再次死亡,则不再重置switch (tanknum){case 1:m_x = 200, m_y = 40;contdir = 2;break;case 2:m_x = 720, m_y = 120;contdir = 3;break;case 3:m_x = 560, m_y = 120;contdir = 2;break;case 4:m_x = 80, m_y = 360;contdir = 2;}m_health = 300;Entankdie = true;}//坦克1第二路线//直接攻击基地void pathschfun5_1_2(){static bool temp = true;   //临时变量用作标记if(temp == true)contdir = 2;if (m_y == 560 && temp == true)        //往右contdir = 4;if (m_y == 560 && m_x == 240){m_y = 560, m_x = 240;contdir = 0;temp = false;}}//坦克2路线2void pathschfun6_2_2(){//720, 120//需要改变两次方向static bool temp = true;static bool temp2 = true;if (temp == true && temp2 == true)contdir = 3;    //往左if (m_x == 200 && temp == true && temp2 == true)      //往下contdir = 2;if (m_x == 200 && m_y == 560 && temp == true){contdir = 4;      //往右temp2 = false;}if (m_y == 560 && m_x == 280){m_y = 560, m_x = 280;contdir = 0;temp = false;}}//坦克3路线2void pathschfun7_3_2(){static bool temp = true;if (temp == true)contdir = 2;  //往下if (m_y == 560 && temp == true)     //往左contdir = 3;if (m_y == 560 && m_x == 480){m_y = 560, m_x = 480;contdir = 0;temp = false;}}//坦克4路线2void pathschfun8_4_2(){static bool temp = true;if(temp == true)contdir = 2;if (m_y == 560 && temp == true)contdir = 4;if (m_x == 200 && m_y == 560){m_x = 200, m_y = 560;contdir = 0;temp = false;}}//正常路线1void pathschfun_1(){static bool temp  = false;    //临时变量辅助控制坦克行走路线if (m_y == 480 && m_x == 200 && temp == true)           //上{b_m_x = m_x + 18;             //重置子弹位置为坦克中间b_m_y = m_y + 18;contdir = 1;return;}else if (m_y == 40 && m_x == 200)                      //下{b_m_x = m_x + 18;b_m_y = m_y + 18;contdir = 2;temp = false;return;}else if (m_y == 480 && m_x == 200 && temp == false)      //右{b_m_x = m_x + 18;b_m_y = m_y + 18;contdir = 4;temp = true;return;}else if (m_x == 700 && m_y == 480)                      //左{b_m_x = m_x + 18;b_m_y = m_y + 18;contdir = 3;return;}}//正常路线2void pathschfun_2(){if (m_x == 720){b_m_x = m_x + 18;                b_m_y = m_y + 18;contdir = 3;return;}if (m_x <= 140){b_m_x = m_x + 18;b_m_y = m_y + 18;contdir = 4;return;}}//正常路线3void pathschfun_3(){if (m_y == 120){b_m_x = m_x + 18;b_m_y = m_y + 18;contdir = 2;return;}if (m_y >= 480){b_m_x = m_x + 18;b_m_y = m_y + 18;contdir = 1;return;}}//正常路线4void pathschfun_4(){if (m_y == 360){b_m_x = m_x + 18;b_m_y = m_y + 18;contdir = 2;return;}if (m_y >= 560){b_m_x = m_x + 18;b_m_y = m_y + 18;contdir = 1;return;}}//敌军坦克自动移动virtual void move(const list<mapstr>& tempves){//根据contdir值,向不同方向移动switch (contdir){case 1:key2 = 'w';            //方向gettank(path_1);    //坦克图片m_y -= 4;break;case 2:key2 = 's';gettank(path_2);m_y += 4;break;case 3:key2 = 'a';gettank(path_3);m_x -= 4;break;case 4:key2 = 'd';gettank(path_4);m_x += 4;break;}launch();   //发射子弹//不同pathsch不同路线  一个坦克两条路线switch (pathsch){case 1: pathschfun_1(); break;case 2: pathschfun_2(); break;case 3: pathschfun_3(); break;case 4: pathschfun_4(); break;case 5: pathschfun5_1_2(); break;case 6: pathschfun6_2_2(); break;case 7: pathschfun7_3_2(); break;case 8: pathschfun8_4_2();}//敌军坦克被消灭//如果坦克血量小于等于0,则将坦克从界面内移除if (m_health <= 0){Endienum++;          //敌军坦克被消灭次数自增Entankdie = false;    //死亡状态为falsem_x = -40,m_y = -40;//坦克被移除至页面外b_m_x = m_x, b_m_y = m_y;//子弹跟随坦克}}
};//敌军坦克数量
const int N = 4;//子弹命中检测
bool hittest(TankFriend& tank_f, TankEnemy* Etankarr, list<mapstr>& listmap)  //参数:我方坦克对象,敌军坦克对象数组,地图list容器
{const int tanfirlau_x = tank_f.getlauch_x();  //友军坦克子弹x坐标const int tanfirlau_y = tank_f.getlauch_y();    //友军坦克子弹y坐标const int firtank_x = tank_f.getTank_x();       //友军坦克x坐标const int firtank_y = tank_f.getTank_y();     //友军坦克y坐标const int tankfirdam = tank_f.getTankdamage();    //友军坦克伤害const int tankfirhea = tank_f.getTankhealth(); //友军坦克血量for (int i = 0; i < N; i++){//发射子弹需要判断两个点//如果友军子弹和敌军坦克重合,敌军坦克血量减少,且友军坦克子弹坐标重置if ((tanfirlau_x >= Etankarr[i].getTank_x() && tanfirlau_x <= Etankarr[i].getTank_x() + 40 && tanfirlau_y >= Etankarr[i].getTank_y() && tanfirlau_y <= Etankarr[i].getTank_y() + 40) ||(tanfirlau_x + 4 >= Etankarr[i].getTank_x() && tanfirlau_x <= Etankarr[i].getTank_x() + 4 + 40 && tanfirlau_y >= Etankarr[i].getTank_y() + 4 && tanfirlau_y + 4 <= Etankarr[i].getTank_y() + 40)){Etankarr[i].setTankhealth(Etankarr[i].getTankhealth() - tankfirdam);  //血量减少tank_f.exploed();         //友方坦克攻击导致子弹遇到对方的位置爆炸tank_f.setlauch_xy();                              //友军的炮弹坐标重置}//如果敌军子弹和友军坦克重合,友军坦克血量减少,且敌军坦克子弹坐标重置if ((Etankarr[i].getlauch_x() >= firtank_x && Etankarr[i].getlauch_x() <= firtank_x + 40 && Etankarr[i].getlauch_y() >= firtank_y && Etankarr[i].getlauch_y() <= firtank_y + 40) ||(Etankarr[i].getlauch_x() + 4 >= firtank_x && Etankarr[i].getlauch_x() + 4 <= firtank_x + 40 && Etankarr[i].getlauch_y() + 4 >= firtank_y && Etankarr[i].getlauch_y() + 4 <= firtank_y + 40)){tank_f.setTankhealth(tankfirhea - Etankarr[i].getTankdamage());      //友军坦克本身血量 - 敌军坦克伤害Etankarr[i].exploed();Etankarr[i].setlauch_xy();                                         //敌军的炮弹坐标重置}//判断墙的状态//包括我军坦克和敌军坦克子弹和墙的状态for (list<mapstr>::iterator it = listmap.begin(); it != listmap.end(); it++){//子弹碰到墙壁需要判断两个点if ((tank_f.getlauch_x() >= it->m_x && tank_f.getlauch_x() <= it->m_x + 20 &&tank_f.getlauch_y() >= it->m_y && tank_f.getlauch_y() <= it->m_y + 20) ||(tank_f.getlauch_x() + 4 >= it->m_x && tank_f.getlauch_x() + 4 <= it->m_x + 20 &&tank_f.getlauch_y() + 4 >= it->m_y && tank_f.getlauch_y() + 4 <= it->m_y + 20)){switch (it->prop){case 0:       //砖块可以被删除tank_f.exploed();      //子弹处发生爆炸tank_f.setlauch_xy();  //子弹重置listmap.erase(it);        //删除被子弹击中的墙壁数据break;case 1:     //铁块会爆炸不会被删除tank_f.exploed();       //子弹处发生爆炸tank_f.setlauch_xy();  //子弹重置break;case 2:     //草块不会有作用break;case 4:mapstr temp;temp.m_x = it->m_x;temp.m_y = it->m_y;temp.prop = 5;listmap.insert(it, temp);listmap.erase(it);      //老鹰被攻击游戏结束return true;}//最后breakbreak;}if ((Etankarr[i].getlauch_x() >= it->m_x && Etankarr[i].getlauch_x() <= it->m_x + 20 &&Etankarr[i].getlauch_y() >= it->m_y && Etankarr[i].getlauch_y() <= it->m_y + 20) ||(Etankarr[i].getlauch_x() + 4 >= it->m_x && Etankarr[i].getlauch_x() + 4 <= it->m_x + 20 &&Etankarr[i].getlauch_y() + 4 >= it->m_y && Etankarr[i].getlauch_y() + 4 <= it->m_y + 20)){switch (it->prop){case 0:     //砖块可以被删除Etankarr[i].exploed();     //子弹处发生爆炸Etankarr[i].setlauch_xy(); //子弹重置listmap.erase(it);        //删除被子弹击中的墙壁数据break;case 1:     //铁块会爆炸不会被删除Etankarr[i].exploed();      //子弹处发生爆炸Etankarr[i].setlauch_xy(); //子弹重置break;case 2:     //草块不会有作用break;case 4:mapstr temp;temp.m_x = it->m_x;temp.m_y = it->m_y;temp.prop = 5;listmap.insert(it, temp);listmap.erase(it);return true;}//最后breakbreak;}}}return false;
}//游戏开始界面
void initgamebegin()
{//开始背景PIMAGE gabegbaimg = newimage();getimage(gabegbaimg,"坦克大战完整素材\\开始游戏背景.jpg");setimage(1000,600,gabegbaimg);putimage(0, 0, gabegbaimg);//开始按钮PIMAGE gabegimg = newimage();getimage(gabegimg, "坦克大战完整素材\\开始游戏.png");setimage(290, 210, gabegimg);putimage_withalpha (NULL, gabegimg, 305, 440);setfont(120,0,"楷体");              //设置字号,字体setcolor(YELLOW);                   //设置文字颜色setbkmode(1);                       //文字背景色透明outtextxy(210, 100, "坦克大战"); //输出文字mouse_msg msg;        //接收开始游戏的鼠标信息while (true){msg = getmouse();if (msg.is_left())if (msg.x >= 305 && msg.y >= 440 && msg.x <= 305 + 290 && msg.y <= 440 + 210)break;delay_fps(50);}}//游戏胜利结束,全局函数
void gameovertrue()
{cleardevice();PIMAGE gameoverbackimg = newimage();getimage(gameoverbackimg, "坦克大战完整素材\\游戏胜利结束背景.jpg");setimage(1000, 600, gameoverbackimg);putimage(0, 0, gameoverbackimg); //输出背景图片PIMAGE gameoverimg = newimage();getimage(gameoverimg, "坦克大战完整素材\\胜利文字.png");setimage(206, 107, gameoverimg);putimage_withalpha(NULL, gameoverimg, 347, 220); //透明格式输出游戏结束图片delimage(gameoverbackimg);delimage(gameoverimg);              //释放内存getch();getch();
}//主函数
int main()
{initgraph(900, 600, INIT_RENDERMANUAL);    //初始化图形界面setcaption("C++ EGE坦克大战");         //设置窗口标题initgamebegin();                        //游戏开始界面TankFriend tank_f;                      //我方坦克TankEnemy tank_e_1(200, 40, 1);           //敌方坦克 1TankEnemy tank_e_2(720, 120, 2);        //敌方坦克 2TankEnemy tank_e_3(560, 120, 3);        //敌方坦克 3TankEnemy tank_e_4(80, 360, 4);         //敌方坦克 4//敌军坦克数组TankEnemy Etankarr[N] = { tank_e_1, tank_e_2,tank_e_3,tank_e_4 };Mymap map_1;  //地图//获取地图信息list<mapstr> listmap = map_1.getmapves();bool gameoverstat = false;     //判断游戏结束状态变量,默认失败bool basestat = false;         //判断基地老鹰的状态,为真则游戏失败//游戏循环while (true){cleardevice();             //清屏//三条生命  被消灭三次时结束游戏if (tank_f.getFridienumfun() < 3) tank_f.move(listmap);else break;//敌军坦克数组循环for (int i = 0; i < N; i++){if(Etankarr[i].getEntadist() == true)  //坦克必须存活时才会调用移动函数Etankarr[i].move(listmap);         //敌方坦克else{switch (Endienum){case 3:                                //坦克死亡时,且敌军总被消灭次数为3时,已被消灭坦克复活Etankarr[i].setEntank(i + 1);   //重置已坦克被消灭break;case 4:case 6:case 8:case 10:Etankarr[i].setEntank(i + 1); //重置坦克Etankarr[i].setpathsch(i + 1);   //修改坦克路线}}}map_1.printmap(listmap);         //输出地图basestat = hittest(tank_f, Etankarr ,listmap);   //子弹命中坦克检测if (basestat) break;              //如果basestat为true则游戏按失败breakif (Endienum > 10)                   //消灭敌军达10则游戏胜利{gameoverstat = true;break;}delay_fps(62);}//根据游戏结束状态,调用结束函数gameoverstat ? gameovertrue(): gameoverfalse();       //游戏结束return 0;
}//设置图片宽高全局函数
void setimage(int pwidth, int pheight, PIMAGE img_1)
{int whidth = getwidth(img_1), height = getheight(img_1);//获取当前img图像对象的宽高PIMAGE img_2 = newimage(pwidth, pheight);           //创建一个新的图像对象,这个新的图像对象的宽高为//要重新设置的图像的宽高putimage(img_2, 0, 0, pwidth, pheight, img_1, 0, 0, whidth, height);   //将原本img中的图像拉伸绘制到img_2中getimage(img_1, img_2, 0, 0, pwidth, pheight);      //img再获取img_2中的图像delimage(img_2);  //使用完毕将释放掉
}

不足之处:
参照标准的坦克大战,子弹在攻击砖块时,如果子弹正好打中两个砖块,则两个砖块同时被消灭,这个效果我在程序中做不出来。只能是用一个一个地消灭代替了。
在按下键键值不是wasdj时和坦克碰到墙壁时坦克会闪的问题,也暂时没有找到解决办法。
因为初学C++,所以我在类和对象的使用上面还有着很多很多的缺陷和不规范的地方。
还有关于地图的问题,因为我没有经验,所以不知道该怎么简便地创造一个游戏地图,在刚开始的时候还在为用什么实现地图而犹豫过,最后还是选择了list容器逐个将地图元素塞进去,因为考虑到list容器插入和删除数据很快。
我知道在程序中很多地方我都写的极为地不合理,以至于程序运行效率非常低(从我的CPU占用看出来的),但是我会继续努力,继续学习,争取早日解决这些问题。

欢迎大家提出批评和建议。


感谢大家的支持。

C++ 坦克大战小游戏EGE图形界面相关推荐

  1. Java实现的经典坦克大战小游戏

    Java实现的经典坦克大战小游戏 先看一下游戏结构: 有点多,没有耐心的可以不用看,这里先给出链接吧! 云链接:经典坦克大战 提取码:s9ai 这里就不介绍功能了,贴了一张游戏运行的截图,具体的功能自 ...

  2. html实现经典坦克大战小游戏

    文章目录 1.设计来源 1.1 游戏主界面 1.2 游戏界面 2.效果和源码 2.1 动态效果 2.2 源代码 源码下载 作者:xcLeigh 文章地址:https://blog.csdn.net/w ...

  3. C++实用编程——坦克大战小游戏

    C++实用编程--坦克大战小游戏 Warning: 转载类 原文地址:*HTML https://yq.aliyun.com/articles/683666 改变速度的玩意坏了 我们直接看代码吧,适于 ...

  4. 【JAVA程序设计】基于JAVA的坦克大战小游戏--入门级小游戏

    基于JAVA的坦克大战小游戏--入门级小游戏 零.项目获取 一.项目简介 二.开发环境 三.游戏玩法 四.运行截图 零.项目获取 获取方式(点击下载):是云猿实战 项目经过多人测试运行,可以确保100 ...

  5. 【180930】坦克大战小游戏源码

    坦克大战小游戏源码程序实现了小霸王游戏机上坦克大战的功能,主要功能是开火.移动.3种不同的敌方坦克.用户自制地图等,缺点是有些小细节还处理的不好,感觉画面不够好,还没实现自动的下一关功能(主要是嫌做默 ...

  6. C++ 飞机大战小游戏 EGE

    C++ EGE 实现飞机大战小游戏图形界面 飞机大战因为没有了地图的限制,所以相比较坦克大战而言稍微简单一些. 而游戏的可玩性和复杂度一般应该是成正比的. 但是飞机大战并没有因为地图上的省略而变得没有 ...

  7. canvas+js实现简单的坦克大战小游戏

    使用canvas和js实现经典的坦克大战并不难,坦克和炮弹的绘制可以使用canvas的里API画出,而坦克的移动和炮弹的发射可以依赖于键盘事件和定时器来实现. 在这里我要实现的坦克大战是双人模式,有木 ...

  8. 坦克大战小游戏关键技术总结

    这两天参照韩顺平的坦克大战游戏并在其基础上初步完善成一个小的页面游戏,最终js代码大约570行,html代码200多行,具体可参见https://github.com/Mrkaiyang/Art/tr ...

  9. 用HTML语言写一段坦克大战小游戏

    好的,我会尽力帮助你. 你可以使用 HTML 写一个坦克大战的小游戏,代码大概长这样: <!-- 这是 HTML 代码 --> <html><head><ti ...

  10. python3小游戏代码教程_Python3制作仿“经典90坦克大战”小游戏|python3教程|python入门|python教程...

    https://www.xin3721.com/eschool/pythonxin3721/ 本文转载至知乎ID:Charles(白露未晞)知乎个人专栏 下载W3Cschool手机App,0基础随时随 ...

最新文章

  1. 系统开出出现问题~~~\WINDOWS\SYSTEM32\CONFIG\SYSTEM 损坏或丢失无法开机
  2. [ARC055D]隠された等差数列
  3. 【渝粤教育】国家开放大学2018年秋季 0734-22T出纳实务 参考试题
  4. android unbound prefix
  5. 30行python代码设计_30行Python代码实现3D数据可视化
  6. 百度seo排名规则_SEO:百度搜索引擎排名规则都有哪些?
  7. 渲染器跑分_碾压图灵43!NVIDIA安培第一个跑分震撼出炉
  8. ASP 無組件上傳類
  9. 关于eclipse中maven项目的问题
  10. php支付自定义金额,自定义付款/支付/收费
  11. 群联PS3111坏硬盘修复记录
  12. [代码审计]Textpattern4.8.4任意文件上传漏洞
  13. 阿里云ECS后台CPU占用100%,top却找不到
  14. nginx下的一级域名跳转到二级域名的配置
  15. MATLAB椎体怎么画,最适合小白的matlab教程系列,进阶,一
  16. 全国率先!北京发文推进电子劳动合同
  17. 站长VS微商 你选择哪个?
  18. 【图像分类损失】Encouraging Loss:一个反直觉的分类损失
  19. 【JavaEE进阶系列 | 从小白到工程师】JavaWeb中的过滤器(Filter)和监听器(Listener)区别,看这一篇就够
  20. java多人聊天室实现(可群聊私聊/添加好友/发送文件)

热门文章

  1. java中接口(interface)及使用方法和注意事项
  2. 如何查看本机flash版本
  3. 更换持续集成工具,从 Travis 到 Github Actions
  4. STM32显示图片,将图片转换为十六进制数组便捷工具
  5. 英语口语笔记B1-Unit04.家居生活-02-Buying household products
  6. 采样频率变化时,滤波器的性能会变差吗?
  7. windows系统C盘pagefile.sys占用空间大怎么解决
  8. 2020高考数学:常用知识点公式第四章(文科)
  9. 学考计算机会考考点工作总结,高中生学业水平考试工作总结范文
  10. J2me的基本概念(转)