“坦克大战”小游戏(C语言)源代码及其详解注释

本文介绍了使用C语言编写的一款“坦克大战”小游戏,包括游戏运行截图。文章详细剖析了游戏开发中遇到的问题,如敌人创建与移动的逻辑、子弹碰撞的处理、坦克射击方向不一致等,并提出了相应的解决方案,如调整函数调用顺序、使用指针处理参数等。
摘要由CSDN通过智能技术生成

“坦克大战”小游戏(C语言)源代码及其详解注释

 

 

运行实现之后的图片结果如下:

 

笔记
1.敌人必须先移动再创造,不然会出现尸体复活。
  原因:敌人死亡之后,中心点是无法再次定位的,敌人刷新的那一帧会出现两个中心点。
  解决方法:再主函数里把敌人移动的函数放在创造敌人的函数之前。


2.敌人子弹和玩家子弹相撞时,必定只会有一方的子弹消失,看概率。
  原因:两方子弹相撞只会有一方的子弹先到达另一方的前面然后消失,跟子弹移动速度(停留时间)有关。
  解决方法:把子弹的消失判定点往前加一个点来判断是否是敌方的子弹(暂时不解决)


3.敌人发射子弹时,有时候会出现发射子弹的方向和敌人的方向不一致。
  原因:敌人转向时是先改变方向,下一次移动时再转过去,子弹发射的时间被卡在了两者之间。
  解决方法:将发射子弹写在移动的里面,这样会改变敌人射击的频率,移动的条件符合,再判断射击条件,两者都符合才会射击。(不优)
            添加一个坦克属性来设置坦克预备转向。


4.敌人的子弹在接近玩家附近一格时,玩家向反方向移动会消除子弹,反之相同。(触发几率很小)
  原因:玩家移动的时候会把之前的所在的一条三个格子全都清零。
  解决方法:暂无


5.当玩家的前方是敌方坦克时,无法发射子弹,反之相同。不能贴脸射击。
  原因:发射子弹的条件是坦克的前方无阻挡物,才会生成子弹,在子弹生成之后才会飞行和击毁。
    解决方法:在发射子弹时添加条件判断。(不优,感觉会影响游戏体验)


6.敌人A和B的行动模式是一样的,可以把他们的移动写在一个函数里,但是运行的时候会出错只有一个坦克会动。
    原因:函数传入的参数是在函数里改变了不会影响外面的参数,这需要用到指针。
    解决方法:把所有的坦克参数全都变成指针类型?(太复杂了)


7.敌人坦克在移动的时候会被自己的子弹挡住然后转向,玩家也是(几率很小,不过不影响游戏)

#pragma warning(disable:4996)
#include<stdio.h>
#include<iostream>
#include<conio.h>
#include<time.h>
#include<windows.h>
#include<graphics.h>
#define ROW 48

int map[ROW][ROW];//正方形的地图
int refresh;//记录当前刷新的次数
int FlyBullet_P_C, FlyBullet_E_C;//控制玩家和敌人子弹的飞行速度
struct Tank{//坦克的参数
	int x;//横向坐标
	int y;//纵向坐标
	int dir;//方向
	int rdir;//预备转向
	int dirt;//记录转向的时间
	int dirc;//控制转向频率
	int life;//坦克的生命
	int maxl;//坦克最大生命值
	int dietime;//坦克的死亡时间
	int str;//子弹的伤害
	int mt;//记录移动时间
	int mc; //控制移动速度
	int st;//记录射击时间
	int sc;//控制射速
	int score;//击败敌人的得分/玩家积累的分数
	int shape[3][3];//坦克的外形
} player, enemyA, enemyB, enemyC, enemyD, enemyE;//创建玩家敌人
int Player[3][3]{ {0,2,0},
				  {2,4,2},
				  {2,2,2} };//玩家的坦克
