博主学习c语言已经有一段时间了,出于对自己学习检验的目的,自制了一款c语言赛车游戏。
由于本质是检验和尝试,所以并没有注重游戏的界面。下文是开发文档,在博主的github网页可以下载源码,注意本项目使用工程的方式开发,打开也请使用打开一个项目工程的方式
。
https://github.com/whatattitude/whatattitude.github.io
摘要: 随着计算机的普及,游戏已经成为广大用户必不可少的使用部分之一,生活中存在许多闲散的时间,游戏作为打发时间与放松身心的一种娱乐方式广为流传。其中赛车游戏应为其刺激,与画面的动感更是受到大众的喜欢。
本文主要阐述了一款公路赛车游戏的设计与实现,较为系统的介绍了菜单设计、赛车的移动与速度改变、赛车的随机生成与动态移动、文件数据的存储读取与排序显示等功能。玩家打开游戏后可以选择开始游戏、查看排行榜或者查看帮助,开始游戏后会根据按键操作进行游戏,最后当血量为0时,或者游戏时间耗尽时,结束游戏并返回主菜单。
这款游戏用c语言进行开发,结合EasyX图形库以vc++6.0作为系统开发平台。
关键词:EasyX图形库;公路赛车游戏;c语言游戏设计;
目 录
绪 论... 1
1 需求分析和概要设计... 2
1.1 整体要求... 2
1.2 系统设计架构... 2
1.3 模块概述... 3
1.4 性能需求... 4
1.5 数据分析... 4
1.6开发平台... 4
1.6.1 Visual C++6.0. 4
1.6.2EasyX.. 5
1.7运行环境... 5
2 详细设计... 6
2.1界面设计... 6
2.1.1主菜单界面... 6
2.1.2游戏界面设计... 6
2.1.3游戏帮助界面设计... 6
2.1.4排行榜界面设计... 6
2.2功能模块的实现... 7
3系统重点... 9
3.1每隔两秒随机生成赛车... 9
3.2 赛车加减速与动态移动... 9
3.3 文件信息的读取与存储... 9
3.4 游戏记录数据冒泡排序(双向链表游戏数据)... 10
3.5 链表摧毁... 10
3.6 游戏排行榜的翻页显示(双向链表游戏数据)... 10
总 结... 11
致 谢... 12
绪 论
在本文详细介绍了一款公路赛车游戏的设计与实现。
在这款赛车游戏以vc++6.0作为系统开发平台,基于c语言进行开发,用于c语言期末项目。
本项目的开发经历了项目的文档编写、游戏设计、代码编写、系统测试几个阶段。
游戏的功能模块共4部分,分别是开始游戏、历史排行榜、游戏帮助、退出游戏。本游戏用EasyX图形库实现的游戏动画,c语言的库函数实现菜单设计、菜单设计、赛车的移动与速度改变、游戏时间计算与本局积分的计算存储、赛车的随机生成与动态移动、文件数据的存储读取与排序显示等功能模块中的关键算法。本文先对游戏功能模块进行简要介绍后再对关键功能的实现进行详细解读,方便读者理解。
1 需求分析和概要设计
1.1 整体要求
本项目开发用于初步了解c语言的项目开发流程,实现了一款赛车游戏。
本款游戏菜单界面为开始游戏、历史排行榜、游戏帮助、退出游戏四个选项;选择开始游戏后,玩家通过键盘输入相应的字符开始游戏并控制赛车移动、加速、减速,通过碰触蓝车加积分,碰触红车会扣血,右方会操作提示游戏相关操作,左方提示剩下的时间、道具数(碰到蓝车数)、当前积分等游戏数据,满足结束条件(血量为0或者时间耗尽)游戏结束。在菜单界面点击历史排行榜后可以查看到所有按积分高低的历史记录。不明白规则的用户可以从主界面直接键入对应的数字打开游戏帮助查看相关提示。该游戏基本满足了玩家对赛车游戏的需求,比如赛车的四个方向移动与加、减速与道具拾取。
1.2 系统设计架构
本游戏由四个部分构成,它们分别是开始游戏、历史排行榜、游戏帮助、退出游戏。
1.3 模块概述
本游戏由四个部分构成,它们分别是开始游戏、历史排行榜、游戏帮助、退出游戏
开始游戏包括游戏准备,游戏进行和游戏结束3个阶段。
(1) 游戏准备
当玩家点击从主菜单点击开始游戏后游戏数据初始,界面初始化绘制,等待玩家键入相应操作以正式开始游戏。
(2) 游戏进行
正式开始游戏后,屏幕上方开始刷新随机车辆下移,玩家通过按键操作赛车躲避,撞到赛车会相应改变数据,结束条件判定如果没满足结束条件继续游戏,满足条件进入游戏结束阶段。
(3) 游戏结束
此时本局数据会写入相应文件中存储,然后屏幕提示结束按任意键后返回主菜单界面。
历史排行榜。玩家可以在这个模块查看按游戏积分高低排序的游戏记录,键入对应的英文小写字符以前后翻页,按e退回主菜单。
游戏帮助。查看有关游戏的操作等的相关介绍,然后按任意键返回。
退出游戏。点击以正常退出游戏。
1.4 性能需求
游戏需要能实现赛车移动与加减速度,生成随机赛车,并作碰撞检测与处理相应的数据满足玩家对赛车类游戏的基本需求。
游戏界面中需要有信息提示,使得玩家能快速上手,较短时间明白游戏规则玩法。
同时还需数据存储和读取,数据排序与存储,数据排序与分页显示让玩家能够看到曾经的历史记录,并且将记录排名,玩家可以对比三种计分因素的相对占比,以调整游戏策略。
1.5 数据分析
本游戏数据有三种,第一种是用于生成随机赛车的结构体数组;第二种是存储本局游戏记录方便写入文件的结构体;第三种是用于读取文件中记录并排序的双向链表。
第一种是用于生成随机赛车的结构体数组包括:随机的纵向坐标变化增量,实时的坐标信息x、y,标志赛车类型的整形变量。
第二种是存储本局游戏记录方便写入文件的结构体包括:剩下生命条数,拾取道具数(即是碰到蓝车次数),本局积分,游戏进行的时间。
第三种是用于读取文件中记录并排序的双向链表包括:空的头尾节点,指向前后的指针,从文件中读取而来的历史记录信息结构体(和第二种中报存的相同)。
1.6开发平台
1.6.1 Visual C++6.0
Visual C++6.0是微软公司推出的开发Win32应用程序(Windows 95/98/2000/XP/NT)的、面向对象的可视化集成工具。它的最大优点就是提供了功能强大的MFC类库,MFC是一个很大的C++类层次结构,其中封装了大量的类及其函数,很多Windows程序所共有的标准内容可以由MFC的类来提供,MFC类为这些内容提供了用户接口的标准实现方法,程序员所要做的就是通过预定义的接口把具体应用程序特有的东西填入这个轮廓,这将简化编程工作,大大的减少程序员编写的代码数量,使编程工作变得更加轻松容易。
1.6.2EasyX
EasyX 是针对 C++ 的图形库,可以帮助 C++语言初学者快速上手图形和游戏编程。
比如,可以用 VC + EasyX 很快的用几何图形画一个房子,或者一辆移动的小车,可以编写俄罗斯方块、贪吃蛇、黑白棋等小游戏,可以练习图形学的各种算法,等等。
1.7运行环境
Microsoft Visual C++ 6.0
Microsoft Visual C++ 6.0,简称VC6.0,是微软于1998年推出的一款C++编译器最低配置为:CPU:P 233以上.32MB以上内存。
Microsoft Visual C++ 6.0对windows7和windows8的兼容性较差。在Windows7使用VC6.0只需要忽略兼容性提示即可正常使用, [4] 但是在Windows8(含Windows8.1)使用VC6.0则需要改原MSDEV.EXE文件名并改兼容性才能正常使用。 [5] 在Windows10的第一个版本也可以正常使用VC6.0,但Windows10系统升级更新后中文版VC6.0无法正常使用,提示“0xc0000142”的错误,需要将原MSDEV.EXE文件替换为英文版或者汉化版才能正常使用 [6] (该版本在Windows8(含Windows8.1)照样需要改原MSDEV.EXE文件名并改兼容性才能正常使用。)。
EasyX
系统支持
操作系统版本:Windows XP(sp3) 及以上操作系统。
编译环境版本:Visual C++ 6.0 / 2008 ~ 2017(x86 & x64)。
2 详细设计
2.1界面设计
游戏界面为vc++6.0调用easyx图形库绘制的界面,直接使用原始黑色背景,字体默认打印白色,赛车由插图的方式生成,简约的风格以达到开发快捷与方便的目的。
2.1.1主菜单界面
主菜单界面用于指引用户进人相应的模块,并提示用户操作方式。主菜单界面调用函数outtextxy以默认的坐标轴在适当的x,y坐标处打印提示信息:1:开始游戏、2:历史排行榜、3:游戏帮助、4:退出游戏、键入对应数字操作游戏。方便玩家进行相应操作选择模块。
2.1.2游戏界面设计
游戏界面同样使用函数outtextxy以默认的坐标轴在右边适当的x,y坐标处打印用于提示用户进行相应的操作:w上移s下移a左移d右移j加速k减速按l开始按e暂停,在左边适当的x,y坐标处打印用于展示玩家所得积分、剩余时间、道具分数、生命四个变量。
2.1.3游戏帮助界面设计
游戏帮助界面主要为玩家指明游戏的相关操作与较为详细的说明,同样使用函数outtextxy以默认的坐标轴在右边适当的x,y坐标处打印包括(j加速k减速a左移d右移j加速k减速按l开始按e暂停游戏,其他赛车按时间生成,间隔2秒撞到红色赛车扣血,蓝色赛车增加道具积分当血量为0,或者时间耗尽即为游戏结束,计算积分积分与当前剩余血量,时间与捡到的道具数相关)的游戏规则,最后打印提示按任意键返回主菜单。
2.1.4排行榜界面设计
排行榜界面用于显示玩家历史的游戏记录,从文件中读取并排好顺序的历史记录直观的由上而下,由高到低展示在玩家眼前,每页5排显示一排一个攻击5个,并在最下面提示当前页码与总的排行榜页数、当前界面的合法操作--------按n到下一页,按p到上一页,按e返回主菜单。当玩家进行相应上移下翻页的合法操作时便以5个一组的形式刷新界面重新显示新的5条信息并更新排行榜当前的页码。
2.2功能模块的实现
本游戏主要分为四个模块,它们分别是开始游戏、历史排行榜、游戏帮助、退出游戏
开始游戏包括游戏准备,游戏进行和游戏结束3个阶段。
(1)游戏准备
当玩家打开应用或者上局游戏结束后相应的玩家车辆坐标位置、拾取道具数、生命条数被重置初始。键入对应开始游戏的数字1时游戏界面中静态不变的例如右边的操作说明都被绘制在界面上,然后是将左边需要实时变化的积分、道具、生命值初始化打印出来,等待玩家键入相应操作以正式开始游戏。
(2)游戏进行
收到玩家键入的正确开始游戏字符后,通过clock函数设定游戏开始时间start与结束时间end,然后按计分关系公式计算计分,并在初始的位置插上玩家的赛车,调用一个自定义的函数先定义初始化包括随机赛车结构体数组,间隔时间变量,时间判断辅助变量在内的一系列必要变量,再配合一个以生命为0或者耗时变量不小于达到头文件宏定义的时间常量的表达式为结束条件的while循环。在这个循环中上方开始刷新随机车辆下移,玩家通过按键操作赛车躲避,撞到赛车会相应改变数据,结束条件判定如果没满足结束条件继续游戏,满足条件进入游戏结束阶段。
(3)游戏结束
此时本局数据会写入相应文件中存储,然后屏幕提示结束按任意键后返回主菜单界面。
历史排行榜。
玩家进入这个模块后会以只读的形式打开保存的二进制文件,将里面存储的游戏信息内容读取出来生成头尾节点为空的双向链表,然后返回头结点指针,然后使用冒泡排序法对双向链表进行按积分由高到低进行排序,然后以只写的方式打开文件清空文件的所有内容,再把排序好的记录写入文件,并摧毁链表。随后再次以只读的方式打开文件,读取内容生成头尾节点为空的双向链表,根据读取链表的节点个数计算出显示的页码总数。接下来用while循环在屏幕上进行打印显示每打印5条或者已经到了尾节点就结束,根据玩家键入对应的英文小写字符以前后翻页或按退回主菜单。
游戏帮助。清屏后打印有关游戏的操作等的相关介绍,然后按任意键返回。
退出游戏。点击以正常退出游戏。
3系统重点
3.1每隔两秒随机生成赛车
在打开应用后键入1以进入开始游戏模块,利用clock函数设置时间变量start与end,游戏进行的时间costtime则为(end-start)/1000,作为初始处理,设定两个辅助整型量一个叫key,一个叫判断均初始化为0;key用来表示下一个两秒的时间值,panduan变量用于确定是否要生成随机车。当同时满足判断为0与游戏进行时间costtime与时间点key相同时,进入if语句key设置为两秒后的时间,判断设置为1,等到过了1秒后,在将panduan设置为0,避免同一个时间多次重复生成赛车,随机赛车使用for循环对随机赛车的结构体数组进行赋值生成,生成时每个赛车结构体横坐标对应一个区间,纵坐标为0,初始化的下移速度分量为40到70之间,随机生成0到6之间的数用于判断是道具蓝车还是扣血红车。
3.2 赛车加减速与动态移动
所有随机赛车移动均由每次循环时y坐标加上各自的初始下移变量,再通过檫除与重绘的方式实现动态移动。而加减速则由设定的程序休眠函数sleep当中的时间变量time的增减实现的。玩家赛车的移动则由玩家键入对应字符后,做出相应改变实现。键入w减小一个speedy大小的y坐标,键入s增加一个speedy大小的y坐标,键入a减小一个speedx大小的y坐标,键入d增加一个speedx大小的y坐标,键入j则time减小5毫秒,键入k则增大10毫秒,在变化之前判断是否有到达临界值,以避免速度过快或过慢。
3.3 文件信息的读取与存储
文件信息中存储的是游戏积分的相关数据,在每轮游戏过后以只写的方式打开文件追加在文件结尾一个定义的结构体大小的数据,随后关闭文件。
文件信息的读取则先以只读的方式打开文件随后从文件中读取一条信息,用一个以!feof(fp) 为结束条件的while循环进行依次读取,循环中如果节点指针是指向null的头结点则用malloc函数为head和tail动态申请内存空间,将头结点的前指针指向null,头结点的下一个指针为tail,tail的前指针为头结点,tail的尾指针指向null,不然就为节点指针p用malloc函数动态申请内存空间,将读取出来的信息结构体复制到链表节点的数据域,然后p的后节点指向tail,p的前节点为原来tail的前节点,tail原来前节点的后节点现在指向p,tail现在的前节点指向p,并且每次生成一个节点增加len用于统计除去头尾节点的节点数。
3.4 游戏记录数据冒泡排序(双向链表游戏数据)
文件读取过后生成的双向链表用冒泡排序法进行排序, 先判断链表是否为空,为空则不必排序。当链表不为空时,从头节点开始依次设置m、p、q、n四个指针变量,用双重while循环实现冒泡排序,最外层结束条件为p知道尾节点的前一个节点,内层结束条件为q是为节点的时候。当满足p节点中的积分小于q中的时,交换两个节点,先将指向左边的p节点的指针绕过p指向p的前节点和后节点,以将左侧节点p移出,然后将指向右边的q节点的指针绕过q指向q的前节点和后节点,以将右侧节点q移出,此时m和n之间有联系,忽略p、q中的指针指向,再通过m和n点中的前后指针将q插入到原来p的位置(即m之后,同理将p插入到原来q所在位置(即n之前),然后恢复p、q指针对应的逻辑节点顺序。无论是否要交换p、q的位置都在每次内层循环下移q、n指针,外层下移m、p指针。
3.5 链表摧毁
先判断链表是否为空,为空则不必操作;不为空时,用free函数释放头指针的内存空间后将头指针下移,直到头指针为null时,链表摧毁操作完成。
3.6 游戏排行榜的翻页显示(双向链表游戏数据)
文件信息读取后会排序生成双向链表,并得到链表当中的有效信息条数。根据有效信息条数可以计算出最大页码数,5条之内为1,大于5条的对5取模不为0则页码为对5取整多1,此外即为对5取整。然后用sprintf函数将数据转换成字符串类型再打印出来,每5条一页。当键入n进行下翻页是如果当前没到最后一页都可以下移,进入下一次循环在节点指针已经到了下一页头的基础上进行重绘输出。而键入y进行上上翻页时不在第一页则根据当前页数在中间时将节点指针前移10个节点输出,在最后一页时算出最后两页的数据数在前移相应的节点数,进行显示。