C++实现坦克大战小游戏EGE图形界面
C++EGE实现坦克大战小游戏,供大家参考,具体内容如下
因为有过一次用EGE写小游戏的经验,所以这一次写坦克大战快了很多。并且使用对象编程也简化了很多编程时繁琐的步骤。
写出坦克大战使我在学习编程的道路上又迈出了一大步。
如果您需要图片素材的,我可以单独发给您。
技术环节:
编译环境:WindowsVS2019
需求:
控制坦克移动发射炮弹,炮弹可以消灭敌军坦克,且可以消灭砖块。坦克遇到方块会被挡住。敌军消灭我军三次或基地被毁则游戏失败,共摧毁十次敌方坦克游戏胜利。
思路:
先写出坦克的父类,我方坦克类和敌方坦克类继承坦克父类,实例化我方坦克和敌方坦克。地图使用list容器存储。
在代码注释中标注了每一步是怎么实现的。
注意:
因为我在程序中用了一些不规范的写法,所以要在VS中正常编译运行,需要右键源文件->属性->C/C+±>符合模式,改为否。
包含
如要在其他graphics图形库下编译,可能需要修改某些地方。
运行效果:
代码:
#include//图形库 #include //time(); #include //list容器 usingnamespacestd;//标准命名空间list等 //设置图片对象中图片的宽高全局函数 //参数:宽、高、对象名 voidsetimage(intpwidth,intpheight,PIMAGEimg_1); //地图全局结构 structmapstr { intm_x;//xy坐标 intm_y; intprop;//属性 }; //地图类 classMymap { private: list
listmap;//地图容器,存储全地图信息,全地图1350个20*20的格子 public: //设置地图 Mymap() { mapstrtemp; //构造函数为链表容器中的地图赋值 //全地图横向45个格子竖向30个格子 //基地部分 { temp.prop=0; for(inti=0;i<4;i++){temp.m_x=380+i*20;temp.m_y=540;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=380+i*20;temp.m_y=520;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=380;temp.m_y=560+i*20;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=360;temp.m_y=520+i*20;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=440;temp.m_y=560+i*20;listmap.push_back(temp);} for(inti=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(inti=0;i<2;i++){temp.m_x=40+i*20;temp.m_y=80;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=40+i*20;temp.m_y=100;listmap.push_back(temp);} //竖铁块 for(inti=0;i<4;i++){temp.m_x=160;temp.m_y=i*20;temp.prop=1;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=180;temp.m_y=i*20;listmap.push_back(temp);} //砖块 for(inti=0;i<4;i++){temp.m_x=160;temp.m_y=160+i*20;temp.prop=0;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=180;temp.m_y=160+i*20;listmap.push_back(temp);} //草块 for(inti=0;i<4;i++){temp.m_x=0;temp.m_y=200+i*20;temp.prop=2;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=20;temp.m_y=200+i*20;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=40+i*20;temp.m_y=240;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=40+i*20;temp.m_y=260;listmap.push_back(temp);} } //中上部分 { //铁块 for(inti=0;i<2;i++){temp.m_x=320;temp.m_y=i*20;temp.prop=1;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=340;temp.m_y=i*20;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=280+i*20;temp.m_y=160;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=280+i*20;temp.m_y=180;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=400+i*20;temp.m_y=200;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=400+i*20;temp.m_y=220;listmap.push_back(temp);} //砖块 for(inti=0;i<4;i++){temp.m_x=320;temp.m_y=40+i*20;temp.prop=0;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=340;temp.m_y=40+i*20;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=240;temp.m_y=200+i*20;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=260;temp.m_y=200+i*20;listmap.push_back(temp);} } //右上部分 { //砖块 for(inti=0;i<4;i++){temp.m_x=480;temp.m_y=40+i*20;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=500;temp.m_y=40+i*20;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=480;temp.m_y=160+i*20;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=500;temp.m_y=160+i*20;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=600;temp.m_y=40+i*20;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=620;temp.m_y=40+i*20;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=600;temp.m_y=160+i*20;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=620;temp.m_y=160+i*20;listmap.push_back(temp);} for(inti=0;i<6;i++){temp.m_x=680+i*20;temp.m_y=200;listmap.push_back(temp);} for(inti=0;i<6;i++){temp.m_x=680+i*20;temp.m_y=220;listmap.push_back(temp);} for(inti=0;i<6;i++){temp.m_x=760;temp.m_y=0+i*20;listmap.push_back(temp);} for(inti=0;i<6;i++){temp.m_x=780;temp.m_y=0+i*20;listmap.push_back(temp);} //草块 for(inti=0;i<6;i++){temp.m_x=560;temp.m_y=160+i*20;temp.prop=2;listmap.push_back(temp);} for(inti=0;i<6;i++){temp.m_x=580;temp.m_y=160+i*20;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=520;temp.m_y=160+i*20;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=540;temp.m_y=160+i*20;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=860;temp.m_y=80+i*20;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=880;temp.m_y=80+i*20;listmap.push_back(temp);} //铁块 for(inti=0;i<4;i++){temp.m_x=520+i*20;temp.m_y=80;temp.prop=1;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=520+i*20;temp.m_y=100;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=640+i*20;temp.m_y=160;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=640+i*20;temp.m_y=180;listmap.push_back(temp);} for(inti=0;i<6;i++){temp.m_x=800+i*20;temp.m_y=200;listmap.push_back(temp);} for(inti=0;i<6;i++){temp.m_x=800+i*20;temp.m_y=220;listmap.push_back(temp);} } //左下部分 { //铁块 for(inti=0;i<2;i++){temp.m_x=i*20;temp.m_y=360;temp.prop=1;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=i*20;temp.m_y=380;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=160;temp.m_y=320+i*20;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=180;temp.m_y=320+i*20;listmap.push_back(temp);} //砖块 for(inti=0;i<12;i++){temp.m_x=40;temp.m_y=360+i*20;temp.prop=0;listmap.push_back(temp);} for(inti=0;i<12;i++){temp.m_x=60;temp.m_y=360+i*20;listmap.push_back(temp);} for(inti=0;i<8;i++){temp.m_x=40+i*20;temp.m_y=280;listmap.push_back(temp);} for(inti=0;i<8;i++){temp.m_x=40+i*20;temp.m_y=300;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=160;temp.m_y=400+i*20;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=180;temp.m_y=400+i*20;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=160;temp.m_y=560+i*20;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=180;temp.m_y=560+i*20;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=240+i*20;temp.m_y=240;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=240+i*20;temp.m_y=260;listmap.push_back(temp);} for(inti=0;i<8;i++){temp.m_x=280;temp.m_y=320+i*20;listmap.push_back(temp);} for(inti=0;i<8;i++){temp.m_x=300;temp.m_y=320+i*20;listmap.push_back(temp);} for(inti=0;i<8;i++){temp.m_x=320;temp.m_y=320+i*20;listmap.push_back(temp);} for(inti=0;i<8;i++){temp.m_x=340;temp.m_y=320+i*20;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=360;temp.m_y=400+i*20;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=380;temp.m_y=400+i*20;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=400;temp.m_y=400+i*20;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=420;temp.m_y=400+i*20;listmap.push_back(temp);} for(inti=0;i<8;i++){temp.m_x=440;temp.m_y=320+i*20;listmap.push_back(temp);} for(inti=0;i<8;i++){temp.m_x=460;temp.m_y=320+i*20;listmap.push_back(temp);} for(inti=0;i<8;i++){temp.m_x=480;temp.m_y=320+i*20;listmap.push_back(temp);} for(inti=0;i<8;i++){temp.m_x=500;temp.m_y=320+i*20;listmap.push_back(temp);} for(inti=0;i<8;i++){temp.m_x=520;temp.m_y=320+i*20;listmap.push_back(temp);} for(inti=0;i<8;i++){temp.m_x=540;temp.m_y=320+i*20;listmap.push_back(temp);} //草块 for(inti=0;i<10;i++){temp.m_x=200+i*20;temp.m_y=280;temp.prop=2;listmap.push_back(temp);} for(inti=0;i<10;i++){temp.m_x=200+i*20;temp.m_y=300;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=200+i*20;temp.m_y=320;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=200+i*20;temp.m_y=340;listmap.push_back(temp);} } //右下部分 { //砖块 for(inti=0;i<8;i++){temp.m_x=600;temp.m_y=320+i*20;temp.prop=0;listmap.push_back(temp);} for(inti=0;i<8;i++){temp.m_x=620;temp.m_y=320+i*20;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=560;temp.m_y=520+i*20;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=580;temp.m_y=520+i*20;listmap.push_back(temp);} for(inti=0;i<8;i++){temp.m_x=600+i*20;temp.m_y=560;listmap.push_back(temp);} for(inti=0;i<8;i++){temp.m_x=600+i*20;temp.m_y=580;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=680+i*20;temp.m_y=520;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=680+i*20;temp.m_y=540;listmap.push_back(temp);} for(inti=0;i<7;i++){temp.m_x=760+i*20;temp.m_y=320;listmap.push_back(temp);} for(inti=0;i<7;i++){temp.m_x=760+i*20;temp.m_y=340;listmap.push_back(temp);} for(inti=0;i<8;i++){temp.m_x=800;temp.m_y=320+i*20;listmap.push_back(temp);} for(inti=0;i<8;i++){temp.m_x=820;temp.m_y=320+i*20;listmap.push_back(temp);} //铁块 for(inti=0;i<4;i++){temp.m_x=640;temp.m_y=320+i*20;temp.prop=1;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=660;temp.m_y=320+i*20;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=680;temp.m_y=320+i*20;temp.prop=1;listmap.push_back(temp);} for(inti=0;i<2;i++){temp.m_x=700;temp.m_y=320+i*20;temp.prop=1;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=820+i*20;temp.m_y=480;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=820+i*20;temp.m_y=500;listmap.push_back(temp);} //草块 for(inti=0;i<4;i++){temp.m_x=560;temp.m_y=360+i*20;temp.prop=2;listmap.push_back(temp);} for(inti=0;i<4;i++){temp.m_x=580;temp.m_y=360+i*20;listmap.push_back(temp);} } } //显示地图 voidprintmap(list &listmap) { PIMAGEmapprop_0=newimage(); getimage(mapprop_0,"坦克大战完整素材\\砖块.png"); setimage(20,20,mapprop_0); PIMAGEmapprop_1=newimage(); getimage(mapprop_1,"坦克大战完整素材\\铁块.png"); setimage(20,20,mapprop_1); PIMAGEmapprop_2=newimage(); getimage(mapprop_2,"坦克大战完整素材\\草块.png"); setimage(20,20,mapprop_2); PIMAGEmapprop_4=newimage(); getimage(mapprop_4,"坦克大战完整素材\\老鹰_1.png"); setimage(40,40,mapprop_4); PIMAGEmapprop_5=newimage(); getimage(mapprop_5,"坦克大战完整素材\\老鹰_2.png"); setimage(40,40,mapprop_5); for(list ::iteratorit=listmap.begin();it!=listmap.end();it++) { switch(it->prop) { case0: putimage(it->m_x,it->m_y,mapprop_0); break; case1: putimage(it->m_x,it->m_y,mapprop_1); break; case2: putimage(it->m_x,it->m_y,mapprop_2); break; case4: putimage(it->m_x,it->m_y,mapprop_4); break; case5: 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 getmapves() { returnlistmap; } }; //坦克父类 classTank { public: virtualvoidmove(constlist &tempves)=0;//坦克移动函数 intgetlauch_x()//获取子弹x坐标 { returnb_m_x; } intgetlauch_y()//获取子弹y坐标 { returnb_m_y; } voidsetlauch_xy()//设置子弹坐标 { b_m_x=m_x+18;//重置位置为坦克中间 b_m_y=m_y+18; key1=key2;//key1=key2避免炮弹一直发射 } intgetTank_x()//获取坦克x坐标 { returnm_x; } intgetTank_y()//获取坦克y坐标 { returnm_y; } chargetkey2()//返回发射时的坦克方向信息 { returnkey2; } //坦克攻击子弹位置爆炸 voidexploed() { PIMAGEexplimg_1=newimage(); getimage(explimg_1,"坦克大战完整素材\\爆炸效果1.png"); setimage(10,10,explimg_1); PIMAGEexplimg_2=newimage(); getimage(explimg_2,"坦克大战完整素材\\爆炸效果2.png"); setimage(20,20,explimg_2); PIMAGEexplimg_3=newimage(); getimage(explimg_3,"坦克大战完整素材\\爆炸效果3.png"); setimage(40,40,explimg_3); PIMAGEexplimgarr[3]={explimg_1,explimg_2,explimg_3}; for(inti=0;i<3;i++) { if(key2=='d'||key2=='a')//根据坦克的攻击朝向确定爆炸的位置 putimage(b_m_x,b_m_y-6*i,explimgarr[i]); else putimage(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: //从文件中获取坦克图片 voidgettank(constchar*path) { PIMAGEtankimg=newimage();//创建图片对象 getimage(tankimg,path);//在文件中获取图片到图片对象 setimage(40,40,tankimg);//设置图片对象大小 putimage(this->m_x,this->m_y,tankimg);//在坐标处输出图片 delimage(tankimg);//释放图片对象 } //输出显示坦克 voidprinttank(constcharkey2) { //根据当前的键值,输出坦克 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; } } //发射子弹 voidlaunch() { 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();//重置子弹位置 } intm_x;//坦克xy坐标 intm_y; intm_health;//坦克血量 intm_damage;//子弹伤害量 char*path_1;//四张不同方向的坦克图片,由派生类决定图片路径 char*path_2; char*path_3; char*path_4; intb_m_x;//子弹坐标xy intb_m_y; charkey1;//用于接收键盘信息 charkey2;//用于存储上一条键值,也是发射时的坦克的朝向 }; //游戏失败结束全局函数在生命为0和基地被攻击时调用 voidgameoverfalse() { cleardevice(); PIMAGEgameoverbackimg=newimage(); getimage(gameoverbackimg,"坦克大战完整素材\\游戏结束背景.jpg"); setimage(900,600,gameoverbackimg); putimage(0,0,gameoverbackimg);//输出背景图片 PIMAGEgameoverimg=newimage(); getimage(gameoverimg,"坦克大战完整素材\\游戏结束.png"); setimage(200,200,gameoverimg); putimage_withalpha(NULL,gameoverimg,350,200);//透明格式输出游戏结束图片 delimage(gameoverbackimg); delimage(gameoverimg);//释放内存 getch(); getch(); } //我方坦克,可被操控移动 classTankFriend:publicTank { private: intFridienum=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用于输出初始的坦克 } intgetTankdamage()//获取坦克伤害 { returnm_damage; } intgetTankhealth()//获取坦克血量 { returnm_health; } voidsetTankhealth(constinthealth)//设置坦克血量 { m_health=health; } intgetFridienumfun()//获取我方坦克被消灭次数 { returnFridienum; } //坦克被操控移动 virtualvoidmove(constlist &tempves) { if(key1!='j') key2=key1;//key2记录上一个key1的值 if(kbhit()) { //用临时变量接收键值,如果键值为wasdj中的一个则赋给使用的变量 chartempkey=getch(); switch(tempkey) { case'w':case'a': case's':case'd': case'j': key1=tempkey; break; //接收的键盘值不是wasdj直接return default: return; } //判断坦克撞墙情况,坦克撞墙可以改变方向,但不会移动坐标 for(list ::const_iteratorit=tempves.begin();it!=tempves.end();it++) { switch(tempkey) { //这里的大于小于号一个都不能错 case'w': if( ( //判断坦克原xy点 (m_x>=it->m_x&&m_x 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 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 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 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;//血量 } } }; //统计所有敌军坦克次数全局变量 intEndienum; //敌军坦克 classTankEnemy:publicTank { private: intpathsch;//路线方案 intcontdir; boolEntankdie=true;//标记敌军坦克的死亡状态 public: //构造函数接收初始坦克坐标 TankEnemy(constintx,constinty,constintpathsch)//构造函数初始化坦克坐标 { 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);//输出一个坦克图片 } intgetTankdamage()//获取坦克伤害 { returnm_damage; } intgetTankhealth()//获取坦克血量 { returnm_health; } voidsetTankhealth(constinthealth)//设置坦克血量 { m_health=health; } boolgetEntadist()//获取坦克的死亡状态 { returnEntankdie; } voidsetpathsch(constinttanknum)//修改坦克行动路线 { switch(tanknum)//判断坦克编号 { case1: pathsch=5;//坦克1路线切换为路线2 break; case2: pathsch=6; break; case3: pathsch=7; break; case4: pathsch=8; break; } } //重置坦克 voidsetEntank(constinttanknum) { if(Entankdie==false&&(pathsch==5||pathsch==6||pathsch==7||pathsch==8)) return;//如果这个坦克的路线已经被修改过,且再次死亡,则不再重置 switch(tanknum) { case1: m_x=200,m_y=40; contdir=2; break; case2: m_x=720,m_y=120; contdir=3; break; case3: m_x=560,m_y=120; contdir=2; break; case4: m_x=80,m_y=360; contdir=2; } m_health=300; Entankdie=true; } //坦克1第二路线 //直接攻击基地 voidpathschfun5_1_2() { staticbooltemp=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路线2 voidpathschfun6_2_2() { //720,120 //需要改变两次方向 staticbooltemp=true; staticbooltemp2=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路线2 voidpathschfun7_3_2() { staticbooltemp=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路线2 voidpathschfun8_4_2() { staticbooltemp=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; } } //正常路线1 voidpathschfun_1() { staticbooltemp=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; } elseif(m_y==40&&m_x==200)//下 { b_m_x=m_x+18; b_m_y=m_y+18; contdir=2; temp=false; return; } elseif(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; } elseif(m_x==700&&m_y==480)//左 { b_m_x=m_x+18; b_m_y=m_y+18; contdir=3; return; } } //正常路线2 voidpathschfun_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; } } //正常路线3 voidpathschfun_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; } } //正常路线4 voidpathschfun_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; } } //敌军坦克自动移动 virtualvoidmove(constlist &tempves) { //根据contdir值,向不同方向移动 switch(contdir) { case1: key2='w';//方向 gettank(path_1);//坦克图片 m_y-=4; break; case2: key2='s'; gettank(path_2); m_y+=4; break; case3: key2='a'; gettank(path_3); m_x-=4; break; case4: key2='d'; gettank(path_4); m_x+=4; break; } launch();//发射子弹 //不同pathsch不同路线一个坦克两条路线 switch(pathsch) { case1:pathschfun_1();break; case2:pathschfun_2();break; case3:pathschfun_3();break; case4:pathschfun_4();break; case5:pathschfun5_1_2();break; case6:pathschfun6_2_2();break; case7:pathschfun7_3_2();break; case8:pathschfun8_4_2(); } //敌军坦克被消灭 //如果坦克血量小于等于0,则将坦克从界面内移除 if(m_health<=0) { Endienum++;//敌军坦克被消灭次数自增 Entankdie=false;//死亡状态为false m_x=-40,m_y=-40;//坦克被移除至页面外 b_m_x=m_x,b_m_y=m_y;//子弹跟随坦克 } } }; //敌军坦克数量 constintN=4; //子弹命中检测 boolhittest(TankFriend&tank_f,TankEnemy*Etankarr,list &listmap)//参数:我方坦克对象,敌军坦克对象数组,地图list容器 { constinttanfirlau_x=tank_f.getlauch_x();//友军坦克子弹x坐标 constinttanfirlau_y=tank_f.getlauch_y();//友军坦克子弹y坐标 constintfirtank_x=tank_f.getTank_x();//友军坦克x坐标 constintfirtank_y=tank_f.getTank_y();//友军坦克y坐标 constinttankfirdam=tank_f.getTankdamage();//友军坦克伤害 constinttankfirhea=tank_f.getTankhealth();//友军坦克血量 for(inti=0;i =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 ::iteratorit=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) { case0://砖块可以被删除 tank_f.exploed();//子弹处发生爆炸 tank_f.setlauch_xy();//子弹重置 listmap.erase(it);//删除被子弹击中的墙壁数据 break; case1://铁块会爆炸不会被删除 tank_f.exploed();//子弹处发生爆炸 tank_f.setlauch_xy();//子弹重置 break; case2://草块不会有作用 break; case4: mapstrtemp; temp.m_x=it->m_x; temp.m_y=it->m_y; temp.prop=5; listmap.insert(it,temp); listmap.erase(it);//老鹰被攻击游戏结束 returntrue; } //最后break break; } 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) { case0://砖块可以被删除 Etankarr[i].exploed();//子弹处发生爆炸 Etankarr[i].setlauch_xy();//子弹重置 listmap.erase(it);//删除被子弹击中的墙壁数据 break; case1://铁块会爆炸不会被删除 Etankarr[i].exploed();//子弹处发生爆炸 Etankarr[i].setlauch_xy();//子弹重置 break; case2://草块不会有作用 break; case4: mapstrtemp; temp.m_x=it->m_x; temp.m_y=it->m_y; temp.prop=5; listmap.insert(it,temp); listmap.erase(it); returntrue; } //最后break break; } } } returnfalse; } //游戏开始界面 voidinitgamebegin() { //开始背景 PIMAGEgabegbaimg=newimage(); getimage(gabegbaimg,"坦克大战完整素材\\开始游戏背景.jpg"); setimage(1000,600,gabegbaimg); putimage(0,0,gabegbaimg); //开始按钮 PIMAGEgabegimg=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_msgmsg;//接收开始游戏的鼠标信息 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); } } //游戏胜利结束,全局函数 voidgameovertrue() { cleardevice(); PIMAGEgameoverbackimg=newimage(); getimage(gameoverbackimg,"坦克大战完整素材\\游戏胜利结束背景.jpg"); setimage(1000,600,gameoverbackimg); putimage(0,0,gameoverbackimg);//输出背景图片 PIMAGEgameoverimg=newimage(); getimage(gameoverimg,"坦克大战完整素材\\胜利文字.png"); setimage(206,107,gameoverimg); putimage_withalpha(NULL,gameoverimg,347,220);//透明格式输出游戏结束图片 delimage(gameoverbackimg); delimage(gameoverimg);//释放内存 getch(); getch(); } //主函数 intmain() { initgraph(900,600,INIT_RENDERMANUAL);//初始化图形界面 setcaption("C++EGE坦克大战");//设置窗口标题 initgamebegin();//游戏开始界面 TankFriendtank_f;//我方坦克 TankEnemytank_e_1(200,40,1);//敌方坦克1 TankEnemytank_e_2(720,120,2);//敌方坦克2 TankEnemytank_e_3(560,120,3);//敌方坦克3 TankEnemytank_e_4(80,360,4);//敌方坦克4 //敌军坦克数组 TankEnemyEtankarr[N]={tank_e_1,tank_e_2,tank_e_3,tank_e_4}; Mymapmap_1;//地图 //获取地图信息 list listmap=map_1.getmapves(); boolgameoverstat=false;//判断游戏结束状态变量,默认失败 boolbasestat=false;//判断基地老鹰的状态,为真则游戏失败 //游戏循环 while(true) { cleardevice();//清屏 //三条生命被消灭三次时结束游戏 if(tank_f.getFridienumfun()<3) tank_f.move(listmap); elsebreak; //敌军坦克数组循环 for(inti=0;i 10)//消灭敌军达10则游戏胜利 { gameoverstat=true; break; } delay_fps(62); } //根据游戏结束状态,调用结束函数 gameoverstat?gameovertrue():gameoverfalse();//游戏结束 return0; } //设置图片宽高全局函数 voidsetimage(intpwidth,intpheight,PIMAGEimg_1) { intwhidth=getwidth(img_1),height=getheight(img_1);//获取当前img图像对象的宽高 PIMAGEimg_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占用看出来的),但是我会继续努力,继续学习,争取早日解决这些问题。
欢迎大家提出批评和建议。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。