int empty[3][3];//空数组用于转向
struct CreatePoint {//敌人的刷新点
	int x;//刷新点横向坐标
	int y;//纵向坐标
}cp[5];
int propbox;//道具编号;
int propt, propc;//记录,控制道具刷新时间
int propflag;//判断场上是否有道具

//游戏开始时的初始化
void GameStart() {
	initgraph(640, 480);//窗口大小
	setbkcolor(WHITE);//背景颜色
	memset(map, 0, sizeof(map));//初始化数组为0
	for (int i = 0; i < ROW; i++) map[0][i] = map[ROW - 1][i] = 1;
	for (int i = 1; i < ROW - 1; i++) map[i][0] = map[i][ROW - 1] = 1;
	for (int y = 0; y < ROW; y++) {//y轴向下
		for (int x = 0; x < ROW; x++) {//x轴向右
			if (map[y][x]) {
				setlinecolor(BLACK);
				setfillcolor(RGB(213, 222, 217));
				fillrectangle(x * 10, y * 10 + 10, x * 10 + 10, y * 10);
			}
		}
	}
	refresh = 0;
	map[45][23] = 4;//玩家的出生点
	map[44][23] = map[46][23] = map[45][22] = map[45][24] = map[46][22] = map[46][24] = 2;
	player.life = 3;
	player.score = 0;
	player.dir = 1;
	player.str = 1;
	player.mc = 3;
	player.sc = 10;
	player.maxl = 3;
	FlyBullet_P_C = 1;
	FlyBullet_E_C = 3;
	enemyA.life = enemyB.life = enemyC.life = enemyD.life = enemyE.life = -1;
	enemyA.dir = enemyB.dir = enemyC.dir = enemyD.dir = enemyE.dir = 2;
	enemyA.rdir = enemyB.rdir = enemyC.rdir = enemyD.rdir = enemyE.rdir = 2;
	int Enemy[3][3]{ {15,15,0},
					 {0,20,15},
					 {15,15,0} };//敌人的坦克
	for (int i = 0; i < 3; i++) {
		for (int j = 0; j < 3; j++) {
			if (Enemy[i][j]) {
				enemyA.shape[i][j] = Enemy[i][j];//敌人A  中心为20 外壳为15
				enemyB.shape[i][j] = Enemy[i][j] + 1;//敌人B  中心为21 外壳为16
				enemyC.shape[i][j] = Enemy[i][j] + 2;//敌人C  中心为22 外壳为17
				enemyD.shape[i][j] = Enemy[i][j] + 3;//敌人D  中心为23 外壳为18
				enemyE.shape[i][j] = Enemy[i][j] + 4;//敌人E  中心为24 外壳为19
			}
		}
	}
	//地图地形
	for (int i = 0; i < 5; i++) map[10][10 + i] = map[37][10 + i] = map[10][37 - i] = map[37][37 - i] = 1;
	for (int i = 0; i < 4; i++) map[11 + i][10] = map[36 - i][10] = map[11 + i][37] = map[36 - i][37] = 1;
	map[23][23] = map[23][24] = map[24][23] = map[24][24] = 1;
	//初始化敌人的刷新点
	cp[0].x = 2;
	cp[0].y = 2;
	cp[1].x = 24;
	cp[1].y = 2;
	cp[2].x = 45;
	cp[2].y = 2;
	cp[3].x = 2;
	cp[3].y = 23;
	cp[4].x = 45;
	cp[4].y = 23;
	//道具的刷新率
	propt = 0;
	propc = 300;
	propflag = -1;
}

