我是靠谱客的博主 想人陪老虎,最近开发中收集的这篇文章主要介绍用C语言写一个简单的球球大作战游戏(图形界面用easyx) 1. 引用与声明 2.主体函数 3. 其他模块,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
1. 引用与声明
1.1 此处包含需要用到的头文件,一些声明和定义 声明一个结构体可以让食物,玩家和ai玩家用,避免重复的定义。
#include<stdio.h>
#include<easyx.h>
#include<time.h>
#include<stdlib.h>
#include<math.h>
#pragma comment(lib,"Winmm.lib")
#define WIDTH 1024 //窗口宽度
#define HEIGHT 640//窗口高度
#define AI_NUM 10 //ai数量
const int Gridsize = 10; //格子宽度
int food_num = 100;//食物数量
int ai_num = 10;//ai玩家数量
//给ai玩家起名字
const char* names[AI_NUM] = { "南夕子","马斯克","地狱烈火","非常可乐","今夜无眠","十大恶人","有你真好","世界和平",
"马赛克","统一" };
//制作一个定时器
bool timer(int ms,int id)
{
static int start[5] = { clock() };
int end = clock();
if (end - start[id] > ms)
{
start[id] = end;
return true;
}
return false;
}
//精灵结构体包括坐标,半径,颜色等
struct Sprite
{
double x;//坐标
double y;
double r;//半径
DWORD color;//颜色
char name[20];//名字
bool exist;//判断是否存在
Sprite* food_index;//目标食物
Sprite* next;//结点指针
};
//定义一个玩家结构体
Sprite player;
//定义一个食物
Sprite* one_food;
//定义ai玩家
Sprite*one_aiplayer;
//调用函数
void InitSprite(Sprite* spr, double x, double y,double r, const char* name = "Sprite");
void DrawPlayer(Sprite* spr, bool showName = true);
void AddFood();
void CreatFood();
void CreatAIplayer();
void AddAIplayer(int num);
void sort();
void ranking();
int game_menu();
2.主体函数
2.1 游戏画面初始化和绘制 画出食物,玩家和ai玩家
//初始化数据
void InitData()
{
srand(unsigned int (time(NULL)));
setbkcolor(WHITE);
cleardevice();//清空原来颜色
mciSendString("open resource/bk.mp3",NULL,0,NULL);
mciSendString("play resource/bk.mp3 repeat", NULL, 0, NULL);
InitSprite(&player, rand() % WIDTH, rand() % HEIGHT,10, "必胜客");//初始化玩家
CreatFood();//创建食物头指针
//将所有食物加载出来
for (int i = 0; i < food_num; i++)
{
AddFood();
}
CreatAIplayer();
for (int i = 0; i < ai_num; i++)
{
AddAIplayer(i);
}
}
//绘制图画
void DrawImg()
{
//画坐标格子
setlinecolor(RGB(100, 250, 100));//设置格子颜色
for (int i = 0; i <= WIDTH / Gridsize; i++)//画纵坐标线段
{
line(i*Gridsize, 0, i*Gridsize, HEIGHT);
}
for (int k = 0; k <= HEIGHT/Gridsize; k++)//画横坐标线段
{
line(0, k*Gridsize, WIDTH, k*Gridsize);
}
DrawPlayer(&player);//绘制玩家
//绘制食物
Sprite* fp;
fp = one_food->next;
while (fp != NULL)
{
DrawPlayer(fp,false);
fp = fp->next;
}
//绘制ai玩家
Sprite* tp;
tp = one_aiplayer->next;
while (tp != NULL)
{
DrawPlayer(tp, true);
tp = tp->next;
}
}
//操作结构体函数(玩家,食物,ai玩家都适用)
void InitSprite(Sprite* spr, double x, double y,double r, const char* name )
{
spr->x = x;
spr->y = y;
spr->r = r;
spr->color = RGB(rand()% 256, rand()% 256, rand()% 256);
spr->exist = true;
strcpy(spr->name, name);
spr->food_index = NULL;
}
2.2 创建角色 创建玩家,对玩家的按键处理来控制方向移动,用链表来创建食物以及ai玩家,当食物被吃时重新随机刷新。
void DrawPlayer(Sprite* spr, bool showName )
{
if (spr->exist)
{
//绘制图形
setfillcolor(spr->color);//填充颜色
solidcircle(spr->x, spr->y, spr->r);//绘制图形位置
if (showName)//判断是否需要名字
{
//绘制文字
setbkmode(TRANSPARENT);//设置文字背景颜色透明
settextcolor(RED);//设置文字颜色红色
settextstyle(18, 0, "黑体");//设置文字大小,粗细,字体
outtextxy(spr->x - textwidth(spr->name) / 2, spr->y - textheight(spr->y) / 2, spr->name);//绘制文字位置
}
}
}
//玩家移动
void MovePlayer(Sprite* spr,double dx,double dy)
{
spr->x += dx;
spr->y += dy;
}
//按键处理
void KeyDownDeal(Sprite* spr)
{
int speed = 2;
if (GetAsyncKeyState(VK_LEFT) && spr->x >= spr->r)
{
MovePlayer(&player, -speed, 0);
}
if (GetAsyncKeyState(VK_RIGHT) && spr->x <= getwidth() - spr->r)
{
MovePlayer(&player, speed, 0);
}
if (GetAsyncKeyState(VK_UP) && spr->y >= spr->r)
{
MovePlayer(&player, 0, -speed);
}
if (GetAsyncKeyState(VK_DOWN) && spr->y <= getheight() - spr->r)
{
MovePlayer(&player, 0, speed);
}
}
//创建食物头指针
void CreatFood()
{
one_food = (Sprite*)malloc(sizeof(Sprite));
if (one_food == NULL)
{
_exit(0);
}
one_food->next = NULL;
}
//增加食物并初始化
void AddFood()
{
Sprite* pnew;
pnew = (Sprite*)malloc(sizeof(Sprite));
if (pnew == NULL)//创建未成功退出
{
_exit(0);
}
pnew->next = NULL;
InitSprite(pnew, rand() % getwidth(), rand() % getheight(), 1 + rand() % 3);
pnew->next = one_food->next;
one_food->next = pnew;
}
//获得两圆距离
int collision(Sprite* spr1, Sprite* spr2)
{
return sqrt(pow(spr1->x - spr2->x, 2) + (pow(spr1->y - spr2->y, 2)));
}
//吃食物长大
void EatFood(Sprite* spr)
{
Sprite* ftp0;
ftp0 = one_food->next;
while (ftp0!=NULL)
{
if (ftp0->exist == false)
{
ftp0 = ftp0->next;
continue;
}
if (ftp0->exist == true && collision(spr, ftp0) < (spr->r+ftp0->r))
{
ftp0 ->exist = false;
spr->r += ftp0->r / 8;
}
ftp0 = ftp0->next;
}
}
//重新刷新食物
void RefreshFood()
{
Sprite* ftp;
ftp = one_food->next;
while (ftp!=NULL)
{
if (ftp->exist == false)
{
InitSprite(ftp, rand() % getwidth(), rand() % getheight(), 1 + rand() % 3);
}
ftp = ftp->next;
}
}
//创建ai玩家头指针
void CreatAIplayer()
{
one_aiplayer = (Sprite*)malloc(sizeof(Sprite));
if (one_aiplayer == NULL)
_exit(0);
one_aiplayer->next = NULL;
}
//添加ai玩家
void AddAIplayer(int num)
{
Sprite* aitp;
aitp = (Sprite*)malloc(sizeof(Sprite));
if (aitp == NULL)
{
_exit(0);
}
aitp->next = NULL;
InitSprite(aitp, rand() % getwidth(), rand() % getheight(), 10,names[num]);
aitp->next = one_aiplayer->next;
one_aiplayer->next = aitp;
}
2.3 ai玩家移动 ai玩家吃食物,ai与玩家和ai与ai之间进行互吃,ai追击目标(也可以自己写一个逃跑)
//判断是否玩家与ai玩家互吃,ai玩家互吃
void DevourEachOther()
{
//判断玩家与ai玩家之间能否吃掉对方
Sprite* aitemp1;
aitemp1 = one_aiplayer->next;
while (aitemp1 != NULL)
{
if (player.exist == true && aitemp1->exist == true && collision(&player, aitemp1) <= player.r&&player.r>=aitemp1->r*1.1)
{
aitemp1->exist = false;
player.r += aitemp1->r / 8;
}
if (player.exist == true && aitemp1->exist == true && collision(&player, aitemp1) <= aitemp1->r&&player.r*1.1 <= aitemp1->r)
{
player.exist = false;
aitemp1->r += player.r / 8;
}
//判断ai玩家之间是否能吃掉对方
Sprite* aitemp2;
aitemp2 = one_aiplayer->next;
while (aitemp2!=NULL)
{
if (aitemp1 == aitemp2)
{
aitemp2 = aitemp2->next;
continue;
}
if (aitemp2->exist == true && aitemp1->exist == true && collision(aitemp1, aitemp2) <= aitemp1->r&&aitemp1->r >= aitemp2->r*1.1)
{
aitemp2->exist = false;
aitemp1->r += aitemp2->r / 8;
}
aitemp2 = aitemp2->next;
}
//判断ai玩家吃食物
EatFood(aitemp1);
aitemp1 = aitemp1->next;
}
}
//追击目标
void chase(Sprite* run, Sprite* chase)
{
if (run->x > chase->x)
{
chase->x++;
}
else
{
chase->x--;
}
if (run->y > chase->y)
{
chase->y++;
}
else
{
chase->y--;
}
}
//判断两个精灵距离是否符合要求
bool SpriteOfRelation(Sprite* spr1,Sprite* spr2)
{
int index_distance = 100;//目标在最小范围才去追击
if (spr2->exist == true && spr1->r > spr2->r*1.5&&collision(spr1,spr2)<=index_distance)
{
return true;
}
return false;
}
//ai玩家找最近的食物
void FandFoods(Sprite* spr)
{
Sprite* fw;//食物 指针
fw = one_food->next;
int min_distance = getheight();//ai玩家与食物最小距离
while (fw != NULL)
{
if (fw->exist == true)
{
if (collision(spr, fw) < min_distance)
{
min_distance = collision(spr, fw);
spr->food_index = fw;
}
}
fw = fw->next;
}
}
//ai玩家移动
void AiplayersMove()
{
Sprite* aimp1 = one_aiplayer->next;//搜索每一个ai玩家
while (aimp1 != NULL)
{
if (aimp1->exist)
{
//寻找合适的ai玩家目标
Sprite* aimp2;
aimp2 = one_aiplayer->next;
while (aimp2 != NULL)
{
if (aimp1 == aimp2)
{
aimp2 = aimp2->next;
continue;
}
if (SpriteOfRelation(aimp1, aimp2))
{
aimp1->food_index = aimp2;//当发现目标时将目标存入在标记中
}
aimp2 = aimp2->next;
}
//判断能否将玩家作为目标
if (SpriteOfRelation(aimp1, &player))
{
aimp1->food_index = &player;
}
//追击目标必须存在且被追击的目标半径必须小于追击者的半径
if (aimp1->food_index != NULL&&aimp1->food_index->exist == true && aimp1->food_index->r < aimp1->r)//如果标记目标,就追击目标
{
chase(aimp1->food_index, aimp1);
}
else
{
FandFoods(aimp1);//如果没有其他ai玩家目标,就找小食物
chase(aimp1->food_index, aimp1);
}
}
aimp1 = aimp1->next;
}
}
2.4 从大到小排序 进行实时排名显示(没有把玩家加入排名,可以自行添加)
//从大到小排序
void sort()
{
Sprite* p1 = one_aiplayer;//定义第一个结点
Sprite* p2 = NULL;//下一个结点
Sprite* tempt = NULL;//临时结点位置存放点
Sprite* p3 = NULL;//用于存放临时最大数的上一个结点
while (p1->next != NULL)
{
p2 = p1->next;
tempt = p2;
p3 = p1;
while (p2 != NULL)
{
//将P2的半径与临时暂存半径进行比较,大的保存在tempt临时指针里
if (tempt->r < p2->r)
{
tempt = p2;
}
p2 = p2->next;
}
while (p3->next != tempt)
{
p3 = p3->next;
}
p3->next = tempt->next;
tempt->next = p1->next;
p1->next = tempt;
p1 = p1->next;
}
}
//排名显示
void ranking()
{
Sprite* r;
r = one_aiplayer->next;
int i = 0;
while (r!=NULL)
{
settextcolor(RGB(255 - i * 5, 215 - i * 10, 0 + i * 10));
setbkmode(TRANSPARENT);
settextstyle(20, 0, "黑体");
char ch[60] = {0};
sprintf(ch, "第%d名:%s", i+1, r->name);
outtextxy(WIDTH - 250, i * 30 + 20, ch);
i = i % 10;
i++;
r = r->next;
}
}
3. 其他模块
3.1 菜单界面 包括开始游戏,退出游戏,以及说明(以及返回)
//开始初始化界面菜单UI void InitUI() { //一级菜单 initgraph(WIDTH, HEIGHT);//初始化窗口 setbkcolor(GREEN); cleardevice(); //游戏名 char GameName[20] = { "球球大作战" }; settextcolor(BLUE); settextstyle(60, 20, "黑体"); outtextxy(WIDTH / 2 - textwidth(GameName) / 2, 50, GameName); //三个选项的背景 fillrectangle(430, 200, 580, 260); fillrectangle(430, 300, 580, 360); fillrectangle(430, 400, 580, 460); setbkmode(TRANSPARENT); settextstyle(40, 10, "黑体"); settextcolor(BLACK); //三个选项 char select1[10] = { "开始游戏" }; char select2[10] = { "退出游戏" }; char select3[10] = { "游戏说明" }; outtextxy(430 + textwidth(select1) / 2, 200 + textheight(select1) / 2, select1); outtextxy(430 + textwidth(select2) / 2, 300 + textheight(select2) / 2, select2); outtextxy(430 + textwidth(select3) / 2, 400 + textheight(select3) / 2, select3); } //菜单运行 int game_menu() { InitUI(); //BeginBatchDraw(); MOUSEMSG m1; while (true) { m1 = GetMouseMsg();//获取鼠标操作 if (m1.x >= 430 && m1.x <= 580 && m1.y >= 200 && m1.y <= 260)//游戏开始界面 { setlinecolor(RED); rectangle(430, 200, 580, 260); if (m1.uMsg == WM_LBUTTONDOWN) { InitData(); while (true) { //运行游戏 BeginBatchDraw();//双缓冲绘图 cleardevice();//在每次绘制之前清空屏幕 DrawImg(); KeyDownDeal(&player); EatFood(&player); RefreshFood(); AiplayersMove(); DevourEachOther(); ranking(); sort(); EndBatchDraw(); } } } else if (m1.x >= 430 && m1.x <= 580 && m1.y >= 300 && m1.y <= 360) { setlinecolor(RED); rectangle(430, 300, 580, 360); if (m1.uMsg == WM_LBUTTONDOWN) { closegraph(); _exit(0); } } else if (m1.x >= 430 && m1.x <= 580 && m1.y >= 400 && m1.y <= 460) { setlinecolor(RED); rectangle(430, 400, 580, 460); if (m1.uMsg == WM_LBUTTONDOWN) { //二级菜单 setbkcolor(WHITE); cleardevice(); settextcolor(BLACK); settextstyle(20, 0, "黑体"); setfillcolor(YELLOW); fillrectangle(40, 60, 140, 100); setbkmode(TRANSPARENT); char returna[20] = { "返回上一层" }; outtextxy(40 +(50 - textwidth(returna) / 2), 60 + textheight(returna) / 2, returna); outtextxy(200, 100, "感谢大家的支持,有不足之处,请多多指正 ,请使用方向键,控制方向!!"); MOUSEMSG m2;//第二层使用鼠标 while (true) { m2 = GetMouseMsg(); if (m2.x >= 40 && m2.x <= 140 && m2.y >= 60 && m2.y <= 100)//游戏开始界面 { setlinecolor(RED); rectangle(40, 60, 140, 100); if (m2.uMsg == WM_LBUTTONDOWN) { closegraph(); InitUI(); break; } } else { setlinecolor(YELLOW); rectangle(40, 60, 140, 100); } } } } else { setlinecolor(WHITE); rectangle(430, 200, 580, 260); rectangle(430, 300, 580, 360); rectangle(430, 400, 580, 460); } } }
3.2 主函数人口 内容不是太多,可以自行添加
//主窗口
int main()
{
game_menu();
closegraph();
return 0;
}
最后
以上就是想人陪老虎为你收集整理的用C语言写一个简单的球球大作战游戏(图形界面用easyx) 1. 引用与声明 2.主体函数 3. 其他模块的全部内容,希望文章能够帮你解决用C语言写一个简单的球球大作战游戏(图形界面用easyx) 1. 引用与声明 2.主体函数 3. 其他模块所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复