(C语言)球球大作战

  前言:

这款简易版的球球大作战是一款单人游戏,玩家需要控制一个小球在地图上移动,吞噬其他小球来增大自己的体积。本游戏使用C语言和easyx图形库编写,旨在帮助初学者了解游戏开发的基本概念和技巧。

在开始编写代码之前,我们需要先了解一下游戏的基本规则和功能:

游戏界面:游戏界面是一个矩形区域,玩家可以在这个区域内控制球的移动。

玩家小球:玩家控制的小球可以在游戏界面内自由移动,按下空格键可以加速。

其他小球:其他小球又分为食物小球,和ai控制的小球

体积:玩家每吃一个其他小球体积就会增大一点,ai小球也可以通过吃食物和玩家小球增大体积。

玩家被吃:当玩家小球被ai小球吃了,玩家小球就会回到初始点,体积也会变成初始大小。

ai小球的追击和逃跑:当玩家小球与ai小球靠近时,ai小球会根据自身体积的大小选择追击玩家小球或者逃跑。

接下来,我们将通过以下几个步骤来实现这个游戏:

初始化游戏界面和小球的信息。

处理键盘输入,实现玩家小球的移动和加速。

生成足够数量的食物小球。

生成ai小球,并控制其移动。

检测小球之间的吞噬关系,增加相应的体积。

通过学习这个游戏的开发过程,初学者将能够掌握C语言编程和easyx图形库的基本技巧。

1. 小球的要素

在此游戏中一个小球的要素无非就是小球所在的位置(坐标)、小球的半径、以及小球的颜色,这里我们可以用一个结构体数组来存放这些要素,以方便初始化小球的信息。

struct Ball
{
	int x;
	int y;
	float r;
	DWORD color;
};

2. 初始化小球的信息

将玩家小球的初始位置设置在窗口的中间,半径大小为10。食物小球和ai小球的位置则通过rand函数、srand函数和time函数生成的随机数,随机分布在地图的各个位置,食物小球半径为1-5,ai小球的半径10.其中在这里使用了RGB随机生成一个颜色,使每个食物小球的颜色都不尽相同。

RGB色彩模式是一种工业标准,它通过红(R)、绿(G)、蓝(B)三个颜色通道的组合来表示不同的颜色。每个通道通常分配一个0到255之间的数值,其中0表示该颜色通道没有亮度,255表示该颜色通道的最大亮度。通过调整这三个通道的值,可以生成几乎所有人类视觉系统能够感知的颜色。例如:

  • 橙色可以通过RGB值(255, 128, 0)来表示。
  • 黄色的RGB值为(255, 255, 0)。
  • 绿色的RGB值是(0, 255, 0)。
  • 蓝色的RGB值为(0, 0, 255)。
  • 紫色可以通过RGB值(170, 0, 255)来表示。
  • 黑色的RGB值为(0, 0, 0)。
  • 白色的RGB值为(255, 255, 255)。
  • 灰色的RGB值可以是(128, 128, 128),其中三个值相等即可,值越接近255,颜色就越接近白色,反之亦然。
