1 引言
《球球大作战》虽然在玩法上类似于大球吃小球的模式看起来很单薄。但是在游戏过程中会出现无数种意外情况,这就需要玩家运用一系列策略来达到不被吃和吃掉别人球的目的,大大增加了游戏的耐玩性。游戏彻底抛弃了枯燥无味的单机模式,采取全球玩家联网实时对战。当竞技在PC端打的火热的时候,《球球大作战》率先引进了微竞技的新模式,让玩家在休闲的同时还能体验到竞技的乐趣,这种尝试也博得了一片称赞声。
1.1 编写目的
球球大作战在在最近几年风靡全球,其版本也在不断迭代。本项目取其最核心的玩
法,给玩家一个最纯粹的休闲游戏体验。此外《球球大作战(简易版)》是基于Easyx图形库开发出来的,在用户界面显示方面表现良好,相信一定会给用户一个不错的游戏体验。
1.2开发背景
《球球大作战》是民族自研,积极健康休闲竞技游戏的代表。轻快明亮的画风、休闲有趣的玩法、富有深度的竞技性,使其成为国产手游创新模范。作为目前最具人气的移动电竞游戏,《球球大作战》累积用户数已超过1.7亿,最高同时在线人数突破175万。月活跃用户达到6000万。年轻化也是《球球大作战》的一大特色,朝气活力的学生群体是游戏主力军,95后及00后用户占比极高。
1.3 可行性分析
1.3.1 经济可行性
本项目是基于C语言开发,开发平台我们选择Visual Studio 2017 Community,此版本为免费版,由Microsoft公司免费提供给开发者使用;主流的开发环境有Windows和Linux,我们选择使用Windows进行开发,因为Windows我们比较熟悉,方便我们快速入手项目开发,所以需要一台安装了Windows操作系统的计算机;此外还使用了Easyx图形库,这个图形库也是免费提供给开发者使用和学习的。因此,总的经济方面付出不高,故经济可行性较高。
1.3.2 技术可行性
本项目大部分使用了C语言的语法,还使用少量的C++语法,调用了Easyx图形库。C语言方面,大部分知识是可以比较容易实现的,少部分通过翻书和查阅资料也是能够实现的。C++方面的语法,我们则较为不熟悉,需要花费较多的时间去了解。
1.4 问题定义
完成一个简易版的球球大作战项目,如何实现大球吃小球的功能?如何实现小球的移动和地图的刷新?如何实现游戏的暂停?等等…
2 需求分析
2.1 需求分析图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m7OqYnwh-1645933074363)(img/structure.jpg)]
2.2 功能需求分析
1)地图。利用easyx图形库生成一个适当大小的白色背景地图,和在右上角生成一个浅灰色的小地图用于显示玩家和AI的缩略图与位置。
2)文件存储。利用文件操作存储累计游戏次数和游戏时间。
3)玩家。初始化玩家球(包括坐标、生命值、颜色、大小、形状)。
4)AI(机器人)。初始化AI,生成指定数量的AI,每个AI随机坐标,生命值均为1,颜色随机,大小固定与玩家相同,形状为圆形。
5)生命。玩家和AI初始生命值均为1表示活,死后生命值变为0。
6)食物。随机位置生成指定数量的食物,颜色随机,大小在一定范围内随机,形状为圆形、椭圆形、圆角矩形等随机。
7)思路。玩家通过方向键控制球移动;大球吃小球,若a.r>b.r且a和b 圆心距d<a.r+b.r,则a.r = sqrt(a.ra.r + b.rb.r),b.r=0,b的生命变为0。所有AI的生命都变为0时,游戏结束,获得胜利。
8)玩家如果被AI吃,玩家生命变为0,游戏结束,游戏失败,显示游戏累 计时间。
2.3 性能需求分析
1)性能:程序总体占用空间较小,响应时间较块。
2)可修改性:程序代码层次清晰,主要注释均有,便于后期修改与维护。
3)可用性:程序目前为止尚未出现崩溃情况,可用性较高。
4)易用性:游戏规则简单,即使是新手也能很快熟练的游戏。
3 概要设计
3.1 运行环境
3.1.1 Windows 10
Windows操作系统是最常见的计算机操作系统,是微软公司开发的操作软件。该软件经历了多年的发展历程,目前推出的win10系统相当成熟。Windows操作系统具有人机操作互动性好,支持应用软件多,硬件适配性强等特点,未来该系统将更加安全、智能、易用。
操作系统是将人类利用计算机硬件发挥作用的平台,是计算机软件运行工作的环境,是计算机硬件的翻译。从计算机诞生发展到今天,出现了相当多种类的操作系统。Windows操作系统是其中的佼佼者。Windows操作系统是美国微软公司推出的一款操作系统。该系统从1985年诞生到现在,经过多年的发展完善,相对比较成熟稳定,是当前个人计算机的主流操作系统。
3.2 开发平台及技术基础
3.2.1 Visual Studio 2017
Microsoft Visual Studio是VS的全称。VS是美国微软公司的开发工具包系列产品。VS是一个基本完整的开发工具集,它包括了整个软件生命周期中所需要的大部分工具,如UML工具、代码管控工具、集成开发环境(IDE)等等。所写的目标代码适用于微软支持的所有平台,包括Microsoft Windows、Windows Mobile、Windows CE、.NET Framework、.Net Core、.NET Compact Framework和Microsoft Silverlight 及Windows Phone。
Visual Studio是目前最流行的Windows平台应用程序的集成开发环境。最新版本为 Visual Studio 2019版本,基于.NET Framework 4.7。
3.2.2 Easyx图形库
EasyX 是针对 C++ 的图形库,可以帮助 C 语言初学者快速上手图形和游戏编程。比如,可以用 VC + EasyX 很快的用几何图形画一个房子,或者一辆移动的小车,可以编写俄罗斯方块、贪吃蛇、黑白棋等小游戏,可以练习图形学的各种算法,等等。
许多学编程的都是从 C 语言开始入门的,而目前的现状是:
-
有些学校以 Turbo C 为环境讲 C 语言,只是 Turbo C 的环境实在太老了,复制粘贴都很不方便。
-
有些学校直接拿 VC 来讲 C 语言,因为 VC 的编辑和调试环境都很优秀,并且 VC 有适合教学的免费版本。可惜在 VC 下只能做一些文字性的练习题,想画条直线画个圆都很难,还要注册窗口类、建消息循环等等,初学者会受严重打击的。初学编程想要绘图就得用 TC,很是无奈。
-
还有计算机图形学,这门课程的重点是绘图算法,而不是 Windows 编程。所以,许多老师不得不用 TC 教学,因为 Windows 绘图太复杂了,会偏离教学的重点。新的图形学的书有不少是用的 OpenGL,可是门槛依然很高。
所以,我们想给大家一个更好的学习平台,就是 VC 方便的开发平台和 TC 简单的绘图功能,于是就有了这个 EasyX 库。如果您刚开始学 C 语言,或者您是一位教 C 语言的老师,再或者您在教计算机图形学,那么这个库一定会让您兴奋的。
3.3 基本设计概要及处理流程
3.3.1 基本设计概要
- 游戏主界面模块
- 游戏运行模块
- 游戏暂停模块
- 计时模块
3.3.2 流程处理(流程图)
3.4 结构图
void Food() {
for (int i = 0; i < FNUM; i++) { // 食物刷新
if (food[i].eat == 0) {
food[i].eat = 1;
food[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
food[i].x = rand() % MAPW;
food[i].y = rand() % MAPH;
food[i].type = rand() % 10 + 1;
}http://www.biyezuopin.vip
}
}
void draw() {
clearcliprgn();
setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 20); // 改变笔的颜色、状态
setlinecolor(RGB(0, 100, 0));
line(-20, MAPH + 20, -20, -20); // 左竖
line(-20, MAPH + 20, MAPW + 20, MAPH + 20); // 上横
line(-20, -20, MAPW + 20, -20); // 下横
line(MAPW + 20, -20, MAPW + 20, MAPH + 20); // 右竖
setfillcolor(GREEN);
if (mover.x - 0.5 * WIDTH / asp < -20)
floodfill(-20 - 11, mover.y, RGB(0, 100, 0));
if (mover.x + 0.5 * WIDTH / asp > MAPW + 20)
floodfill(MAPW + 20 + 11, mover.y, RGB(0, 100, 0));
if (mover.y - 0.5 * HEIGHT / asp < -20)
floodfill(mover.x, -20 - 11, RGB(0, 100, 0));
if (mover.y + 0.5 * HEIGHT / asp > MAPH + 20)
floodfill(mover.x, MAPH + 20 + 11, RGB(0, 100, 0));
setlinecolor(WHITE);
setlinestyle(PS_NULL);
for (int i = 0; i < FNUM; i++) { // 画出食物
if (food[i].eat == 0) continue;
setfillcolor(food[i].color);
switch (food[i].type) { // 形状
case 1: solidellipse(food[i].x, food[i].y, food[i].x + 2, food[i].y + 4); break;
case 2: solidellipse(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2); break;
case 3: solidrectangle(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2); break;
case 4: solidrectangle(food[i].x, food[i].y, food[i].x + 2, food[i].y + 4); break;
case 5: solidroundrect(food[i].x, food[i].y, food[i].x + 2, food[i].y + 4, 2, 2); break;
case 6: solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 2, 2); break;
case 7: solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 4, 2); break;
case 8: solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 2, 4); break;
case 9: solidroundrect(food[i].x, food[i].y, food[i].x + 4, food[i].y + 2, 1, 1); break;
case 10: fillcircle(food[i].x, food[i].y, 4); break;
}
}
for (int i = 0; i < AINUM; i++) { // 画 AI
if (ai[i].life == 0) continue;
setfillcolor(ai[i].color);
fillcircle(ai[i].x, ai[i].y, int(ai[i].r + 0.5));
}
setfillcolor(mover.color); // 画玩家
fillcircle(mover.x, mover.y, int(mover.r + 0.5));
IMAGE map(150, 100); // 小地图
SetWorkingImage(&map);
setbkcolor(RGB(120, 165, 209)); // 浅灰色背景
cleardevice();
for (int i = 0; i < AINUM; i++) // 画 AI(小地图)
{
if (ai[i].life == 0) continue;
setfillcolor(ai[i].color);
fillcircle(ai[i].x * 150 / WIDTH / 4, ai[i].y * 100 / HEIGHT / 4, int(ai[i].r / 28 + 0.5));
}
setfillcolor(mover.color); // 画玩家(小地图)
fillcircle(mover.x * 150 / WIDTH / 4, mover.y * 100 / HEIGHT / 4, int(mover.r / 28 + 0.5));
setlinecolor(RGB(0, 100, 0));
SetWorkingImage(); // 恢复绘图背景
putimage(mover.x + int(0.5 * WIDTH) - 150, mover.y - int(0.5 * HEIGHT), 150, 100, &map, 0, 0); // 画出小地图
setlinecolor(LIGHTBLUE);
setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 4);
line(mover.x + int(0.5 * WIDTH) - 151, mover.y - int(0.5 * HEIGHT), mover.x + int(0.5 * WIDTH) - 151, mover.y - int(0.5 * HEIGHT) + 99); // 地图边框线
line(mover.x + int(0.5 * WIDTH) - 151, mover.y - int(0.5 * HEIGHT) + 99, mover.x + int(0.5 * WIDTH), mover.y - int(0.5 * HEIGHT) + 99); // 地图边框线
setlinestyle(PS_NULL); // 恢复笔
TCHAR str[32];
swprintf_s(str, _T("质量:%.1fg 击杀:%d"), mover.r, eaten);
settextcolor(BLUE); // 改字体
outtextxy(mover.x - int(0.5 * WIDTH), mover.y - int(0.5 * HEIGHT), str);
settextcolor(BLUE);
outtextxy(mover.x - 36, mover.y - 8, _T("user name"));
}
void setall() {
srand((unsigned)time(NULL)); // 随机数
mover.color = RGB(rand() % 256, rand() % 256, rand() % 256); // 随机颜色
mover.life = 1; // 赋初值1
mover.x = int(WIDTH0.5);
mover.y = int(HEIGHT0.5);
mover.r = 20;
for (int i = 0; i < AINUM; i++) { // AI 的属性
ai[i].life = 1;
ai[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
ai[i].r = float(rand() % 10 + 10);
ai[i].x = rand() % (MAPW - int(ai[i].r + 0.5)) + int(ai[i].r + 0.5);
ai[i].y = rand() % (MAPH - int(ai[i].r + 0.5)) + int(ai[i].r + 0.5);
}
for (int i = 0; i < FNUM; i++) // 食物的属性
{
food[i].eat = 1;
food[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
food[i].x = rand() % MAPW;
food[i].y = rand() % MAPH;
food[i].type = rand() % 10 + 1;
}
pBuffer = GetImageBuffer(NULL); // 获取显存指针
setbkcolor(WHITE); // 白色背景
cleardevice(); // 初始化背景
settextcolor(LIGHTRED); // 改字体
setbkmode(TRANSPARENT);
settextstyle(16, 0, _T("宋体"));
}
void delay(DWORD ms) // 绝对延时
{
static DWORD oldtime = GetTickCount();
while (GetTickCount() - oldtime < ms)
Sleep(1);
oldtime = GetTickCount();
}
void start()
{
setbkcolor(WHITE); // 白色背景
cleardevice(); // 初始化背景
settextcolor(RED); // 改字体
setbkmode(TRANSPARENT);
settextstyle(128, 0, _T(“宋体”));
outtextxy(320, 40, _T(“贪婪球”));
settextstyle(32, 0, _T(“宋体”));
outtextxy(740, 135, _T(“Ver 1.0”));
settextcolor(BLUE);
outtextxy(170, 240, _T(" ↑ 上移 ↓ 下移 ← 左移 → 右移 "));
settextcolor(GREEN);
outtextxy(112, 340, _T(“躲避大球 追补小球 贪吃食物 增强实力”));
settextcolor(BLACK);
settextstyle(32, 0, _T(“宋体”));
outtextxy(384, 500, _T(“按任意键开始游戏”));
settextstyle(20, 0, _T(“宋体”));
outtextxy(810, 10, _T(“2018级软件工程1班”));
outtextxy(810, 30, _T(“贺巍”));
outtextxy(810, 50, _T(“201810414113”));
_getch();
}http://www.biyezuopin.vip