专栏首页Golang语言社区【游戏编程板块】关于游戏开发的客户端/服务器端的版本控制

【游戏编程板块】关于游戏开发的客户端/服务器端的版本控制

【客户端】 1.关于游戏引擎 在15年3月开始准备做h5游戏的时候,首先遇到的问题就是引擎选型的问题。 当时市面上的2d引擎主要有3个:白鹭egret,layabox和cocos2d-js。 一方面,是因为我以前用cocos2d-x(c++)做了一年多的手游客户端,所以,很自然就选择了cocos2d-js。另一方面,是因为当时市面上其他两个引擎的成功项目还不多。 cocos引擎的每一次版本更新,我们都会第一时间在我们的游戏里面进行测试。 如果发现游戏在android手机上的性能有明显提升,我们就会跟着引擎版本一起升级。站在巨人的肩膀上,我们可以事半功倍。 从15年3月的v3.5,到15年9月的v3.8,到15年11月的v3.9,直到最近16年7月的v3.12。我们一共更新了3次游戏引擎! PS:js-tests里面的OpenGl Test直到v3.12才在android真机上能看到运行效果,泪流满面! 2.关于数据加密和通信协议 因为是强联网游戏,所以只能是websocket。因为我们原来的手游客户端和服务器之前是tcpsocket,传输的内容是sha1加密过的自定义格式的二进制数据。 所以项目的第一个难点就是怎么用js实现json字符串的二进制编码和解码,以及sha1加密和解密。 TODO:其实没有必要每一条上下行都加密和编码解码,这会造成客户端和服务器端cpu压力过大。只需要保护一些重要的事件(如登录、充值、扣金币等)即可! 游戏的第一个demo做好了,上线一测试,问题来了:有些android手机的默认浏览器根本不支持websocket! 最开始我的解决办法比较简单粗暴,不支持就弹提示:"你的手机浏览器不支持websocket,请换chrome浏览器!" 市场表示接受不了:真实玩家都跑了!除了公司的测试人员,谁都不会为了玩一个h5游戏还去专门下载一个浏览器!更何况除了浏览器,还有微信和qq,怎么破? 最终的解决办法,就是通信层从websocket改成websocket+http双协议,对外封装成Net。业务层对websocket的调用都改成对Net的调用。 Net默认连websocket,如果不支持,就自动切换到http长轮询。不管是websocket还是http,传输的内容还是之前加密过的二进制数据。 虽然http的长轮询在实时战斗的时候,会有卡顿,但是聊胜于无,至少这部分玩家能进到游戏里面,可以玩单机副本,和其他系统。不会因为不支持websocket而进不来! 根据我们的数据分析统计,这部分玩家居然有10%。可能不同渠道导入的用户,这个值会有不同!而且随着时间的推移,这个比例应该越来越少! PS:不支持websocket的android手机,跟IE6一样令人讨厌,都是阻碍生产力发展的,必将被历史淘汰! 3.关于android和微信 中国的市场现状就是,H5游戏必须考虑android手机,必须考虑微信和qq这两个传播渠道。只关注用pc浏览器开发和苹果手机测试没问题,是不明智的,也是对公司的不负责任。 开发的时候可以用pc浏览器调试,但是发布之前必须在android手机的微信里面,打开游戏看是否有兼容性问题,同时确认流畅度。 如果pc和苹果手机都能跑到50~60帧,但是android的微信就只有10多帧,那就必须在图片尺寸和动画效果等方面做取舍。 我们的标准是保证游戏在android中端机的微信里面打开,最低25帧。 今年4月份微信的浏览器内核自动从webkit升级成Blink,这是对H5整个行业的重大利好! 窃以为,白鹭、layabox和cocos2d,包括unity,虚幻,这几个游戏引擎之争,现在来看,都是在争VR和3D,但是最终是看谁对奇葩辈出的android的全覆盖支持最好,谁就能最终占领中国乃至全球市场! 4.关于音乐和音效播放 cocos2d-js引擎自带的CocosDension有bug,不能同时播放一个以上的音乐。而且在中低端的android的微信里面,声音品质会变差(像破锣一样发呲) 我们的解决方案就是引入第三方的howler.js 5.关于资源分场景加载 cocos2d-js默认的resource.js里面,所有资源都是在一个数组里面,所以预加载的时候必须全部都加载完了才能进游戏!刚开始开发的时候,这样没有问题。 但是到了后期,随着系统的增加,资源文件也越来越多,对第一次玩游戏的玩家来说,因为浏览器没有缓冲,需要全部加载,在wifi环境都需要等待1分钟以上,这会导致大量的新玩家流失! 我们的解决办法是,分场景加载资源。在resource.js里面,将资源按场景分成N个数组,每次加载某个场景的时候,只预加载对应数组里面的资源。 6.关于json文件压缩 随着游戏开发的进行,场景越来越多,ccs生成的json文件也越来越多,同时各种地图、商品、道具、奖励等数据的完善,对应的json文件内容越来越多,文件大小越来越大! 最后游戏发布的时候,发现居然有70个场景json文件,合计1.3M。有27个配置json文件,合计755K。等待这几十个文件加载的时间可不短! 解决办法,引入第三方的jszip,可以将多个json文件合并成一个zip,文件大小只有原来的8%。

