C语言游戏实战(9):球球大作战_void inset(){ //玩家小球srand((unsigned)time(null))-程序员宅基地

技术标签: c语言游戏实战篇  学习  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;
}

//修改版
#include<stdio.h>
#include<easyx.h>
#include<time.h>
#include<math.h>
#define Wide 1139
#define Hight 640
#define Wide_map (Wide*5)
#define Hight_map (Hight*5)
#define Food_num 2888
#define Enemy_num 388
#define Invincibility 50
//整个游戏地图
IMAGE map(Wide_map, Hight_map);
//复活时的无敌时间
int invincibility = Invincibility;
//玩家速度
int player_sleep = 2;
int l = 2;
int enemy_sleep = 2;
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 = 15;
	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 = rand() % 15 + 15;
		Enemy[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
	}

}
//玩家操作
void Player_move()
{
	if (GetAsyncKeyState(VK_UP)|| GetAsyncKeyState(0x57))
	{
		if (player.y > 0)
		{
			player.y -= player_sleep;
		}
	}
	if (GetAsyncKeyState(VK_DOWN)||GetAsyncKeyState(83))
	{
		if (player.y < Hight_map)
		player.y += player_sleep;
	}
	if (GetAsyncKeyState(VK_LEFT)|| GetAsyncKeyState(65))
	{
		if (player.x > 0)
		player.x -= player_sleep;
	}
	if (GetAsyncKeyState(VK_RIGHT)|| GetAsyncKeyState(68))
	{
		if (player.x < Wide_map)
		player.x += player_sleep;
	}
	if (GetAsyncKeyState(0x20))
	{
		player_sleep = l + 2;
	}
	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;
					}
				}
			}
		}
		
	}
}

//吃食物
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 / 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 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 = rand() % 10 + 15;
				Enemy[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
			}
			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 = rand() % 10 + 15;
				Enemy[j].color = RGB(rand() % 256, rand() % 256, rand() % 256);
			}
		}
		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 = rand() % 10 + 15;
				Enemy[j].color = RGB(rand() % 256, rand() % 256, rand() % 256);
			}
			//敌人吃玩家
			else
			{
				if (invincibility == 0)
				{
					Enemy[j].r += player.r / 10;
					player.x = Wide / 2;
					player.y = Hight / 2;
					player.r = 15;
					invincibility = Invincibility;
				}
			}
		}
	}
}
//显示
void Show()
{
	
	//设置地图
	SetWorkingImage(&map);
	//清屏
	cleardevice();
	//背景颜色
	setbkcolor(RGB(46, 47, 68));
	//划线颜色
	//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;
}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_58252863/article/details/136639127

智能推荐

Qt5 的connect新语法中 lambda表达式的引用传递问题_lambda qt connect 传参-程序员宅基地

文章浏览阅读1.7k次。介绍 Qt5 的 connect 新式语法的文章很多,关于其使用 lambda 表达式的语法也很容易搜到,今天我来一点不一样的干货也可以说是bug,由于个人能力原因,无法深究真正的原因,望神通广大的网友能告知一下,不尽感激。/* * 使用Qt 5.15.0 创建一个新的GUI程序,基类选择QWidget * 同时取消创建 ui界面,在 widget.cpp 中写上下面的代码 * 然后编译执行,在弹出的窗口中,点击QPushButton即可验证*/#include "widget.h"#incl_lambda qt connect 传参

【转】GitLab 7.2.1 升级到 7.14.3 过程中遇到的坑_gitlab gc-程序员宅基地

文章浏览阅读281次。转自:http://dockone.io/article/8413GitLab 7.2.1 升级到 7.14.3 过程中遇到的坑【背景】在此次升级之前,我们线上的 GitLab 7.2.1 版本已经跑了3年之久,其中结合我们自己的 CI/CD 流程添加了一些自定义的 feature,整个 CI/CD 流程运行的也十分顺畅。不过随着微服务、Docker、Kubernetes、Servic..._gitlab gc

mysql expdp gtid_ORACLE 12C可以通过expdp导出view数据-程序员宅基地

文章浏览阅读315次。有时候,多么的希望ORACLE能够导出某个视图中的数据,然后通过这个视图来迁移需要的数据,现在ORACLE 12C通过expdp的views_as_tables来实现了该功能,把视图当作一个普通表从而导出数据,导入的时候直接和一个正常表一样,通过视图的导出,表的导入来实现相关需求准备测试环境SQL> SELECT * FROM V$VERSION;BANNER ..._oracle expdp导出数据视图

51nod 1450 闯关游戏_51nod1450闯关游戏-程序员宅基地

文章浏览阅读694次。期望DP+思路_51nod1450闯关游戏

java计算机毕业设计高校防疫物资管理系统MyBatis+系统+LW文档+源码+调试部署-程序员宅基地