//绘制地图
void DrawMap() {
	for (int y = 1; y < ROW-1; y++) {//y轴向下
		for (int x = 1; x < ROW-1; x++) {//x轴向右
			switch (map[y][x]) {
			case 0:break;
			case 1:
				setlinecolor(BLACK);
				setlinestyle(NULL, 1);
				setfillcolor(RGB(213,222,217));//灰色
				fillrectangle(x * 10, y * 10 + 10, x * 10 + 10, y * 10);
				break;//墙壁
			case 2://玩家坦克的外壳
			case 4://玩家的中心点
				setlinecolor(BLACK);
				setlinestyle(NULL, 1);
				setfillcolor(RGB(0, 140, 158));//青蓝色
				fillrectangle(x * 10, y * 10 + 10, x * 10 + 10, y * 10);
				break;
			case 19://敌人E的外壳
				setlinecolor(BLACK);
				setlinestyle(NULL, 1);
				setfillcolor(RED);
				fillrectangle(x * 10, y * 10 + 10, x * 10 + 10, y * 10);
				break;
			case 18://敌人D的外壳
			case 17://敌人C的外壳
				setlinecolor(BLACK);
				setlinestyle(NULL, 1);
				setfillcolor(RGB(89, 79, 79));//褐色
				fillrectangle(x * 10, y * 10 + 10, x * 10 + 10, y * 10);
				break;
			case 16://敌人B的外壳
			case 15://敌人A的外壳
				setlinecolor(BLACK);
				setlinestyle(NULL, 1);
				setfillcolor(RGB(85, 98, 112));//深灰色
				fillrectangle(x * 10, y * 10 + 10, x * 10 + 10, y * 10);
				break;
			case 24://敌人E的中心点
				setlinecolor(BLACK);
				setlinestyle(NULL, 2);
				switch (enemyE.life) {
				case 0:setfillcolor(RGB(255, 255, 255)); break;
				case 1:setfillcolor(RGB(255, 0, 0)); break;
				case 2:setfillcolor(RGB(255, 165, 0)); break;
				case 3:setfillcolor(RGB(255, 255, 0)); break;
				case 4:setfillcolor(RGB(0, 255, 0)); break;
				case 5:setfillcolor(RGB(0, 255, 255)); break;
				case 6:setfillcolor(RGB(0, 0, 255)); break;
				case 7:setfillcolor(RGB(160, 32, 240)); break;
				}
		       	【】fillrectangle(x * 10, y * 10 + 10, x * 10 + 10, y * 10);//边框填充矩形
				break;
			case 23://敌人D的中心点
				setlinecolor(BLACK);
				setlinestyle(NULL, 2);
				switch (enemyD.life) {
				case 0:setfillcolor(RGB(255, 255, 255)); break;
				case 1:setfillcolor(RGB(255, 0, 0)); break;
				case 2:setfillcolor(RGB(255, 165, 0)); break;
				case 3:setfillcolor(RGB(255, 255, 0)); break;
				case 4:setfillcolor(RGB(0, 255, 0)); break;
				case 5:setfillcolor(RGB(0, 255, 255)); break;
				case 6:setfillcolor(RGB(0, 0, 255)); break;
				case 7:setfillcolor(RGB(160, 32, 240)); break;
				}
				fillrectangle(x * 10, y * 10 + 10, x * 10 + 10, y * 10);
				break;
			case 22://敌人C的中心点
				setlinecolor(BLACK);
				setlinestyle(NULL, 2);
				switch (enemyC.life) {
				case 0:setfillcolor(RGB(255, 255, 255)); break;
				case 1:setfillcolor(RGB(255, 0, 0)); break;
				case 2:setfillcolor(RGB(255, 165, 0)); break;
				case 3:setfillcolor(RGB(255, 255, 0)); break;
				case 4:setfillcolor(RGB(0, 255, 0)); break;
				case 5:setfillcolor(RGB(0, 255, 255)); break;
				case 6:setfillcolor(RGB(0, 0, 255)); break;
				case 7:setfillcolor(RGB(160, 32, 240)); break;
				}
				fillrectangle(x * 10, y * 10 + 10, x * 10 + 10, y * 10);
				break;
			case 21://敌人B的中心点
				setlinecolor(BLACK);
				setlinestyle(NULL, 2);
				switch (enemyB.life) {
				case 0:setfillcolor(RGB(255, 255, 255)); break;
				case 1:setfillcolor(RGB(255, 0, 0)); break;
				case 2:setfillcolor(RGB(255, 165, 0)); break;
				case 3:setfillcolor(RGB(255, 255, 0)); break;
				case 4:setfillcolor(RGB(0, 255, 0)); break;
				case 5:setfillcolor(RGB(0, 255, 255)); break;
				case 6:setfillcolor(RGB(0, 0, 255)); break;
				case 7:setfillcolor(RGB(160, 32, 240)); break;
				}
				fillrectangle(x * 10, y * 10 + 10, x * 10 + 10, y * 10);
				break;
			case 20://敌人A的中心点		
				setlinecolor(BLACK);
				setlinestyle(NULL, 2);
				switch (enemyA.life) {
				case 0:setfillcolor(RGB(255, 255, 255)); break;//黑
				case 1:setfillcolor(RGB(255, 0, 0)); break;//红
				case 2:setfillcolor(RGB(255, 165, 0)); break;//橙
				case 3:setfillcolor(RGB(255, 255, 0)); break;//黄
				case 4:setfillcolor(RGB(0, 255, 0)); break;//绿
				case 5:setfillcolor(RGB(0, 255, 255)); break;//青
				case 6:setfillcolor(RGB(0, 0, 255)); break;//蓝
				case 7:setfillcolor(RGB(160, 32, 240)); break;//紫
				}
				fillrectangle(x * 10, y * 10 + 10, x * 10 + 10, y * 10);
				break;
			case 5://玩家向上的子弹
			case 6://玩家向右的子弹
			case 7://玩家向下的子弹
			case 8://玩家向左的子弹
				setlinecolor(BLACK);
				setlinestyle(NULL, 1);
				circle(x * 10 + 5, y * 10 + 5, 3);//空心圆 玩家的子弹
				break;
			case 11://敌人向上的子弹
			case 12://敌人向右的子弹
			case 13://敌人向下的子弹
			case 14://敌人向左的子弹
				setlinecolor(BLACK);
				setlinestyle(NULL, 1);
				setfillcolor(BLACK);
				fillcircle(x * 10 + 5, y * 10 + 5, 3);//黑色实心圆 敌人的子弹
				break;
			case 25://装道具的盒子
				switch (propbox) {
				case 1:
					setlinecolor(BLACK);
					setlinestyle(NULL, 2);
					setfillcolor(RED);
					fillcircle(x * 10 + 5, y * 10 + 5, 5);
					break;
				case 2:
					setlinecolor(BLACK);
					setlinestyle(NULL, 2);
					setfillcolor(RGB(242, 196, 90));
					fillcircle(x * 10 + 5, y * 10 + 5, 5);
					break;
				case 3:
					setlinecolor(BLACK);
					setlinestyle(NULL, 2);
					setfillcolor(RGB(77, 188, 233));
					fillcircle(x * 10 + 5, y * 10 + 5, 5);
					break;
				case 4:
					setlinecolor(BLACK);
					setlinestyle(NULL, 2);
					setfillcolor(RGB(42, 4, 74));
					fillcircle(x * 10 + 5, y * 10 + 5, 5);
					break;
				case 5:
					setlinecolor(BLACK);
					setlinestyle(NULL, 5);
					setfillcolor(RGB(254, 67, 101));
					fillrectangle(x * 10, y * 10 + 10, x * 10 + 10, y * 10);
					break;
				}
				break;
			case 10:
				setfillcolor(RGB(250, 105, 0));
				setlinecolor(RGB(204, 51, 63));
				setlinestyle(NULL, 2);
				POINT pts[] = { {x * 10 - 10, y * 10 - 8}, {x * 10, y * 10}, {x * 10 - 10, y * 10 + 5},{x * 10 + 1,y * 10 + 7},{x * 10 - 5,y * 10 + 11},{x * 10 + 4,y * 10 + 12},{x * 10 + 3,y * 10 + 18},{x * 10 + 8,y * 10 + 11},{x * 10 + 12,y * 10 + 20},{x * 10 + 10,y * 10 + 9},{x * 10 + 20,y * 10 + 11},{x * 10 + 13,y * 10 + 5},{x * 10 + 20,y * 10 - 4},{x * 10 + 10,y * 10 + 2},{x * 10 + 10,y * 10 - 10},{x * 10 + 7,y * 10 - 2} };
				fillpolygon(pts, 16);
				break;//爆炸效果
			}
		}
	}
}