void Inset()
{
    //玩家小球
	srand((unsigned)time(NULL));
	player.x = Wide / 2;
	player.y = Hight / 2;
	player.r = 10;
    //食物小球
	for (int i = 0; i < Food_num; i++)
	{
		Food[i].x = rand() % Wide_map;
		Food[i].y = rand() % Hight_map;
		Food[i].r = rand() % 5 + 1;
		Food[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
	}
    //ai小球
	for (int i = 0; i < Enemy_num; i++)
	{
		Enemy[i].x = rand() % Wide_map;
		Enemy[i].y = rand() % Hight_map;
		Enemy[i].r = 10;
		Enemy[i].color = RGB(0,255,0);
	}

}

3. 玩家操作小球

在这里需要用到GetAsyncKeyState(vk virtual key)函数获取异步按键状态,其中vk virtual key是虚拟键值,如果接受到这个虚拟键值,它会返回真。VK_UP、VK_DOWN、VK_LEFT、VK_RIGHT、0x20分别是上箭头键、下箭头键、左箭头键、右箭头键、空格键的虚拟键值。

void Player_move()
{
	if (GetAsyncKeyState(VK_UP))
	{
		if (player.y > 0)
		{
			player.y -= player_sleep;
		}
	}
	if (GetAsyncKeyState(VK_DOWN))
	{
		if (player.y < Hight_map)
		player.y += player_sleep;
	}
	if (GetAsyncKeyState(VK_LEFT))
	{
		if (player.x > 0)
		player.x -= player_sleep;
	}
	if (GetAsyncKeyState(VK_RIGHT))
	{
		if (player.x < Wide_map)
		player.x += player_sleep;
	}
	if (GetAsyncKeyState(0x20))
	{
		player_sleep = l + 5;
	}
	else
	{
		player_sleep = l;
	}
}

4. 显示出小球

在此游戏中,小球是一个实心圆,在easyx图形库中提供了一个画实心圆的函数—solidcircle函数,通过它我们就可以在窗口中显示小球了,但显示出的小球默认颜色为白色,为了区分不同的小球,我们还需使用setfillcolor函数来改变小球的颜色。因为显示的函数、玩家操作小球的函数等函数都是放在同一个while循环重复执行的,这样就会重复显示小球,所以我们还需要用到一个清屏函数cleardevice。为了使窗口更好看可以使用setbkcolor函数修改窗口的背景颜色,以及使用line函数在窗口中画一些线,函数setlinecolor可以改变线的颜色。

void Show()
{
	
	//设置地图
	SetWorkingImage(&map);
	//清屏
	cleardevice();
	//背景颜色
	setbkcolor(WHITE);
	//划线颜色
	setlinecolor(RGB(230,231,239));
	//划线
	for (int i = 0; i < Wide_map; i += 10)
	{
		line(i, 0, i, Hight_map);
	}
	for (int i = 0; i < Hight_map; i += 10)
	{
		line(0, i, Wide_map, i);
	}
	//食物
	for (int i = 0; i < Food_num; i++)
	{
		setfillcolor(Food[i].color);
		solidcircle(Food[i].x, Food[i].y, Food[i].r);
	}
	//敌人
	for (int i = 0; i < Enemy_num; i++)
	{
		setfillcolor(Enemy[i].color);
		solidcircle(Enemy[i].x, Enemy[i].y, Enemy[i].r);
	}
	//玩家
	setfillcolor(RED);
	solidcircle(player.x, player.y, player.r);
	SetWorkingImage();

	int x = player.x - (Wide / 2);
	int y = player.y - (Hight / 2);
	//防止窗口越界
	if (x < 0)
	{
		x = 0;
	}
	if (y < 0)
	{
		y = 0;
	}
	if (x > Wide_map - Wide)
	{
		x = Wide_map - Wide;
	}
	if (y > Hight_map - Hight)
	{
		y = Hight_map - Hight;
	}
	//把map输出到窗口上
	putimage(0, 0, Wide, Hight, &map, x, y);
}

5. 生成地图

可以使用IMAGE map(Wide_map, Hight_map) 创建一个图像映射,其中 Wide_map 代表图像的宽度,而 Hight_map 代表图像的高度。然后使用SetWorkingImage(&map),将map的地址作为参数传递给SetWorkingImage函数。这个函数的作用是将map作为当前操作的对象,以便在后续的图像处理过程中使用。最后使用putimage(0, 0, Wide, Hight, &map, x, y) 将地址绘制到窗口上,其中要让玩家小球始终出现在窗口的中央位置,那么其中的x=player.x - (Wide / 2);y=player.y - (Hight / 2);但是单单这样写就会出现窗口越界的情况,所以我们还需要限制x和y的范围:

//防止窗口越界
if (x < 0)
{
	x = 0;
}
if (y < 0)
{
	y = 0;
}
if (x > Wide_map - Wide)
{
	x = Wide_map - Wide;
}
if (y > Hight_map - Hight)
{
	y = Hight_map - Hight;
}

putimage(0, 0, Wide, Hight, &map, x, y) 这个函数调用是用于在屏幕上的特定位置绘制或显示一个图像。下面是对这个函数调用中各个参数的具体解释:

  1. (0, 0):这是图像要绘制的目标位置的左上角坐标,即x=0和y=0,通常表示屏幕的左上角。

  2. Wide:这个参数指定了要绘制的图像的宽度。

  3. Hight:这个参数指定了要绘制的图像的高度。

  4. &map:这是一个指向图像内存地址的指针,该图像将被绘制到屏幕上。在这个上下文中,map可能是一个包含了图像数据的数据结构或数组。

  5. x:这个参数通常指定了要开始绘制图像的起始点的x坐标(在图像数据中)。

  6. y:这个参数通常指定了要开始绘制图像的起始点的y坐标(在图像数据中)。

6. ai小球的移动

随机生成0-3的数字分别代表ai小球上下左右的移动,这样小球就会自由移动了。当玩家小球与ai小球靠近时,ai小球会追击或者逃跑,这里我们需要先计算小球的之间的距离,小球之间的距离就是两小球的圆心坐标的x相减的平方加上y相减的平方再开根号。开根号的函数为sqrt,它的头文件是<math.h>。

//距离
int Distance(int x, int y, int x1, int y1)
{
	return sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
}

然后判断两小球的距离是否小于50个像素点,即判断是否小于玩家小球的半径 + ai小球的半径 + 50。判断完后比较两小球的半径大小,如果ai小球的半径大于玩家小球的半径,那么ai小球就要追击玩家小球,即ai小球的坐标需要靠近玩家小球的坐标,就是如果ai小球的x大于玩家小球的x那么ai小球的x就减小,同理可得剩下的操作。

void Enemy_move()
{
	srand((unsigned)time(NULL));
	for (int i = 0; i < Enemy_num; i++)
	{
		int direction = rand() % 4;

		if (Distance(player.x, player.y, Enemy[i].x, Enemy[i].y) > player.r + Enemy[i].r + 50)
		{
			if (direction == 0)
			{
				if (Enemy[i].y > 0)//防止小球越界的判断语句
				{
					Enemy[i].y -= enemy_sleep;
				}
			}
			if (direction == 1)
			{
				if (Enemy[i].y < Hight_map)
					Enemy[i].y += enemy_sleep;
			}
			if (direction == 2)
			{
				if (Enemy[i].x > 0)
					Enemy[i].x -= enemy_sleep;
			}
			if (direction == 3)
			{
				if (Enemy[i].x < Wide_map)
					Enemy[i].x += enemy_sleep;
			}
		}
		//敌人追击玩家
		if (Distance(player.x, player.y, Enemy[i].x, Enemy[i].y) < player.r + Enemy[i].r + 50)
		{
			if (Enemy[i].r > player.r)
			{
				if (Enemy[i].x < player.x)
				{
					if (Enemy[i].x < Wide_map)
					{
						Enemy[i].x += enemy_sleep;
					}
				}
				if (Enemy[i].x > player.x)
				{
					if (Enemy[i].x > 0)
					{
						Enemy[i].x -= enemy_sleep;
					}
				}
				if (Enemy[i].y < player.y)
				{
					if (Enemy[i].y < Hight_map)
					{
						Enemy[i].y += enemy_sleep;
					}
				}
				if (Enemy[i].y > player.y)
				{
					if (Enemy[i].y > 0)
					{
						Enemy[i].y -= enemy_sleep;
					}
				}
			}
			//敌人逃跑
			else
			{
				if (Enemy[i].x < player.x)
				{
					if (Enemy[i].x > 0)
					{
						Enemy[i].x -= enemy_sleep;
					}
				}
				if (Enemy[i].x > player.x)
				{
					if (Enemy[i].x < Wide_map)
					{
						Enemy[i].x += enemy_sleep;
					}
				}
				if (Enemy[i].y < player.y)
				{
					if (Enemy[i].y > 0)
					{
						Enemy[i].y -= enemy_sleep;
					}
				}
				if (Enemy[i].y > player.y)
				{
					if (Enemy[i].y < Hight_map)
					{
						Enemy[i].y += enemy_sleep;
					}
				}
			}
		}
	}
}

7. 小球之间的吞噬关系

玩家小球与ai小球、ai小球与ai小球:

当两小球的圆心小于最大的那个圆的半径时,小的那个球就会被吃掉。吃点就是那个小球重新找个位置生成。吃完后,吃的那个小球半径增加被吃小球半径的十分之一。

ai小球与食物小球、玩家小球与食物小球:同上。

void EatFood()
{
	for (int i = 0; i < Food_num; i++)
	{
		//玩家吃食物
		if (Distance(player.x, player.y, Food[i].x, Food[i].y) < player.r)
		{
			player.r += Food[i].r / 100;
			Food[i].x = rand() % Wide_map;
			Food[i].y = rand() % Hight_map;
			Food[i].r = rand() % 5 + 1;
			Food[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
		}
		
	}
	for (int j = 0; j < Enemy_num; j++)
	{
		//敌人吃食物
		for (int i = 0; i < Food_num; i++)
		{
			if (Distance(Enemy[j].x, Enemy[j].y, Food[i].x, Food[i].y) < Enemy[j].r)
			{
				Enemy[j].r += Food[i].r / 50;
				Food[i].x = rand() % Wide_map;
				Food[i].y = rand() % Hight_map;
				Food[i].r = rand() % 5 + 1;
				Food[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
			}
		}
		//敌人吃敌人
		for (int i = 0; i < Enemy_num; i++)
		{
			if (Distance(Enemy[j].x, Enemy[j].y, Enemy[i].x, Enemy[i].y) < Enemy[j].r&& Enemy[j].r > Enemy[i].r)
			{
				Enemy[j].r += Enemy[i].r / 10;
				Enemy[i].x = rand() % Wide_map;
				Enemy[i].y = rand() % Hight_map;
				Enemy[i].r = 10;
					Enemy[i].color = RGB(0, 255, 0);
			}
			if (Distance(Enemy[j].x, Enemy[j].y, Enemy[i].x, Enemy[i].y) < Enemy[i].r && Enemy[j].r < Enemy[i].r)
			{
				Enemy[i].r += Enemy[j].r / 10;
				Enemy[j].x = rand() % Wide_map;
				Enemy[j].y = rand() % Hight_map;
				Enemy[j].r = 10;
				Enemy[j].color = RGB(0, 255, 0);
			}
		}
		if (Distance(player.x, player.y, Enemy[j].x, Enemy[j].y) < player.r)
		{
			//玩家吃敌人
			if (player.r > Enemy[j].r)
			{
				player.r += Enemy[j].r / 10;
				Enemy[j].x = rand() % Wide_map;
				Enemy[j].y = rand() % Hight_map;
				Enemy[j].r = 10;
				Enemy[j].color = RGB(0, 255, 0);
			}
			//敌人吃玩家
			else
			{
				if (invincibility == 0)
				{
					Enemy[j].r += player.r / 10;
					player.x = Wide / 2;
					player.y = Hight / 2;
					player.r = 10;
					invincibility = 10;
				}
			}
		}
	}
}

最终效果:

球球大作战

源码:

#include<stdio.h>
#include<easyx.h>
#include<time.h>
#include<math.h>
#define Wide 1024
#define Hight 640
#define Wide_map (Wide*5)
#define Hight_map (Hight*5)
#define Food_num 1888
#define Enemy_num 888
//整个游戏地图
IMAGE map(Wide_map, Hight_map);
//复活时的无敌时间
int invincibility = 10; 
//玩家速度
int player_sleep = 5;
int l = 5;
int enemy_sleep = 5;
struct Ball
{
	int x;
	int y;
	float r;
	DWORD color;
};
struct Ball player;
struct Ball Food[Food_num];
struct Ball Enemy[Enemy_num];
//初始化球的数据
void Inset()
{
	srand((unsigned)time(NULL));
	player.x = Wide / 2;
	player.y = Hight / 2;
	player.r = 10;
	for (int i = 0; i < Food_num; i++)
	{
		Food[i].x = rand() % Wide_map;
		Food[i].y = rand() % Hight_map;
		Food[i].r = rand() % 5 + 1;
		Food[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
	}
	for (int i = 0; i < Enemy_num; i++)
	{
		Enemy[i].x = rand() % Wide_map;
		Enemy[i].y = rand() % Hight_map;
		Enemy[i].r = 10;
		Enemy[i].color = RGB(0,255,0);
	}

}
//玩家操作
void Player_move()
{
	if (GetAsyncKeyState(VK_UP))
	{
		if (player.y > 0)
		{
			player.y -= player_sleep;
		}
	}
	if (GetAsyncKeyState(VK_DOWN))
	{
		if (player.y < Hight_map)
		player.y += player_sleep;
	}
	if (GetAsyncKeyState(VK_LEFT))
	{
		if (player.x > 0)
		player.x -= player_sleep;
	}
	if (GetAsyncKeyState(VK_RIGHT))
	{
		if (player.x < Wide_map)
		player.x += player_sleep;
	}
	if (GetAsyncKeyState(0x20))
	{
		player_sleep = l + 5;
	}
	else
	{
		player_sleep = l;
	}
}
//距离
int Distance(int x, int y, int x1, int y1)
{
	return sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
}
//敌人移动
void Enemy_move()
{
	srand((unsigned)time(NULL));
	for (int i = 0; i < Enemy_num; i++)
	{
		int direction = rand() % 400;

		if (Distance(player.x, player.y, Enemy[i].x, Enemy[i].y) > player.r + Enemy[i].r + 50)
		{
			if (direction < 100)
			{
				if (Enemy[i].y > 0)
				{
					Enemy[i].y -= enemy_sleep;
				}
			}
			if (direction < 200 && direction >= 100)
			{
				if (Enemy[i].y < Hight_map)
					Enemy[i].y += enemy_sleep;
			}
			if (direction < 300 && direction >= 200)
			{
				if (Enemy[i].x > 0)
					Enemy[i].x -= enemy_sleep;
			}
			if (direction <400 && direction >= 300)
			{
				if (Enemy[i].x < Wide_map)
					Enemy[i].x += enemy_sleep;
			}
		}
		//敌人追击玩家
		if (Distance(player.x, player.y, Enemy[i].x, Enemy[i].y) < player.r + Enemy[i].r + 50)
		{
			if (Enemy[i].r > player.r)
			{
				if (Enemy[i].x < player.x)
				{
					if (Enemy[i].x < Wide_map)
					{
						Enemy[i].x += enemy_sleep;
					}
				}
				if (Enemy[i].x > player.x)
				{
					if (Enemy[i].x > 0)
					{
						Enemy[i].x -= enemy_sleep;
					}
				}
				if (Enemy[i].y < player.y)
				{
					if (Enemy[i].y < Hight_map)
					{
						Enemy[i].y += enemy_sleep;
					}
				}
				if (Enemy[i].y > player.y)
				{
					if (Enemy[i].y > 0)
					{
						Enemy[i].y -= enemy_sleep;
					}
				}
			}
			//敌人逃跑
			else
			{
				if (Enemy[i].x < player.x)
				{
					if (Enemy[i].x > 0)
					{
						Enemy[i].x -= enemy_sleep;
					}
				}
				if (Enemy[i].x > player.x)
				{
					if (Enemy[i].x < Wide_map)
					{
						Enemy[i].x += enemy_sleep;
					}
				}
				if (Enemy[i].y < player.y)
				{
					if (Enemy[i].y > 0)
					{
						Enemy[i].y -= enemy_sleep;
					}
				}
				if (Enemy[i].y > player.y)
				{
					if (Enemy[i].y < Hight_map)
					{
						Enemy[i].y += enemy_sleep;
					}
				}
			}
		}
		//for (int j = 0; j < Enemy_num; j++)
		//{
		//	if (Distance(Enemy[j].x, Enemy[j].y, Enemy[i].x, Enemy[i].y) < Enemy[j].r + Enemy[i].r + 30)
		//	{
		//		//敌人追敌人
		//		if (Enemy[i].r > Enemy[j].r)
		//		{
		//			int sleep = rand() % 6;
		//			int enemy_sleep1;
		//			if (sleep > 2)
		//			{
		//				enemy_sleep1 = enemy_sleep;
		//			}
		//			else
		//			{
		//				enemy_sleep1 = enemy_sleep + 5;
		//			}
		//			if (Enemy[i].x < Enemy[j].x)
		//			{
		//				if (Enemy[i].x < Wide_map)
		//				{
		//					Enemy[i].x += enemy_sleep1;
		//				}
		//			}
		//			if (Enemy[i].x > Enemy[j].x)
		//			{
		//				if (Enemy[i].x > 0)
		//				{
		//					Enemy[i].x -= enemy_sleep1;
		//				}
		//			}
		//			if (Enemy[i].y < Enemy[j].y)
		//			{
		//				if (Enemy[i].y < Hight_map)
		//				{
		//					Enemy[i].y += enemy_sleep1;
		//				}
		//			}
		//			if (Enemy[i].y > Enemy[j].y)
		//			{
		//				if (Enemy[i].y > 0)
		//				{
		//					Enemy[i].y -= enemy_sleep1;
		//				}
		//			}
		//		}
		//		//逃跑
		//		else
		//		{
		//			int sleep = rand() % 6;
		//			int enemy_sleep1;
		//			if (sleep > 2)
		//			{
		//				enemy_sleep1 = enemy_sleep;
		//			}
		//			else
		//			{
		//				enemy_sleep1 = enemy_sleep + 5;
		//			}
		//			if (Enemy[i].x < Enemy[j].x)
		//			{
		//				if (Enemy[i].x > 0)
		//				{
		//					Enemy[i].x -= enemy_sleep1;
		//				}
		//			}
		//			if (Enemy[i].x > Enemy[j].x)
		//			{
		//				if (Enemy[i].x < Wide_map)
		//				{
		//					Enemy[i].x += enemy_sleep1;
		//				}
		//			}
		//			if (Enemy[i].y < Enemy[j].y)
		//			{
		//				if (Enemy[i].y > 0)
		//				{
		//					Enemy[i].y -= enemy_sleep1;
		//				}
		//			}
		//			if (Enemy[i].y > Enemy[j].y)
		//			{
		//				if (Enemy[i].y < Hight_map)
		//				{
		//					Enemy[i].y += enemy_sleep1;
		//				}
		//			}
		//		}
		//	}
		//}
	}
}

//吃食物
void EatFood()
{
	for (int i = 0; i < Food_num; i++)
	{
		//玩家吃食物
		if (Distance(player.x, player.y, Food[i].x, Food[i].y) < player.r)
		{
			player.r += Food[i].r / 100;
			Food[i].x = rand() % Wide_map;
			Food[i].y = rand() % Hight_map;
			Food[i].r = rand() % 5 + 1;
			Food[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
		}
		
	}
	for (int j = 0; j < Enemy_num; j++)
	{
		//敌人吃食物
		for (int i = 0; i < Food_num; i++)
		{
			if (Distance(Enemy[j].x, Enemy[j].y, Food[i].x, Food[i].y) < Enemy[j].r)
			{
				Enemy[j].r += Food[i].r / 50;
				Food[i].x = rand() % Wide_map;
				Food[i].y = rand() % Hight_map;
				Food[i].r = rand() % 5 + 1;
				Food[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
			}
		}
		//敌人吃敌人
		for (int i = 0; i < Enemy_num; i++)
		{
			if (Distance(Enemy[j].x, Enemy[j].y, Enemy[i].x, Enemy[i].y) < Enemy[j].r&& Enemy[j].r > Enemy[i].r)
			{
				Enemy[j].r += Enemy[i].r / 10;
				Enemy[i].x = rand() % Wide_map;
				Enemy[i].y = rand() % Hight_map;
				Enemy[i].r = 10;
					Enemy[i].color = RGB(0, 255, 0);
			}
			if (Distance(Enemy[j].x, Enemy[j].y, Enemy[i].x, Enemy[i].y) < Enemy[i].r && Enemy[j].r < Enemy[i].r)
			{
				Enemy[i].r += Enemy[j].r / 10;
				Enemy[j].x = rand() % Wide_map;
				Enemy[j].y = rand() % Hight_map;
				Enemy[j].r = 10;
				Enemy[j].color = RGB(0, 255, 0);
			}
		}
		if (Distance(player.x, player.y, Enemy[j].x, Enemy[j].y) < player.r)
		{
			//玩家吃敌人
			if (player.r > Enemy[j].r)
			{
				player.r += Enemy[j].r / 10;
				Enemy[j].x = rand() % Wide_map;
				Enemy[j].y = rand() % Hight_map;
				Enemy[j].r = 10;
				Enemy[j].color = RGB(0, 255, 0);
			}
			//敌人吃玩家
			else
			{
				if (invincibility == 0)
				{
					Enemy[j].r += player.r / 10;
					player.x = Wide / 2;
					player.y = Hight / 2;
					player.r = 10;
					invincibility = 10;
				}
			}
		}
	}
}
//显示
void Show()
{
	
	//设置地图
	SetWorkingImage(&map);
	//清屏
	cleardevice();
	//背景颜色
	setbkcolor(WHITE);
	//划线颜色
	setlinecolor(RGB(230,231,239));
	//划线
	for (int i = 0; i < Wide_map; i += 10)
	{
		line(i, 0, i, Hight_map);
	}
	for (int i = 0; i < Hight_map; i += 10)
	{
		line(0, i, Wide_map, i);
	}
	//食物
	for (int i = 0; i < Food_num; i++)
	{
		setfillcolor(Food[i].color);
		solidcircle(Food[i].x, Food[i].y, Food[i].r);
	}
	//敌人
	for (int i = 0; i < Enemy_num; i++)
	{
		setfillcolor(Enemy[i].color);
		solidcircle(Enemy[i].x, Enemy[i].y, Enemy[i].r);
	}
	//玩家
	setfillcolor(RED);
	solidcircle(player.x, player.y, player.r);
	SetWorkingImage();

	int x = player.x - (Wide / 2);
	int y = player.y - (Hight / 2);
	//防止窗口越界
	if (x < 0)
	{
		x = 0;
	}
	if (y < 0)
	{
		y = 0;
	}
	if (x > Wide_map - Wide)
	{
		x = Wide_map - Wide;
	}
	if (y > Hight_map - Hight)
	{
		y = Hight_map - Hight;
	}
	//把map输出到窗口上
	putimage(0, 0, Wide, Hight, &map, x, y);
}
int main()
{
	
	initgraph(Wide, Hight);
	Inset();
	//缓冲
	BeginBatchDraw();
	while (1)
	{
		if (invincibility > 0)
			invincibility--;
		Show();
		//玩家操作
		Player_move();
		Enemy_move();
		EatFood();
		//刷新
		FlushBatchDraw();
	}
	closegraph();
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/454855.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HADOOP完全分布式搭建(饭制版)

HADOOP完全分布式搭建&#xff08;饭制版&#xff09; 1.虚拟机安装 安装系统 点击VMware Workstation左上角文件&#xff0c;新建虚拟机 选择自定义&#xff0c;点击下一步 点击下一步 选择稍后安装操作系统&#xff08;后续我们使用的操作系统为CentOS7&#xff09;,点击…

【研发日记】,Matlab/Simulink开箱报告(十)——Requirements Toolbox

前言 见《开箱报告&#xff0c;Simulink Toolbox库模块使用指南&#xff08;五&#xff09;——S-Fuction模块(C MEX S-Function)》 见《开箱报告&#xff0c;Simulink Toolbox库模块使用指南&#xff08;六&#xff09;——S-Fuction模块&#xff08;TLC&#xff09;》 见《开…

2.案例、鼠标时间类型、事件对象参数

案例 注册事件 <!-- //disabled默认情况用户不能点击 --><input type"button" value"我已阅读用户协议(5)" disabled><script>// 分析&#xff1a;// 1.修改标签中的文字内容// 2.定时器// 3.修改标签的disabled属性// 4.清除定时器// …

构建部署_Jenkins介绍与安装

构建部署_Jenkins介绍与安装 构建部署_Jenkins介绍与安装Jenkins介绍Jenkins安装 构建部署_Jenkins介绍与安装 Jenkins介绍 Jenkins是一个可扩展的持续集成引擎。 持续集成&#xff0c;就是通常所说的CI&#xff08;Continues Integration&#xff09;&#xff0c;可以说是现…

Ajax(2)

图片上传 传图片文件不能像传文字一样用JSON格式&#xff0c;可以用form-data类型携带文件 1.获取图片文件对象 2.使用FormData&#xff08;浏览器内置的构造函数&#xff09;携带图片文件 3.提交表单数据到服务器&#xff0c;返回图片网址 这里可能用到的事件监听器&#…

[算法] 牛课题霸 - DP6 连续子数组最大和 - 动态规划

文章目录 题目链接解题过程思路一思路二 题目链接 DP6 连续子数组最大和 解题过程 思路一 两个for循环&#xff0c;遍历。 因为每个元素都要遍历两遍&#xff0c;所以时间复杂度O(n^2)。 简单的测试用例可以通过&#xff0c;但是提交时&#xff0c;一个巨大的数组用例&…

Copilot如何将word文稿一键转为PPT

背景 很多小伙伴平时经常会遇到的一个场景是&#xff0c;如何将word文稿图文转为PPT。 这个过程是既复杂而又无趣的。 现在&#xff0c;有了copilot&#xff0c;你可以一键搞定&#xff01; 使用copilot Pro来实现 比如我们想要做一个关于copilot studio的PPT展示&#xf…

Unix环境高级编程-学习-05-TCP/IP协议与套接字

目录 一、概念 二、TCP/IP参考模型 三、客户端和服务端使用TCP通信过程 1、同一以太网下 四、函数介绍 1、socket &#xff08;1&#xff09;声明 &#xff08;2&#xff09;作用 &#xff08;3&#xff09;参数 &#xff08;4&#xff09;返回值 &#xff08;5&…

【Python】新手入门学习:详细介绍单一职责原则(SRP)及其作用、代码示例

【Python】新手入门学习&#xff1a;详细介绍单一职责原则&#xff08;SRP&#xff09;及其作用、代码示例 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyT…

MySQL一些命令记录

查看数据引擎 show engines;创建数据库,并选择库 CREATE DATABASE IF NOT EXISTS test_database; USE test_database;创建表 CREATE TABLE IF NOT EXISTS test_table (id INT AUTO_INCREMENT PRIMARY KEY,field1 VARCHAR(50),field2 VARCHAR(50),field3 VARCHAR(50),field4 …

https超文本传输安全协议到底是什么?

HTTPS&#xff08;全称&#xff1a;Hyper Text Transfer Protocol over Secure Socket Layer&#xff09;是超文本传输安全协议的英文翻译缩写&#xff0c;它是以安全为目标的HTTP通道&#xff0c;在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性。HTTPS在HTTP的基…

基于SSM的协同过滤算法的电影推荐系统(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的协同过滤算法的电影推荐系统&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通…

盘点9款AI论文写作神器,轻松写出高质量论文

0. 未来百科 未来百科&#xff0c;是一个全球最大的 AI 产品导航网站 —— 为发现全球优质 AI 工具而生 。目前已 聚集全球 10000优质 AI 工具产品 &#xff0c;旨在帮助用户发现全球最好的 AI 工具&#xff0c;同时为研发 AI 垂直应用的创业公司提供展示窗口&#xff0c;迎接…

如何使用vue定义组件之——父组件调用子组件

首先&#xff0c;我们需要创建两个组件模板template&#xff1a; <template id"father"><div><h3>我是父组件</h3><h3>访问自己的数据:</h3><h3>{{ msg }}</h3></div></template><template id"…

C#多线程(5)——异步方法async与await

在上一章节中&#xff0c;为大家介绍了C#多线程&#xff08;4&#xff09;——任务并行库TPL&#xff0c;TPL是从.NetFramwork4.0后引入的基于异步操作的一组API&#xff0c;核心关注于任务【 T a s k 和 T a s k < T > \textcolor{red}{Task 和 Task<T>} Task和Ta…

HarmonyOS NEXT应用开发之下拉刷新与上滑加载案例

介绍 本示例介绍使用第三方库的PullToRefresh组件实现列表的下拉刷新数据和上滑加载后续数据。 效果图预览 使用说明 进入页面&#xff0c;下拉列表触发刷新数据事件&#xff0c;等待数据刷新完成。上滑列表到底部&#xff0c;触发加载更多数据事件&#xff0c;等待数据加载…

基于Springboot的集团门户网站(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的集团门户网站&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&…

YOLOv5目标检测学习(5):源码解析之:推理部分dectet.py

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、导入相关包与路径、模块配置1.1 导入相关的python包1.2 获取当前文件的相对路径1.3 加载自定义模块1.4 总结 二、执行主体的main函数所以执行推理代码&…

手写简易操作系统(六)--内存分页

前情提要 上一节我们讲到了获取物理内存&#xff0c;这节我们将开启内存分页 一、内存分页的作用 内存分页是一种操作系统和硬件协同工作的机制&#xff0c;用于将物理内存分割成固定大小的页面&#xff08;通常为4KB&#xff09;并将虚拟内存空间映射到这些页面上。内存分页…

Django官网项目 五

Writing your first Django app, part 5 | Django documentation | Django 自动测试介绍 何为自动测试 测试有系统自动完成。你只需要一次性的编写测试代码&#xff0c;当程序代码变更后&#xff0c;不需要对原来的测试人工再重新测试一遍。系统可以自动运行原来编写的测试代…
最新文章