写了个Python脚本,把ccs和configs两个目录下的json文件先转成一个一行,再用jszip打包成2个zip文件,游戏一开始先用jszip加载这两个zip,解压的json放到全局数组里面。

注意这里面有个坑,策划的excel里面不能出现半角逗号,否则jszip打包会报错。强制策划不输入半角逗号不太合理,解决办法是go生成json的时候替换半角逗号为全角逗号。

然后复写了引擎的cc.loader.loadJson这个函数,对打包的json文件特殊处理(不用额外发起http请求,直接从全局数组里面拿) 有了5、6这两步的优化,现在新手在第一次Loading页只需要等待4秒就能进入游戏。 7.关于混淆 cocos封装了google的混淆编译脚本,但是这里面有个坑:就是加了--advance参数之后,所有变量名都会被混淆,包括object的内部函数名称和变量。

解决办法就是在你不想混淆的函数或者变量(object{}对外暴露的public函数和变量 以及 引用的第三方库的函数 )前面加上一行:

/** @expose */

注意:千万不要xxx.yyy 和 xxx['yyy'] 混着用!否则加/** @expose */也没用,必须全部统一成其中一种写法!

8.关于上线发布流程和cdn缓存 1)本地运行publish.sh:本地混淆编译,本地测试publish/html5/index.html是否正常 2)本地运行oline_t1.sh:根据当前时间生成版本号,publish/html5目录下的res和game.min.js和index.html里面的相对路径都改成http://cdn域名/版本号的文件地址, 将res和game.min.js加上版本号之后,上传cdn服务器。更新测试服t1的index.html,通知测试! 3)本地运行online_s1.sh:更新正式服s1上的index.html。发布完毕。 说明: 1)客户端和服务器端程序员都是mac开发环境,每人的机子上都有一套完整的前后端游戏环境。本地开发,本地调试,没有问题之后通过git提交代码到公司内网git服务器。这样可以最大限度保证多人协作的同时,互不影响开发进度! 2)因为cdn加了时间版本号,所以每一次的发布都是马上生效,不需要等缓存过期。也不担心多人各自发布覆盖对方的代码。发步完马上可以查看效果,大大提高生产效率。以cdn的空间换效率,非常划算!

3)python的fab包是个好东西,可以远程登录服务器执行shell命令,实现本地一键发布。不需要在服务器上通过Git的钩子来实现自动发布!

9.关于断线重连(websocket) 1)客户端每隔58秒有一个心跳上行,保持与服务器的链接 2)多标签的浏览器在切换tab或者浏览器进入后台的时候或者断网,都会导致心跳失效 3)每次客户端发送上行的时候,先判断Net.isConnect()是否为true。如果false就先保存上行事件和数据,然后重连,然后重新登录,然后发送保存的上行事件和数据。这些都是在后台进行,如果重连失败则弹出提示,点击确认之后刷新页面。 10.关于运营商的域名劫持和移动端js加弹出广告 运营商耍流氓,中国又是一个"法制"国家,除了上https,没有别的办法! 我们选择的是沃通的超安SSL,单域一年4888元 http://www.wosign.com/price.htm

