10年C++编程开发的亲自真实经历:C++实现跨平台五子棋网游!
image
闲来无事,因自己想要在服务器开发方面进行更深入的学习,积累更丰富的经验。决定写一套网络游戏的c/s。
下面是小编整理好的一套学习C/C++的资料,加小编C/C++学习群825414254获取一整套C/C++系统性学习的资料教程哦!
image
由于主要目的是服务器的开发,因而游戏我选用规则较为简单、画面特效没有要求的回合制游戏:五子棋。我曾经在刚接触编程的时候自己在控制台下做过这个游戏,当时写的ai特nb我自己根本下不赢他。确定是制作五子棋了, 但是还要满足跨平台的特性,毕竟移动互联时代,得终端者得天下。游戏做成全平台才能更好的将各种玩家聚集在一起。跨平台?b/s是人们通常会第一个想到的跨平台方式,确实现在市面上有很多基于b/s的页游,大部分使用的是flash作为游戏引擎。但手机上很少有人使用浏览器玩游戏。(其实根本不会flash,html也烂得很,曾经给别人用php做的数据管理网站根本就没有像样的界面)于是选择了c++的跨平台游戏引擎cocos2dx,这引擎简单好用,而且由于是c++作为游戏逻辑,移植特方便,以前也用过这个引擎(某比赛)。最终选用的版本是cocos2d-x 3.4。
既然是网络游戏的服务器,那么就得高效,而且是在linux下,因而我选epoll模型进行服务端的开发,epoll的部分写在这篇文章里:epoll模型的了解与封装实现,使用的linux系统为CENT OS 6.4,内核为linux2.6。
关于游戏开发步骤的思考:
按照自己以前习惯的套路来说,通信方式与协议的设计应该是放在首位的,而后是服务器、再到用户端(没有美工)。
而自己以前曾经玩到很多的单机游戏,升级版本后,游戏便添加了网络游戏功能。这似乎说明了很多游戏与网络协议之间是相互独立的。甚至网络协议是根据实际的游戏逻辑设计的,而不是游戏根据协议来设计自身的逻辑。
最终决定先把单机的版本做出来。于是制定了如下的开发流程:
1、游戏的算法与数据结构设计与实现
2、游戏交互设计与实现
3、单机游戏的实现
4、游戏通信协议设计
5、服务器实现(不可忽略掉的重点,自己写游戏的目的)
6、网络游戏功能实现
7、平台移植
1、游戏的算法与数据结构设计与实现:
五子棋这个游戏是一个二维平面上的游戏,我们将棋盘看做一个数组,每一个格子的状态分为两种:没棋和有棋,有棋因不同玩家而区别(数量不限,可直接作为多人多子棋的游戏基类)
代码:
image
检测胜利的逻辑很简单:找到一个下有棋的位置,检查这个位置下、右、左下、右下能否有连续相等的5个棋,即为游戏胜利。游戏一旦胜利是不可以继续下棋的,所以只会有一个玩家胜利。下面给出判断代码:
image
image
2、游戏交互设计与实现
涉及到游戏交互,这里就要使用到游戏引擎了。首先需要把游戏的少量图片资源大致搞定,这里用画图这画了几个不堪入目的图片资源:
image.png
别看这画的丑,我可是用鼠标和window自带的画图画出来的,到时候在游戏中看起来是毫无违和感的(笔者小学就会画H漫了)。
这里就要用到cocos2dx的东西了。首先为每一个下棋的格子设计一个个块状的节点,而后设计游戏主体布景层:
1
class ChessNode:public Nodeclass ChessMain:public Layer
作为游戏棋盘,每一个格子的形态都是一样的,我只要要将它们拼接成矩阵就成了一个完整的棋盘。因而在游戏布景层里,我开了一个Vector的ChessNode,将其依次紧凑地排列在屏幕上。在游戏初始状态时,chess_1.png、chess_2.png是不会显示的,如图(截图我直接使用现成游戏的截图):
image
这样的棋盘看起来是不是很没有违和感?
当下棋后,即可以把对应的棋图显示出来:
image
后面发现如同真正的下棋是下在十字交叉处的。。
这部分的注意事项主要就在于触摸检测与棋盘屏幕大小。触摸的话计算相对棋盘布景层的坐标可以得出下棋的位置。棋盘就以静态值480px为标准,在其余地方调用的时候缩放就可。
image
image
image
这里的触摸函数会由以后ChessMain的子类重写。
3、单机游戏的实现
单机游戏,只要写好对手的AI逻辑就可。幸亏是五子棋不是围棋,一般的对局AI很好写,但是对于大棋盘来说,计算出必胜态依然非常困难。因为自己主要目的是写网络端。因而我把单机功能实现后并没有写AI,把接口留着的,只接了一个随机函数,等以后有空自己做个AI逻辑加上。
总的来说这部分就是加上了进入游戏前的菜单以及单机游戏的选项和游戏结束的对话框:
image
image
image
现在一个能玩的游戏已经完成,接下来是重点的网络部分。
4、游戏通信协议设计
由于是PC、手机都能玩的游戏,考虑到糟糕的手机网络环境,通信采用用户端单方发起请求,服务器回复的方式,使服务器不用考虑确保手机信号不好或者IP变更的情况,相似于web方式。
游戏没有设计固定的客户,采用的是游戏每次向服务器申请一个游戏ID,使用这个游戏ID在互联网上和其余客户对战。于是协议报文设计了两种:普通请求/回复报文gamequest、游戏数据报文nextquest。
image
NEWID:申请一个新的游戏ID的请求与回复
NEWGAME:申请开始游戏的请求与回复
NEXTSTEP:升级游戏对局数据的请求与回复
GETNEXSTEP:获取游戏对局数据的请求与回复
GAMEEND:终止或者结束游戏的请求
关于游戏请求与游戏对局时的通信,由于采用的是请求加回复的方式,服务器不能主动通知用户端有新的游戏开始或者是对手已经喜下了下一步棋,因而需要用户端主动向服务器获取相应的信息。于是这部分被设计为用户端定时向服务器发送升级数据的请求,服务器一旦接收到请求,就把通过该请求的TCP连接发回去。这样尽管添加了网络的流量,但为了数据的稳固性必需做出牺牲。好的是该协议报文很小,而且由于是对局游戏,就算有几万人同时在玩,实际单位时间的数据量也不会太多,最重要的是在解决并发数据的情况。
5、服务器实现:
这是最重要最核心的部分。一个高效、稳固的游戏服务器程序直接决定了游戏的体验。在实际的游戏服务器开发中,游戏逻辑与网络通信逻辑可能分工由不同的人员开发。因而,游戏逻辑与网络通信逻辑应在保证效率的情况下尽可能地实现低耦合。我这里尽管是独立开发的,是由于游戏的逻辑很简单,但假如比方去开发一个像GTAOL这样的游戏服务器,原本做网络通信的人想要做出GTA的游戏逻辑那就相当地困难,需要写解决世界、物体、角色,还要和游戏端的逻辑一致,累成狗狗。
所以说游戏的逻辑与网络的通信需要尽可能地独立,就这个五子棋服务器而言,网络通信端使用PPC、select、epoll都和游戏逻辑无关,只需能接收分类并交给游戏逻辑解决,并将游戏逻辑解决好的数据发出就可。该服务器选用的epoll实现的,因篇幅起因,网络通信部分已经在这篇文章中说明清楚:epoll模型的了解封装与应用。
关于服务器的游戏逻辑,首先看看我们的服务器要做哪些事情:
1、客户游戏ID的申请与管理
2、对局数据的解决与管理
大致就以上这两种事情。但是由于游戏的用户端数量很多,不同的用户端之间进行对局,必需要清晰地解决与管理这些数据。我这里建立了一个idpool,用于id的储存于申请,以防发生错误给客户分配无效或者是重复的id。
对局数据的解决与管理:
在两个客户都有id的情况下,双方都能申请进行游戏。这是服务端要做的就是匹配好这些客户并通知这些客户开始游戏。为方便说明,我先把代码粘上来:
image
image
image
p2p类:它的作用是用来匹配玩家的。当有用户端申请进行游戏时,服务器会先调用makepair函数来寻觅可以进行匹配的另一个玩家,假如找到了合适的玩家,接下来就会调用setp2p简历这两个玩家有对局关系。假如没有匹配到,则会调用setwait等待其余的客户进行匹配。该类使用的数据结构为简单的hash映射。
setpstatus类:用于存放对局数据的类,使用的pool方式,用户端下棋的信息将会储存在这里,用以用户端获取对方下棋的信息。p2p类的info会直接映射到pool的对应下标。不同id的用户端查找数据会相当地迅速。
gamemain类:游戏的主类。给出api函数dealdata用以接收用户端的数据并将解决后的数据返回。
image
image
image
这里的dealdata是线程安全的,方便网络通信部分用的各种方式调用。由于这该五子棋服务器的游戏逻辑的主要功能就是数据的存储转发,没有什么需要在后端一直运行的要求。因而该程序耦合很低,使用很简答,只要要创立、调用解决函数、获取解决结果就可。
6、网络游戏功能实现
现在回到游戏用户端,前面已经实现的单机游戏的功能。现在要做的就是加入网络功能,其实就是把单机的ai部分接到服务器上。
首先是游戏id的获取。通过向服务器发送NEWID请求。会受到服务器分配的id。将这个id作为自己的游戏id,在告知服务器退出游戏或者是服务器在长时间未受到该id的情况下自动释放前都有效。
image
图中两个用户端分别分配到id2与3。
当用户端分配到id后,即可以向服务器发起游戏匹配请求NEWGAME。为了防止匹配不到玩家,设置发送匹配请求最多只维持一分钟,在一分钟结束后,用户端向服务器发出中止匹配的请求。
当有两个用户端在这交叉的时段进行进行匹配,便可能匹配在一起开始游戏。
游戏匹配成功后,用户端将收到服务器发过来的对局基础信息,包括了对手id、先手还是后手。当游戏开始后,先手的下棋而后将数据提交到服务器,又后手的升级数据,而后照这样依次循环下去直到游戏结束。
image
id2与id3匹配到了一起。
在游戏结束时,赢的一方会显示胜利,输的显示失败,双方都不再升级数据。退出对局后便能开始下继续匹配游戏。
image
游戏用户端需要注意的是对局数据的校验还有sock链接的问题。当在糟糕的网络环境下,用户端不应定能获取到正确的数据,因而要根据数据包总的mac进行校验。而tcp链接再侧重状态下将时断时续。因而要注意当连接中断后及时与服务器进行重连。
还有关于跨平台的问题。我将socket封装成类,不论是win还是linux都是同样的调用方式。在sock类中用ifdef区分开两个系统的不同api调用。
以下是用户端跨平台sock的封装:
image
image
image
7、平台移植:
整个项目搞定了就是爽哈,平台移植便是非常轻松的事情,只需自己写的代码没作死,用特定系统或者编译器的api或者是语法与库,平台移植就相当得快速。尤其是cocos2dx引擎,早已把移植的工作全都准备好了,只要要自己调调错就可(回想起了以前自己一个人把c++往android上交叉编译,叫那个苦啊)。
控制台傻瓜编译:
image
编译成功。
image
手机与用户端实现网络游戏对局。
image
哈哈,手机也能和电脑一起联网玩游戏了。
这次做的这套五子棋网络游戏还有很多欠缺的东西,用户端还缺乏肯定的容错能力,客户体验也不够人性化。在网络方面,通信的方式并不适合时效性要求较高的游戏,像少量及时对战游戏,请求/回复的方式需要很频繁的请求才能保证时效。这样也没错,糟糕的网络环境也不能用来玩这些游戏。自己对自己的美工挺满意的,嘿(哪里有美工啊?这个图片都算不上好不好)。
总的来说,这是一次很棒的开发经历,希望毕业以后也能有这样的闲功夫,去做自己真正想做的。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 10年C++编程开发的亲自真实经历:C++实现跨平台五子棋网游!