C/C++编程笔记:C语言开发球球大作战(源码分享),你想试试吗?
游戏背景
《球球大作战》是Superpop一款自主研du发的免费手机网络游戏。 以玩家间的实时互动PK产生游戏乐趣为设计宗旨,通过简单的规则将玩家操作直接转化为游戏策略,体验智谋碰撞的战斗乐趣。
游戏的基本操作包括键盘按下(上下左右四个方向,还有作弊测试按键空格键和A键),玩家可以在地图上随意移动,不过不能超出边界。不管是玩家还是AI都可以吃比自己小的球,反之也可以被吃,吃掉之后直径会增大,增大算法是被吃掉的半径的1/4。如果玩家被吃掉,会在任意地方重新开始。
那么今天,我们就用C语言,来写出我们的球球大作战,一起来看看吧!
效果展示

游戏步骤
球球大作战游戏分为几个步骤:
①使用自定义空白图片表示地图;②绘制玩家,食物;③处理玩家移动,以及吃食物判断;④绘制一个AI并实现其移动;
话不多说,接下来我们之间来看我们的代码吧!需要素材以及相关资料源码可以关注微信公众号输入关键词领取,那先来看看代码吧!
源码分享
#include<graphics.h> //包含easyx图形库文件
#include<time.h> //C语言时间头文件
#include<mmsystem.h>//win32多媒体设备接口文件
#pragma comment(lib,"winmm.lib")//win32多媒体设备接口库
#define WIN_WIDTH 1024 //屏幕的宽
#define WIN_HEIGHT 640//576 //屏幕高
#define MAP_WIDTH (WIN_WIDTH*3) //地图宽度
#define MAP_HEIGHT (WIN_HEIGHT*3)//地图高度
#define FOOD_NUM 500 //食物数量
#define AI_NUM 200 //ai数量
IMAGE map(MAP_WIDTH, MAP_HEIGHT);
POINT g_CameraPos; // 摄像机(屏幕左上角)在地图上的位置
struct Ball
{
bool flag; // 是否被吃 活 1,死 0
COLORREF color; // 颜色
float r; //
float x; // 坐标
float y;
int type; //食物独有属性,决定是什么类型的食物(圆?矩形?多边形?)
};
struct Ball mover; //玩家
struct Ball food[FOOD_NUM]; //食物数组
struct Ball ai[AI_NUM]; //AI数量
void ChaseAlgorithom(Ball *chase, Ball *run);
float DisTance(Ball b1, Ball b2);
void Gameinit()
{
//设置随机数种子
srand((unsigned)time(NULL));
//播放背景音乐
mciSendString("open BallGame.mp3 alias bk", , , );
mciSendString("play bk repeat", , , );
//初始化食物
for (int i = ; i < FOOD_NUM; i++)
{
food[i].x = (float)(rand() % MAP_WIDTH);
food[i].y = (float)(rand() % MAP_HEIGHT);
food[i].r = (float)(rand() % + );
food[i].color = RGB(rand() % , rand() % , rand() % ); // 随机颜色
food[i].flag = ;
food[i].type = rand() % ;
}
//初始化AI
for (int i = ; i < AI_NUM; i++)
{
ai[i].color = RGB(rand() % , rand() % , rand() % ); //rand()%256 随机取值 0-255
ai[i].flag = ;
ai[i].x = rand() % (MAP_WIDTH - int(ai[i].r + 0.5)) + int(ai[i].r + 0.5); //AI产生的位置不会出现一个越界
ai[i].y = rand() % (MAP_HEIGHT - int(ai[i].r + 0.5)) + int(ai[i].r + 0.5);
ai[i].r = float(rand() % + );
}
{//初始化玩家数据
mover.color = BLUE;
mover.r = ;
//玩家在窗口的位置
mover.x = rand() % WIN_WIDTH;
mover.y = rand() % WIN_HEIGHT;
mover.flag = ;
}
}
//游戏地图开始绘制位置判断
void computeCameraPos()
{
// 以人物位置为中心计算摄像机的理论位置
g_CameraPos.x = mover.x - WIN_WIDTH / ;
g_CameraPos.y = mover.y - WIN_HEIGHT / ; // 防止摄像机越界
if (g_CameraPos.x < ) g_CameraPos.x = ;
if (g_CameraPos.y < ) g_CameraPos.y = ;
if (g_CameraPos.x > MAP_WIDTH - WIN_WIDTH) g_CameraPos.x = MAP_WIDTH - WIN_WIDTH;
if (g_CameraPos.y > MAP_HEIGHT - WIN_HEIGHT) g_CameraPos.y = MAP_HEIGHT - WIN_HEIGHT;
}
//游戏绘制
void Gamedraw()
{
SetWorkingImage(&map);
setbkcolor(WHITE); // 白色背景
cleardevice();
//画食物
for (int i = ; i < FOOD_NUM; i++)
{
if (food[i].flag == )
{
setfillcolor(food[i].color);
if (food[i].type == )
{
solidellipse((int)food[i].x, (int)food[i].y, (int)(food[i].x + food[i].r), (int)(food[i].y + food[i].r));
}
else if (food[i].type == )
{
solidpie((int)food[i].x, (int)food[i].y, (int)(food[i].x + food[i].r), (int)(food[i].y + food[i].r), 0.0, 1.5);
}
else
{
solidcircle(int(food[i].x), int(food[i].y), int(food[i].r));
}
}
else
{
food[i].x = (float)(rand() % MAP_WIDTH);
food[i].y = (float)(rand() % MAP_HEIGHT);
food[i].r = (float)(rand() % + );
food[i].color = RGB(rand() % , rand() % , rand() % ); // 随机颜色
food[i].flag = ;
food[i].type = rand() % ;
}
}
//画AI
for (int i = ; i < AI_NUM; i++)
{
if (ai[i].flag == )
{
setfillcolor(ai[i].color);
solidcircle(ai[i].x, ai[i].y, ai[i].r);
}
else
{
ai[i].color = RGB(rand() % , rand() % , rand() % ); //rand()%256 随机取值 0-255
ai[i].flag = ;
ai[i].x = rand() % (MAP_WIDTH - int(ai[i].r + 0.5)) + int(ai[i].r + 0.5); //AI产生的位置不会出现一个越界
ai[i].y = rand() % (MAP_HEIGHT - int(ai[i].r + 0.5)) + int(ai[i].r + 0.5);
ai[i].r = float(rand() % + );
}
}
//绘制玩家
setfillcolor(RED);
fillcircle(mover.x, mover.y, mover.r);
//绘制玩家名称
settextcolor(BLACK);
setbkmode(TRANSPARENT);
settextstyle(, , "楷体");
char pname[] = "微信公众号:C语言编程学习基地";
int twidth = textwidth(pname) / ;//计算文字宽度为了居中显示在玩家中央
outtextxy(mover.x - twidth, mover.y, pname);
//恢复默认工作区,即窗口
SetWorkingImage();
//更新摄像机位置
computeCameraPos();
//把地图显示到窗口上
putimage(, , WIN_WIDTH, WIN_HEIGHT, &map, g_CameraPos.x, g_CameraPos.y);
}
//玩家移动,参数为玩家移动的速度(单位像素)
void Gamemove(int speed)
{
//获取键盘按键
if (GetAsyncKeyState(VK_UP) & 0x8000)
{
if (mover.y - mover.r > )
{
mover.y -= speed;
}
}
if (GetAsyncKeyState(VK_DOWN) & 0x8000)
{
if (mover.y + mover.r < MAP_HEIGHT)
{
mover.y += speed;
}
}
if (GetAsyncKeyState(VK_LEFT) & 0x8000)
{
if (mover.x - mover.r > )
{
mover.x -= speed;
}
}
if (GetAsyncKeyState(VK_RIGHT) & 0x8000)
{
if (mover.x + mover.r < MAP_WIDTH)
{
mover.x += speed;
}
}
//作弊测试,按空格不断增大,A缩小
if (GetAsyncKeyState(VK_SPACE) & 0x8000)
{
mover.r += ;
}
if (GetAsyncKeyState('A') & 0x8000)
{
if (mover.r > )
mover.r -= ;
}
}
//玩家吃食物
void EatFood()
{
for (int i = ; i < FOOD_NUM; i++)
{
if (food[i].flag == && DisTance(food[i], mover) < mover.r)
{
food[i].flag = ;
mover.r += food[i].r / ;
}
}
}
//玩家吃Ai,Ai吃玩家
void EatAi()
{
for (int i = ; i < AI_NUM; i++)
{
if (ai[i].flag == )
continue;
//玩家吃Ai
if (DisTance(ai[i], mover) < mover.r - ai[i].r / )
{
ai[i].flag = ;
mover.r += ai[i].r / ;
break;//吃到一个就退出
}
//ai吃玩家
else if (DisTance(ai[i], mover) < ai[i].r - mover.r / )
{
mover.x = rand() % MAP_WIDTH;
mover.y = rand() % MAP_HEIGHT;
ai[i].r += mover.r / ;
mover.r = ;
break;
}
}
}
//AI吃食物,AI吃Ai
void AiEatFood()
{
for (int i = ; i < AI_NUM; i++)
{
if (ai[i].flag == )
continue;
//ai吃食物
for (int j = ; j < FOOD_NUM; j++)
{
if (food[j].flag == && DisTance(ai[i], food[j]) < ai[i].r)
{
food[j].flag = ;
ai[i].r += food[i].r / ;
}
}
//Ai吃Ai
for (int k = i + ; k < AI_NUM; k++)
{
if (ai[k].flag == )
{
if (DisTance(ai[i], ai[k]) < ai[k].r - ai[i].r / )
{
ai[i].flag = ;
ai[k].r += ai[i].r / ;
}
else if (DisTance(ai[i], ai[k]) < ai[i].r - ai[k].r / )
{
ai[k].flag = ;
ai[i].r += ai[k].r / ;
}
} }
}
}
//Ai移动算法,追逐比自己半径小的球
void AiMove()
{
for (int i = ; i < AI_NUM; i++)
{
double min_DISTANCE = MAP_WIDTH;//最大搜索距离
int min = -;//用来保存找到目标小球的下标
if (ai[i].flag == )
{
//AI靠近AI
for (int k = i + ; k < AI_NUM; k++)
{
if (ai[i].r > ai[k].r&&ai[k].flag == )
{//如果能吃,且距离达到要求则更新距离,并保存下标
if (DisTance(ai[i], ai[k]) < min_DISTANCE)
{
min_DISTANCE = DisTance(ai[i], ai[k]);
min = k;
}
}
}
}
//如果找到目标,则去追逐
if ((min != -))
{
ChaseAlgorithom(&ai[i], &ai[min]);
} }
}
void JudeEat()
{
EatFood();
EatAi();
AiEatFood();
AiMove();
}
int main()
{
initgraph(WIN_WIDTH, WIN_HEIGHT, );
Gameinit();
DWORD t1, t2;
t1 = t2 = GetTickCount();
while ()
{
Gamedraw();
Gamemove();
if (t2 - t1 > )
{
JudeEat();
t1 = t2;
}
t2 = GetTickCount();
} getchar();
closegraph();
return ;
} //追逐算法
void ChaseAlgorithom(Ball *chase, Ball *run)
{
if (rand() % == )
{
if (chase->x < run->x)
{
chase->x += ;
}
else
{
chase->x -= ;
}
}
else
{
if (chase->y < run->y)
{
chase->y += ;
}
else
{
chase->y -= ;
}
}
}
//求两点之间的距离
float DisTance(Ball b1, Ball b2)
{
return sqrt((b1.x - b2.x)*(b1.x - b2.x) + (b1.y - b2.y)*(b1.y - b2.y));
}
以上就是本篇文章的全部分享,希望对大家有帮助!
自学C/C++编程难度很大,不妨和一些志同道合的小伙伴一起学习成长!
C语言C++编程学习交流圈子,【点击进入】微信公众号:C语言编程学习基地
有一些源码和资料分享,欢迎转行也学习编程的伙伴,和大家一起交流成长会比自己琢磨更快哦!

