C++實現(xiàn)坦克大戰(zhàn)小游戲EGE圖形界面
C++ EGE 實現(xiàn)坦克大戰(zhàn)小游戲,供大家參考,具體內容如下
因為有過一次用EGE寫小游戲的經驗,所以這一次寫坦克大戰(zhàn)快了很多。并且使用對象編程也簡化了很多編程時繁瑣的步驟。
寫出坦克大戰(zhàn)使我在學習編程的道路上又邁出了一大步。
如果您需要圖片素材的,我可以單獨發(fā)給您。
技術環(huán)節(jié):
編譯環(huán)境:Windows VS2019
需求:
控制坦克移動發(fā)射炮彈,炮彈可以消滅敵軍坦克,且可以消滅磚塊。坦克遇到方塊會被擋住。敵軍消滅我軍三次或基地被毀則游戲失敗,共摧毀十次敵方坦克游戲勝利。
思路:
先寫出坦克的父類,我方坦克類和敵方坦克類繼承坦克父類,實例化我方坦克和敵方坦克。地圖使用list容器存儲。
在代碼注釋中標注了每一步是怎么實現(xiàn)的。
注意:
因為我在程序中用了一些不規(guī)范的寫法,所以要在VS中正常編譯運行,需要右鍵源文件->屬性->C/C+±>符合模式,改為否。
包含<graphics.h>圖形庫需要提前配置EGE圖形庫。
如要在其他graphics圖形庫下編譯,可能需要修改某些地方。
運行效果:



代碼:
#include <graphics.h> //圖形庫
#include <ctime> //time();
#include <list> //list容器
using namespace std; //標準命名空間 list等
//設置圖片對象中圖片的寬高 全局函數(shù)
//參數(shù):寬、高、對象名
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;
//構造函數(shù)為鏈表容器中的地圖賦值
//全地圖橫向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, "坦克大戰(zhàn)完整素材\\磚塊.png");
setimage(20, 20, mapprop_0);
PIMAGE mapprop_1 = newimage();
getimage(mapprop_1, "坦克大戰(zhàn)完整素材\\鐵塊.png");
setimage(20, 20, mapprop_1);
PIMAGE mapprop_2 = newimage();
getimage(mapprop_2, "坦克大戰(zhàn)完整素材\\草塊.png");
setimage(20, 20, mapprop_2);
PIMAGE mapprop_4 = newimage();
getimage(mapprop_4, "坦克大戰(zhàn)完整素材\\老鷹_1.png");
setimage(40, 40, mapprop_4);
PIMAGE mapprop_5 = newimage();
getimage(mapprop_5, "坦克大戰(zhàn)完整素材\\老鷹_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; //坦克移動函數(shù)
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避免炮彈一直發(fā)射
}
int getTank_x() //獲取坦克x坐標
{
return m_x;
}
int getTank_y() //獲取坦克y坐標
{
return m_y;
}
char getkey2() //返回發(fā)射時的坦克方向信息
{
return key2;
}
//坦克攻擊子彈位置爆炸
void exploed()
{
PIMAGE explimg_1 = newimage();
getimage(explimg_1, "坦克大戰(zhàn)完整素材\\爆炸效果1.png");
setimage(10, 10, explimg_1);
PIMAGE explimg_2 = newimage();
getimage(explimg_2, "坦克大戰(zhàn)完整素材\\爆炸效果2.png");
setimage(20, 20, explimg_2);
PIMAGE explimg_3 = newimage();
getimage(explimg_3, "坦克大戰(zhàn)完整素材\\爆炸效果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')//根據(jù)坦克的攻擊朝向確定爆炸的位置
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);
}
//構造函數(shù)
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(); //創(chuàng)建圖片對象
getimage(tankimg, path); //在文件中獲取圖片到圖片對象
setimage(40, 40, tankimg); //設置圖片對象大小
putimage(this->m_x, this->m_y, tankimg);//在坐標處輸出圖片
delimage(tankimg); //釋放圖片對象
}
//輸出顯示坦克
void printtank(const char key2)
{
//根據(jù)當前的鍵值,輸出坦克
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;
}
}
//發(fā)射子彈
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; //子彈坐標xy
int b_m_y;
char key1; //用于接收鍵盤信息
char key2; //用于存儲上一條鍵值,也是發(fā)射時的坦克的朝向
};
//游戲失敗結束全局函數(shù) 在生命為0 和 基地被攻擊時調用
void gameoverfalse()
{
cleardevice();
PIMAGE gameoverbackimg = newimage();
getimage(gameoverbackimg, "坦克大戰(zhàn)完整素材\\游戲結束背景.jpg");
setimage(900,600,gameoverbackimg);
putimage(0, 0, gameoverbackimg); //輸出背景圖片
PIMAGE gameoverimg = newimage();
getimage(gameoverimg, "坦克大戰(zhàn)完整素材\\游戲結束.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:
//構造函數(shù)初始化坦克坐標
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 = "坦克大戰(zhàn)完整素材\\己方坦克上.png"; //賦值需要將源文件屬性語言中符合模式改為否
path_2 = "坦克大戰(zhàn)完整素材\\己方坦克下.png";
path_3 = "坦克大戰(zhàn)完整素材\\己方坦克左.png";
path_4 = "坦克大戰(zhàn)完整素材\\己方坦克右.png";
key1 = 'w'; //初始化key1用于輸出初始的坦克
}
int getTankdamage() //獲取坦克傷害
{
return m_damage;
}
int getTankhealth() //獲取坦克血量
{
return m_health;
}
void setTankhealth(const int health) //設置坦克血量
{
m_health = health;
}
int getFridienumfun() //獲取我方坦克被消滅次數(shù)
{
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直接return
default:
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;
}
}
//根據(jù)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則發(fā)射炮彈,如果鍵值為wasd則移動坦克
if (key1 == 'j')
launch();
else
{
printtank(key1); //根據(jù)鍵值輸出顯示坦克
b_m_x = m_x + 18; //移動時也重置子彈坐標
b_m_y = m_y + 18; //這里key1值不能重置為key2值
}
//如果我軍坦克被消滅,則被消滅次數(shù)+1,并重置坦克
if (m_health <= 0)
{
Fridienum++;
m_x = 300; //坐標
m_y = 560;
m_health = 100; //血量
}
}
};
//統(tǒng)計所有敵軍坦克次數(shù)全局變量
int Endienum;
//敵軍坦克
class TankEnemy :public Tank
{
private:
int pathsch; //路線方案
int contdir;
bool Entankdie = true; //標記敵軍坦克的死亡狀態(tài)
public:
//構造函數(shù)接收初始坦克坐標
TankEnemy(const int x ,const int y, const int pathsch) //構造函數(shù)初始化坦克坐標
{
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 = "坦克大戰(zhàn)完整素材\\敵方坦克上.png"; //賦值需要將源文件屬性語言中符合模式改為否
path_2 = "坦克大戰(zhàn)完整素材\\敵方坦克下.png";
path_3 = "坦克大戰(zhàn)完整素材\\敵方坦克左.png";
path_4 = "坦克大戰(zhàn)完整素材\\敵方坦克右.png";
gettank(path_1);//輸出一個坦克圖片
}
int getTankdamage() //獲取坦克傷害
{
return m_damage;
}
int getTankhealth() //獲取坦克血量
{
return m_health;
}
void setTankhealth(const int health) //設置坦克血量
{
m_health = health;
}
bool getEntadist() //獲取坦克的死亡狀態(tài)
{
return Entankdie;
}
void setpathsch(const int tanknum) //修改坦克行動路線
{
switch (tanknum) //判斷坦克編號
{
case 1:
pathsch = 5; //坦克1路線切換為路線2
break;
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路線2
void 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路線2
void 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路線2
void 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;
}
}
//正常路線1
void 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;
}
}
//正常路線2
void 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;
}
}
//正常路線3
void 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;
}
}
//正常路線4
void 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)
{
//根據(jù)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(); //發(fā)射子彈
//不同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++; //敵軍坦克被消滅次數(shù)自增
Entankdie = false; //死亡狀態(tài)為false
m_x = -40,m_y = -40;//坦克被移除至頁面外
b_m_x = m_x, b_m_y = m_y;//子彈跟隨坦克
}
}
};
//敵軍坦克數(shù)量
const int N = 4;
//子彈命中檢測
bool hittest(TankFriend& tank_f, TankEnemy* Etankarr, list<mapstr>& listmap) //參數(shù):我方坦克對象,敵軍坦克對象數(shù)組,地圖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++)
{
//發(fā)射子彈需要判斷兩個點
//如果友軍子彈和敵軍坦克重合,敵軍坦克血量減少,且友軍坦克子彈坐標重置
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(); //敵軍的炮彈坐標重置
}
//判斷墻的狀態(tài)
//包括我軍坦克和敵軍坦克子彈和墻的狀態(tài)
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(); //子彈處發(fā)生爆炸
tank_f.setlauch_xy(); //子彈重置
listmap.erase(it); //刪除被子彈擊中的墻壁數(shù)據(jù)
break;
case 1: //鐵塊會爆炸不會被刪除
tank_f.exploed(); //子彈處發(fā)生爆炸
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;
}
//最后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)
{
case 0: //磚塊可以被刪除
Etankarr[i].exploed(); //子彈處發(fā)生爆炸
Etankarr[i].setlauch_xy(); //子彈重置
listmap.erase(it); //刪除被子彈擊中的墻壁數(shù)據(jù)
break;
case 1: //鐵塊會爆炸不會被刪除
Etankarr[i].exploed(); //子彈處發(fā)生爆炸
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;
}
//最后break
break;
}
}
}
return false;
}
//游戲開始界面
void initgamebegin()
{
//開始背景
PIMAGE gabegbaimg = newimage();
getimage(gabegbaimg,"坦克大戰(zhàn)完整素材\\開始游戲背景.jpg");
setimage(1000,600,gabegbaimg);
putimage(0, 0, gabegbaimg);
//開始按鈕
PIMAGE gabegimg = newimage();
getimage(gabegimg, "坦克大戰(zhàn)完整素材\\開始游戲.png");
setimage(290, 210, gabegimg);
putimage_withalpha (NULL, gabegimg, 305, 440);
setfont(120,0,"楷體"); //設置字號,字體
setcolor(YELLOW); //設置文字顏色
setbkmode(1); //文字背景色透明
outtextxy(210, 100, "坦克大戰(zhàn)"); //輸出文字
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);
}
}
//游戲勝利結束,全局函數(shù)
void gameovertrue()
{
cleardevice();
PIMAGE gameoverbackimg = newimage();
getimage(gameoverbackimg, "坦克大戰(zhàn)完整素材\\游戲勝利結束背景.jpg");
setimage(1000, 600, gameoverbackimg);
putimage(0, 0, gameoverbackimg); //輸出背景圖片
PIMAGE gameoverimg = newimage();
getimage(gameoverimg, "坦克大戰(zhàn)完整素材\\勝利文字.png");
setimage(206, 107, gameoverimg);
putimage_withalpha(NULL, gameoverimg, 347, 220); //透明格式輸出游戲結束圖片
delimage(gameoverbackimg);
delimage(gameoverimg); //釋放內存
getch();
getch();
}
//主函數(shù)
int main()
{
initgraph(900, 600, INIT_RENDERMANUAL); //初始化圖形界面
setcaption("C++ EGE坦克大戰(zhàn)"); //設置窗口標題
initgamebegin(); //游戲開始界面
TankFriend tank_f; //我方坦克
TankEnemy tank_e_1(200, 40, 1); //敵方坦克 1
TankEnemy tank_e_2(720, 120, 2); //敵方坦克 2
TankEnemy tank_e_3(560, 120, 3); //敵方坦克 3
TankEnemy tank_e_4(80, 360, 4); //敵方坦克 4
//敵軍坦克數(shù)組
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; //判斷游戲結束狀態(tài)變量,默認失敗
bool basestat = false; //判斷基地老鷹的狀態(tài),為真則游戲失敗
//游戲循環(huán)
while (true)
{
cleardevice(); //清屏
//三條生命 被消滅三次時結束游戲
if (tank_f.getFridienumfun() < 3)
tank_f.move(listmap);
else break;
//敵軍坦克數(shù)組循環(huán)
for (int i = 0; i < N; i++)
{
if(Etankarr[i].getEntadist() == true) //坦克必須存活時才會調用移動函數(shù)
Etankarr[i].move(listmap); //敵方坦克
else
{
switch (Endienum)
{
case 3: //坦克死亡時,且敵軍總被消滅次數(shù)為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則游戲按失敗break
if (Endienum > 10) //消滅敵軍達10則游戲勝利
{
gameoverstat = true;
break;
}
delay_fps(62);
}
//根據(jù)游戲結束狀態(tài),調用結束函數(shù)
gameoverstat ? gameovertrue(): gameoverfalse(); //游戲結束
return 0;
}
//設置圖片寬高全局函數(shù)
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); //創(chuàng)建一個新的圖像對象,這個新的圖像對象的寬高為
//要重新設置的圖像的寬高
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); //使用完畢將釋放掉
}
不足之處:
參照標準的坦克大戰(zhàn),子彈在攻擊磚塊時,如果子彈正好打中兩個磚塊,則兩個磚塊同時被消滅,這個效果我在程序中做不出來。只能是用一個一個地消滅代替了。
在按下鍵鍵值不是wasdj時和坦克碰到墻壁時坦克會閃的問題,也暫時沒有找到解決辦法。
因為初學C++,所以我在類和對象的使用上面還有著很多很多的缺陷和不規(guī)范的地方。
還有關于地圖的問題,因為我沒有經驗,所以不知道該怎么簡便地創(chuàng)造一個游戲地圖,在剛開始的時候還在為用什么實現(xiàn)地圖而猶豫過,最后還是選擇了list容器逐個將地圖元素塞進去,因為考慮到list容器插入和刪除數(shù)據(jù)很快。
我知道在程序中很多地方我都寫的極為地不合理,以至于程序運行效率非常低(從我的CPU占用看出來的),但是我會繼續(xù)努力,繼續(xù)學習,爭取早日解決這些問題。
歡迎大家提出批評和建議。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
C# interface與delegate效能比較的深入解析
本篇文章是對C#中interface與delegate的效能比較進行了詳細的分析介紹,需要的朋友參考下2013-05-05