//右半部分显示游戏状态
void GameState() {
	//刷新的帧数
	char s[10];
	settextcolor(BLUE);
	sprintf(s, "%d", refresh);
	outtextxy(490, 460, s);

	outtextxy(490, 0, "当前生命值:");
	//显示生命值
	if (player.life > 0) {
		setfillcolor(RGB(254, 67, 101));
	}
	else {
		setfillcolor(BLACK);
	}
	setlinecolor(RED);
	setlinestyle(NULL, 2);
	//第一颗心
	POINT pts[] = { {490, 30}, {498, 22}, {505, 30},{512, 22},{520, 30},{505, 45} };
	fillpolygon(pts, 6);
	if (player.life > 1) {
		setfillcolor(RGB(254, 67, 101));
	}
	else {
		setfillcolor(BLACK);
	}
	//第二颗心
	POINT pts1[] = { {530, 30}, {538, 22}, {545, 30},{552, 22},{560, 30},{545, 45} };
	fillpolygon(pts1, 6);
	if (player.life > 2) {
		setfillcolor(RGB(254, 67, 101));
	}
	else {
		setfillcolor(BLACK);
	}
	//第三颗心
	POINT pts2[] = { {570, 30}, {578, 22}, {585, 30},{592, 22},{600, 30},{585, 45} };
	fillpolygon(pts2, 6);
	if (player.maxl > 3) {
		setlinecolor(RED);
	}
	else {
		setlinecolor(BLACK);
	}
	if (player.life > 3) {
		setfillcolor(RGB(254, 67, 101));
	}
	else {
		setfillcolor(BLACK);
	}
	//第四颗心
	POINT pts3[] = { {510, 55}, {518, 47}, {525, 55},{532, 47},{540, 55},{525, 70} };
	fillpolygon(pts3, 6);
	if (player.maxl > 4) {
		setlinecolor(RED);
	}
	else {
		setlinecolor(BLACK);
	}
	if (player.life > 4) {
		setfillcolor(RGB(254, 67, 101));
	}
	else {
		setfillcolor(BLACK);
	}
	//第五颗心
	POINT pts4[] = { {550, 55}, {558, 47}, {565, 55},{572, 47},{580, 55},{565, 70} };
	fillpolygon(pts4, 6);

	//伤害面板
	outtextxy(490, 75, "伤害:");
	setlinecolor(RGB(255, 130, 58));
	setlinestyle(NULL, 2);
	if (player.str > 1) {
		setfillcolor(RGB(242, 196, 90));
	}
	else {
		setfillcolor(BLACK);
	}
	fillrectangle(545, 75, 570, 92);
	if (player.str > 2) {
		setfillcolor(RGB(242, 196, 90));
	}
	else {
		setfillcolor(BLACK);
	}
	fillrectangle(575, 75, 600, 92);
	if (player.str > 3) {
		setfillcolor(RGB(242, 196, 90));
	}
	else {
		setfillcolor(BLACK);
	}
	fillrectangle(605, 75, 630, 92);
	//速度面板
	outtextxy(490, 100, "速度:");
	setlinecolor(RGB(38, 173, 228));
	setlinestyle(NULL, 2);
	if (player.mc < 3)
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值