11.关于客户端AI

碰碰车只实现了简单AI,就是在单机比赛场里: 1)NPC碰到障碍物之后会固定角度转向,避免卡死在角落。其他时间会随机转向。 2) 自动添加NPC,保证房间内NPC的最低数量 3)同一时刻只有一个NPC处于追踪玩家状态,有定时器触发追踪者的选角切换

服务器端】 1.关于Go语言 我们的H5游戏服务器框架是用Go语言开发的。以前做页游的时候是用的php和Python,都是动态语言。在上线之后,高并发的时候,单机有性能问题,一直没有好的解决办法! 13年的时候我原来的领导开始转用Go来开发手游的服务器端,所以我也跟着转型了! 正如七牛的许世伟所说,用go开发,是可以降低程序员心智负担的!静态编译的优点不用赘述,语言简洁,开发效率高,特别是goroutine和chanel两大神器,专治各种疑难杂症。 Go语言这两年的发展非常迅猛,特别是在中国的很多重量级互联网公司得到大量运用。 而且语言本身已经发展到1.6版本,GC时间从原来饱受诟病的几秒下降到了1毫秒,除非是对延迟要求非常苛刻的应用场景,绝大部分的应用场景都能hold住! 2.关于通讯协议 我们这套框架,最开始是手游的游戏服务器。所以只支持tcp socket。 后来转H5之后,又加入了对websocket协议的支持,两者放在一起,做了封装。 后来为了兼容不支持websocket协议的Android手机,又加入了对http协议的支持,因为http属于应用层协议,tcp是传输层协议,没法简单的封装在一起,所以就写了两套。 但是发送和接受的内容都是一样的:加密之后的自定义格式的二进制数据。 3.关于缓存和数据库 我们的数据库用的是MySQL,缓存同时支持memcache和redis。 在业务层和数据库之间,封装了一层k-v的cache,可以通过配置分别使用memcache或者redis。 每张数据表都有自增长的id主键,并且有一个类似Java bean的struct与之相对应. 针对单表的sql操作,根据类型不同有不同的处理机制: 1)select操作就根据id去缓存里面取值,没有就查mysql,然后缓存结果. 2)update/insert/delete操作,就直接操作mysql,同时删除对应缓存. 如果是对多表的联合查询,一般都是直接走sql,不走缓存。 这样就可以在高并发的时候,减轻数据库的访问压力。 目前是只用到一个主库。后期压力上来可以改成1主多从。 4.关于单元测试 Go语言对单元测试的原生支持,让测试驱动开发成为一种本能! 但是单元测试也有不同的重量级,有的功能需要依赖项目启动时读取的配置文件,有的功能还需要玩家的特殊状态。 再加上多人协作开发的时候,需要控制每个人的私有单元测试边界和公用的单元测试范围,免得互相影响,因为引入不必要的测试而导致测试总时长增加! 在项目开始的时候,强调单元测试的重要性,并做好整个项目的单元测试的组织规划和部署,非常重要,可以事半功倍,节省大量后期测试和纠错的时间! 5.关于excel工具链 策划的数值表都是excel,我们用go写了个转换工具可以通过命令行把指定的excel转成服务器端需要的json格式文件。 其中有些json文件的内容是客户端需要的,于是又用python写了个转换脚本,提取和组合服务器端的json文件内容,生成客户端需要的json格式文件。 有了这两个工具,就可以实现自动化部署,方便测试在单独的数据测试服上调数据! 6.关于服务器端AI 碰碰车的联网比赛场里的AI行为比客户端复杂,策划在AI行为数据表里进行配置,转成json,在比赛场里根据AI配置文件控制NPC的行为。 将计算之后的NPC的位置和角度等状态发送给客户端,客户端只负责呈现! 7.关于联网纠偏 碰碰车的联网比赛,服务器端在房间里会模拟客户端的帧update事件,更新频率在80毫秒一次。 每次update的时候都需要计算房间内所有agent的位置,进行碰撞检测,以及其他逻辑。并把更新后的信息,通过纠偏事件下行给所有玩家。 这个更新频率太短和太长都不好。太短会造成服务器和客户端CPU压力太大和网络流量的增加,太长会造成客户端收到的位置和自身计算的位置差距太大, 如果不做线性补偿,直接以服务器端为准进行更新,会有跳跃感。 8.关于微服务和全球统一服 我们一开始做这套游戏框架的目标就是支持高并发的全球统一服。 单机的性能再怎么优化都有天花板,微服务和容器云是目前互联公司应对类似需求场景的通用解决方案! 按计划分三步走: 第一步:单块系统,通过命令行来打包和发布。目前已在线上运行! 第二步:通过Docker创建容器,实现自动化打包和发布。目前已经在本地mac实现docker创建容器和运行测试,还没有部署到线上! 第三步:进行微服务拆分,通过docker容器云实现动态扩容,支持高并发,实现全球统一服。 9.关于服务监测 go是静态语言,所以编译运行的web应用如果出现panic,整个进程就退出了,所有连接都会被断开。 这跟php这种动态语言提供的web应用还不太一样,一个连接的服务挂了,其他连接不受影响。 所以必须充分的测试,尽量做到线上的服务不要panic。但是人难免会犯错,程序也不可能百分百没有bug,所以必须做好监控和预防措施! 我们的解决方案是有个定时程序每分钟检查一次服务器程序的进程是否还在,如果没有就说明程序panic了,就重启服务器应用,将影响降至最低。 同时邮件通知相关技术。技术收到邮件之后可以通过日志查看panic的原因,解决bug之后,测试通过,再发布更新! 10.关于压力测试 1)测并发链接数上限,并以此为参考,设定登录排队系统的人数限制! 2)测比赛场的玩家数上限,这个需要提前准备足够的AI玩家数据,然后同时进入指定比赛场, 一是看自动分房间功能是否正常,而是看有没有并发死锁和chanel挂起等问题发生。这些问题在开发的时候,本地单元测试是发现不了的!