文章浏览阅读660次。java计算机毕业设计高校防疫物资管理系统MyBatis+系统+LW文档+源码+调试部署。springboot基于微服务架构的图书借阅系统的设计与实现。ssm基于大数据在线考试系统在线阅卷系统及大数据统计分析。jsp网上花卉销售系统的设计与实现sqlserver。springboot基于VUE的个人记账管理系统。ssm基于SSM的线上家庭医生系统的设计与实现。ssm基于vue的健康餐饮管理系统的设计与实现。ssm疫情背景下基于web的学生信息日报系统。ssm基于用户行为的自动化书籍推荐系统。

解决PYTHON爬取:RESPONSE.STATUS_CODE为418、403 问题_python r.status_code 403-程序员宅基地

文章浏览阅读4k次,点赞4次,收藏15次。问题1:初步解决响应状态418python爬取豆瓣网站电影:url = ‘https://movie.douban.com/?start=0&filter=’import requestsurl = 'https://movie.douban.com/top250?start=0&filter='res =requests.get(url)print(res.status_code)响应状态:418正常返回状态应该是 200问题解决参考链接: req_python r.status_code 403

随便推点

我的心得:数据中心运维&管理(二)-程序员宅基地

文章浏览阅读2.9k次。续接:《我的心得:数据中心运维&管理(一)》5:追其根源,防患未然:5Why 分析法在数据中心的应用;如何有效的解决问题,首先需要了解产生此问题的因素和最根本因素;如何寻找根本原因?需要更加有效合理的工具方法,下面给大家介绍一下典型的 5-Why 分析法:什么是 5-Why5-why 的关键在于鼓励解决问题的人要努力避开主观或自负的假设和逻辑陷阱,从结果着手,沿着因果关系链条,顺藤摸瓜,直至找出原_数据中心运维汇报案例

粒子群优化算法(PSO)-程序员宅基地

文章浏览阅读1.9w次,点赞34次,收藏307次。先简单介绍一下粒子群优化算法(Particle Swarm Optimization),后边会介绍一些改进的粒子群算法。1.背景知识受到鸟群觅食行为的启发(鸟群觅食,通过信息共享使种群找到最优的觅食点),由社会心理学家JamesKennedy和电气工程师RussellEberhart于1995年提出,用于解决科学工程领域的非线性,非凸性,组合优化问题;在函数优化,图像处理也有广泛的应用。粒子群优化算法是一种基于数值的优化算法,粒子群优化算法的基础是“信息共享”。具..._粒子群优化算法

刷了LeetCode的链表专题,我发现了一个秘密!!!_leetcode 刷题的链表带不带头结点-程序员宅基地

文章浏览阅读228次,点赞2次,收藏4次。刷了LeetCode的链表专题,我发现了一个秘密!文章目录刷了LeetCode的链表专题,我发现了一个秘密!引言1、链表的几个概念讲解1.1链表中的的指针是什么1.1指针指向哪儿1.3判断边界的条件2、必须掌握的几类题目2.1单链表反转(LeetCode206)2.2链表中环的检测(LeetCode141)2.3两个有序的链表合并(LeetCode21)2.4删除链表(LeetCode18)2.5删除链表倒数第 n 个结点(LeetCode19)2.6求链表的中间结点(LeetCode876)3、学习链表_leetcode 刷题的链表带不带头结点

android studio的安装(补充篇gradle失败的问题更新于 2021-03-10)-程序员宅基地

文章浏览阅读10w+次,点赞199次,收藏864次。本来没有打算写这篇文章的但是很多人看完我的上篇文章之后有所需求特此写下此文附上上篇android studio的安装,史上最详细(超多图)!!先说明原因:gradle资源包是通过android studio 远程访问安卓的gradle仓库进行下载的难免会出现网络不佳,以及被墙的情况(并不是所有人都会遇到)开始正文:1.现象说明gradle失败会显示这个界面2.首先确认自己的g..._补充篇gradle失败的问题

对`__stack_chk_fail`未定义的引用 解决手段?_对‘--stack-chk-fail“未定义的引用-程序员宅基地

文章浏览阅读6.4k次。init/built-in.o: In function `try_name':do_mounts.c.text+0x5e3):对‘__stack_chk_fail’未定义的引用init/built-in.o: In function `name_to_dev_t':(.text+0x8cb):对‘__stack_chk_fail’未定义的引用init/built-in.o: In_对‘--stack-chk-fail“未定义的引用

探索 `pianotrans`:一款创新的钢琴曲谱转换工具-程序员宅基地

文章浏览阅读313次,点赞5次,收藏6次。探索 pianotrans:一款创新的钢琴曲谱转换工具项目地址:https://gitcode.com/azuwis/pianotrans在音乐创作与学习的世界里,拥有一款能够准确、高效地处理乐谱的工具是至关重要的。今天,我们有幸向大家推荐一个开源项目——azuwis/pianotrans。这是一个基于Python编写的钢琴曲谱自动转换器,它可以帮助用户将各种格式的乐谱文件转化为方便演奏和学习...

推荐文章

热门文章

相关标签