C语言游戏实战(9):球球大作战
前言:
这款简易版的球球大作战是一款单人游戏,玩家需要控制一个小球在地图上移动,吞噬其他小球来增大自己的体积。本游戏使用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)
这个函数调用是用于在屏幕上的特定位置绘制或显示一个图像。下面是对这个函数调用中各个参数的具体解释:
(0, 0)
:这是图像要绘制的目标位置的左上角坐标,即x=0和y=0,通常表示屏幕的左上角。
Wide
:这个参数指定了要绘制的图像的宽度。
Hight
:这个参数指定了要绘制的图像的高度。
&map
:这是一个指向图像内存地址的指针,该图像将被绘制到屏幕上。在这个上下文中,map
可能是一个包含了图像数据的数据结构或数组。
x
:这个参数通常指定了要开始绘制图像的起始点的x坐标(在图像数据中)。
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;
}
相关文章:
C语言游戏实战(9):球球大作战
前言: 这款简易版的球球大作战是一款单人游戏,玩家需要控制一个小球在地图上移动,吞噬其他小球来增大自己的体积。本游戏使用C语言和easyx图形库编写,旨在帮助初学者了解游戏开发的基本概念和技巧。 在开始编写代码之前…...

【Windows】关闭自动更新
右键单击“此电脑”,点击“管理”。 找到:任务计划程序 -> 任务计划程序库 -> Microsoft -> Windows -> WindowsUpdate 右键单击Scheduled Start任务,然后点击“禁用”即可。 可能还会存在左下角提示更新重启的字样&#x…...

mac如何检测移动硬盘 mac硬盘检测工具 Tuxera怎么用 Tuxera NTFS官网
在工作学习中,我们都绕不开用移动硬盘来拷贝存储一些文件。但是在使用过程中,我们经常遇到“mac检测不到移动硬盘”“移动硬盘不存在”等问题,今天本文就带大家了解下mac如何检测移动硬盘,mac硬盘检测工具。 一、mac如何检测移动…...

1038 Recover the Smallest Number
idea 给出若干个可能含有前导0的数字串,将其进行拼接使其组成的数最小。 拼接串,想到借助string。 找最小,样例中的32,321, 3214尤为具备代表性,让字典序小的数尽可能靠前,联想到string的比较规则也是字典序 >判断…...

【Go】四、包名、访问范围控制、标识符、运算符
文章目录 1、_2、包名3、命名大小影响可访问范围4、运算符5、获取终端输入 1、_ 下划线"_"本身在Go中是一个特殊的标识符,称为空标识符用于忽略某个值 1)忽略导入的没使用的包 2)忽略某个返回值 2、包名 main包是程序的入口包&a…...
达梦数据库日志文件管理
达梦数据库日志文件管理 联机重做日志管理归档日志文件管理开启归档模式:SQL开启归档模式:dmarch.ini归档文件切换和删除 联机重做日志管理 检查联机重做日志: select * from v$rlog; --CUR_FILE表示正在使用的日志文件编号select * fr…...
zookeeper 监控 与 JVM 设置
一、通过JMX监控 JVM 默认情况下,在 ./bin/zkServer.sh 脚本中是默认开启了JMX监控的,并且是不需要认证的,详情可见ZOOMAIN变量; ZOOMAIN"-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port$JMXPORT -D…...

【java】关于String、StringBuffer和StringBuilder的那些事
在之前的文章中我们曾简单介绍过String这个引用类型变量,其实它还有许多特性,还有StringBuffer和StringBuilder这两个方法在字符串操作中也有非常重要的地位,接下来就由小编带大家梳理一下吧👊 目录 一、String 1、构造方法 2、…...
Spring 的 Ioc配置
HappyComponent.java package com.atguigu.Ioc_01;public class HappyComponent {// 默认包含无参的构造方法public void dowork(){System.out.println("HappyComponent.dowork");} }ClientService.java package com.atguigu.Ioc_01;静态工厂类 public class Clien…...

基于Java-SpringBoot+vue实现的前后端分离信息管理系统设计和实现
基于Java-SpringBootvue实现的前后端分离信息管理系统设计和实现 博主介绍:多年java开发经验,专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐…...

用Python实现办公自动化(自动化处理PDF文件)
自动化处理 PDF 文件 目录 自动化处理 PDF 文件 谷歌浏览器 Chrome与浏览器驱动ChromeDriver安装 (一)批量下载 PDF 文件 1.使用Selenium模块爬取多页内容 2.使用Selenium模块下载PDF文件 3.使用urllib模块来进行网页的下载和保存 4.使用urllib…...

银河麒麟操作系统Kylin Linux 离线安装Nginx1.21.5
一、查看操作系统版本号 nkvers ############## Kylin Linux Version ################# Release: Kylin Linux Advanced Server release V10 (Lance)Kernel: 4.19.90-52.15.v2207.ky10.x86_64Build: Kylin Linux Advanced Server release V10 (SP3) /(Lance)-x86_64-Build20/…...
ApiFox 使用教程
ApiFox 使用教程 目录概述需求: 设计思路实现思路分析1.基本使用教程(Apifox 使用 Postman)Apifox 下使用 mockapifox 下 swaggerApifox 下使用 Jmeter 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show…...

github拉取的项目添加至自己的仓库
想把GitHub的开源项目拉到本地进行二开,研究了一下上传到gitee的步骤: 步骤 gitee新建仓库,仓库名与本地文件夹的名称一致,建好后gitee的页面也会有显示git命令 打开项目目录,右键打开git bash(或者在gi…...

ZooKeeper 的持久化机制
持久化的定义: 数据,存到磁盘或者文件当中。机器重启后,数据不会丢失。内存 -> 磁盘的映射,和序列化有些像。 ZooKeeper 的持久化: SnapShot 快照,记录内存中的全量数据TxnLog 增量事务日志ÿ…...
VS2022+QT5.9 提示找不到qtmain.lib
从VS2013QT的项目切换到VS2022QT5.9,安装好mscv2017版本的QT5.9,项目工程选择QT project settings中的Qt Installation为mscv2017版本的QT5.9,编译好提示找不到qtmain.lib 解决思路: 提示找到xxxx.lib,第一库目录不对…...

HTTP和HTTPS谁传输数据更安全?
1.HTTP HTTP在传输数据时,通常都是明文传输,也就是传输的数据没有进行加密。在这种情况下,如果传输的是一些敏感数据,比如某银行卡密码,就很容易被别人截获到,这就对我们的个人利益产生了威胁。 HTTP传输数…...
竞赛常考的知识点大总结(七)图论
最短路 最短路问题(Shortest Path Problem)是图论中的一个经典问题,它要求在给定的图中找到两个顶点之间的最短路径。最短路问题可以是单源最短路问题(从一个顶点到其他所有顶点的最短路径)或所有对最短路问题&#x…...

NOSQL - Redis的简介、安装、配置和简单操作
目录 一. 知识了解 1. 关系型数据库与非关系型数据库 1.1 关系型数据库 1.2 非关系型数据库 1.3 区别 1.4 非关系型数据库产生背景 1.5 NOSQL 与 SQL的数据记录对比 2. 缓存相关知识 2.1 缓存概念 2.2 系统缓存 2.3 缓存保存位置及分层结构 二 . redis 相关知识 1.…...

书生·浦语大模型开源体系(二)笔记
💗💗💗欢迎来到我的博客,你将找到有关如何使用技术解决问题的文章,也会找到某个技术的学习路线。无论你是何种职业,我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章,也欢…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...

12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...