本文分享自微信公众号 - Golang语言社区(Golangweb),作者:wk3368

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-05-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Golang语言--反射的用处--代码自动生成

    背景: go语言处理db、json的时候,具体代码的变量定义和db字段、json输出的时候可能不一样。 这个时候,我们需要用tag的方式来进行定义。 例如: ?...

    李海彬
  • [转载]Go JSON 技巧

    相对于很多的语言来说, Go 的 JSON 解析可谓简单至极. 问题 通常情况下, 我们在 Go 中经常这样进行 JSON 的解码: package main ...

    李海彬
  • Node.js真的无所不能?那些不适用的应用领域分析

    Node.js是一个服务器端JavaScript解释器,底层采用的还是libevent;它的目标是帮助程序员构建高度可伸缩的应用程序,目前对Node.js 的采...

    李海彬
  • 精通Excel数组公式010:认识数组函数:TRANSPOSE、MODE.MULT和TREND

    数组函数是可以提供多个值的Excel内置函数。下面列出了8个Excel内置的数组函数:

    fanjy
  • 微信小程序wepy框架入门教程(一)

    端开发框架和环境都是需要 Node.js ,先安装node.js开发环境,WePY借鉴了Vue.js(后文简称Vue)的语法风格和功能特性,vue的运行是要依赖...

    祈澈菇凉
  • 《Drools7.0.0.Final规则引擎教程》第4章 4.6 结果条件

    结果条件 在Java中,如果有重复的代码我们会考虑进行重构,抽取公共方法或继承父类,以减少相同的代码在多处出现,达到代码的最优管理和不必要的麻烦。Drools同...

    用户1161110
  • planet 介绍

    用户1908973
  • JS闭包

    JS的闭包用法给开发带来了极大的便利,它的使用方式非常自然,以至于很多同学并不很了解闭包,却可以在实际开发中顺畅的使用了 例如下面的代码,给button添加...

    dys
  • carbon nanotubes 碳纳米管晶体管

    后摩尔技术有很多选择,如三星正在推动的GAA和FinFET发明者胡正明教授正在推动的负电容晶体管都是当中的代表,碳纳米管则是另一拨人坚持的流派。

    白山头
  • vue.js中的computed计算属性如何传递参数

    笔者参考博客https://blog.csdn.net/qq_35775675/article/details/82288571的做法后,的确成功了 。

    acoolgiser

扫码关注云+社区

领取腾讯云代金券