C/C++编程笔记:C语言开发球球大作战(源码分享),你想试试吗?的更多相关文章
- OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波
http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ...
- C/C++编程笔记:C语言成绩管理系统!链式结构的管理系统源码分享
最近很多同学因为学校的要求,需要完成自己的那个C语言课程设计,于是就有很多人私信或者加我私聊我,问的最多的还是<学生成绩管理系统>,其实当你项目写多了你就会发现:其实各类的管理系统都离不开 ...
- C/C++编程笔记:C语言实现连连看游戏,小白练手项目(源码分享)
本篇文章分享看题目就知道是写给初学者的,学的比较好的小伙伴也可以将自动算法等一些知识给加进去,希望对大家有帮助! 好了,当我们所有的准备工作做好之后,我们就可以来编写我们的C语言连连看游戏了! 其实这 ...
- GO语言slice详解(结合源码)
一.GO语言中slice的定义 slice 是一种结构体类型,在源码中的定义为: src/runtime/slice.go type slice struct { array unsafe.Point ...
- hadoop2.5.2学习及实践笔记(二)—— 编译源代码及导入源码至eclipse
生产环境中hadoop一般会选择64位版本,官方下载的hadoop安装包中的native库是32位的,因此运行64位版本时,需要自己编译64位的native库,并替换掉自带native库. 源码包下的 ...
- 基于python语言的tensorflow的‘端到端’的字符型验证码识别源码整理(github源码分享)
基于python语言的tensorflow的‘端到端’的字符型验证码识别 1 Abstract 验证码(CAPTCHA)的诞生本身是为了自动区分 自然人 和 机器人 的一套公开方法, 但是近几年的 ...
- Hadoop源码学习笔记之NameNode启动场景流程一:源码环境搭建和项目模块及NameNode结构简单介绍
最近在跟着一个大佬学习Hadoop底层源码及架构等知识点,觉得有必要记录下来这个学习过程.想到了这个废弃已久的blog账号,决定重新开始更新. 主要分以下几步来进行源码学习: 一.搭建源码阅读环境二. ...
- 用GO语言开发editplus编辑器插件(附源码)
我要开发的插件功能极为简单,就是对用户选中的内容进行base64编码或解密工作. 其中所涉及的技术部分主要是GO语言程序开发和editplus插件配置的部分,首先我们来看一下GO语言代码的写法,如下: ...
- C语言学生管理系统源码分享
大家好 我就是如假包换的...陈玲 自从运营了C语言程序设计微信公众号 很多粉丝都给我备注 ...奇葩 实在是不敢当 也被人开始叫玲玲姐 我知道 很多人都想看我出境 我本人也有 年多的舞台演讲训练 实 ...
随机推荐
- LESS 原理,一款css的预处理程序Less的使用
Less一种动态样式语言,LESS将CSS赋予了动态语言的特性,如变量,继承,运算,函数...LESS 既可以在客户端上运行 (支持IE 6+, Webkit, Firefox),也可以借助Node ...
- (四)ansible 通过堡垒机访问内网服务器
场景: 在ansible的使用过程中,存在这样的场景,ansible所在的管理节点与被管理的机器需要 通过一个跳板机才能连接,无法直接连接.要解决这个问题,并不需要在 ansible里做什么处 ...
- POJ3262贪心
题意:FJ去砍树,然后和平时一样留了 N (2 ≤ N ≤ 100,000)头牛吃草.当他回来的时候,他发现奶牛们正在津津有味地吃着FJ种的美丽的花!为了减少后续伤害,FJ决定立即采取行动:运输每头牛 ...
- 反转链表(剑指offer-15)
方法1:递归 /* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; ...
- [JAVA]标准IO流操作
import java.io.*; /** * @Description: * @projectName:JavaTest * @see:PACKAGE_NAME * @author:郑晓龙 * @c ...
- 机器学习实战基础(二十一):sklearn中的降维算法PCA和SVD(二) PCA与SVD 之 降维究竟是怎样实现
简述 在降维过程中,我们会减少特征的数量,这意味着删除数据,数据量变少则表示模型可以获取的信息会变少,模型的表现可能会因此受影响.同时,在高维数据中,必然有一些特征是不带有有效的信息的(比如噪音),或 ...
- Java实现 LeetCode第30场双周赛 (题号5177,5445,5446,5447)
这套题不算难,但是因为是昨天晚上太晚了,好久没有大晚上写过代码了,有点不适应,今天上午一看还是挺简单的 5177. 转变日期格式 给你一个字符串 date ,它的格式为 Day Month Yea ...
- Unity3D+Post Processing Stack V2自定义后处理效果研究
背景 众所周知,Unity3D支持自定义后处理效果,实现过程有三步: 添加着色器,在着色器里书写后处理代码: 添加材质,把材质和着色器绑定: 给相机添加脚本,重写其OnRenderImage方法,将材 ...
- ffmpeg播放器实现详解 - 框架搭建
ffplay是ffmpeg源码中一个自带的开源播放器实例,同时支持本地视频文件的播放以及在线流媒体播放,功能非常强大. FFplay: FFplay is a very simple and port ...
- MAC地址和交换机
数据链路层主要关注三个问题: 这个包是发给谁的?谁应该接收? 大家都在发,会不会产生混乱?有没有谁先发.谁后发的规则? 如果发送的时候出现了错误,怎么办? 数据链路层也称为MAC(Medium Acc ...