欢迎你们前往云+社区,获取更多腾讯海量技术实践干货哦~javascript
做者:木桶java
《欢乐坦克大战》是一款支持3V3实时对战并首批参与上线的微信小游戏中的做品。由于该游戏为微信小游戏中的重度之做,项目开发周期很是短,因此游戏复杂度、开发难度、性能挑战也是挺大的;项目组在一个月内就完成了单机、网络对战玩法的开发。node
同时,由于客户端开发团队的核心成员有多年的cocos2dx引擎开发经验,因此项目组决定使用CocosCreator V1.6.1版本的引擎进行开发。而对于微信小游戏平台采用的javascript语言,开发团队基本上是从0开始作,边学边作,对自身挑战很大。android
网络通讯方面项目采用了WebSocket协议进行通讯,而通讯格式是json。为了迎合tdr的xml协议,项目组本身开发了tdr->json的转换工具。算法
为了方便策划同窗使用excel表格进行数据配置,项目组又开发了将excel转换成json文件的工具,以便供客户端读取配置文件。chrome
地图方面咱们没有使用cocos引擎自带的TileMap,而是本身实现了一个类TileMap机制。策划同窗能够在excel中配置地图信息,使用工具将excil转换成json格式的地图文件供客户端加载。json
因为开发进度紧张,须要同时开发单机和PVP玩法。因此咱们封装了一个命令层(CMD层)来进行战斗逻辑驱动。好比使用摇杆控制坦克运动,是由表现层发送CMD命令给逻辑层进行处理,在单机模式下CMD会存储于客户端本地列表,而后由命令管理器CMDMgr在Update时读取本地命令列表驱动逻辑层进行处理。而在对战模式中,CMD命令会被发往服务器,由服务器广播给全部玩家,玩家客户端的命令管理器CMDMgr在Update时驱动逻辑层进行处理。引入命令层(CMD层)以后,战斗逻辑层是抽象独立的,开发不须要关心当前的玩法模式,能够方便的复用,减小了开发成本。小程序
咱们PVP实时对战采用的是c/s模式的同步架构,客户端作碰撞检测,将碰撞检测结果通知服务器,服务器进行校验并作伤害计算,而后广播给其余玩家。游戏支持断线重连、客户端crash重连机制,服务器拥有战斗中的全部状态数据,重连时将全部数据发送给客户端,客户端进行战斗场景还原。微信小程序
玩家位置同步采用了基于时间戳的位置点同步算法。这个算法原先应用于《全民飞机大战》的双打模式、对抗模式中。《全民飞机大战》中实时对战采用的是UDP通讯。而在《欢乐坦克大战的》WebSocketTCP环境下也取得了不错的效果。算法原理以下:浏览器
在开发过程当中,咱们也遇到了很多挑战,可是咱们都一一解决了,具体遇到的问题以下:
微信小游戏平台增长了动态执行代码的限制,好比:eval('console.log(1)')、new Function(‘console.log(1)')、setTimeout('console.log(1)’) 等调用方式没法调用。而在CocosCreatorV1.6.1源码中大量使用了Function,为了解决这个问题,咱们和cocos引擎开发商的沟通了下,又参考cocos在1.7版本(当时还没有发布)中的修改,修改了一些源码,解决了此问题。
正如标题所示,微信小程序严格要求了大小,为了解决这个问题,咱们又想了很多办法。
使用png图片压缩工具pngquant,能够有效的减少png图片的文件大小(一般能压缩60%-70%)左右。
经过以上2个措施,资源仍然会超标,只能采用资源动态下载的方案了。
咱们在游戏中增长了一个资源更新场景。游戏启动时,场景进行资源更新时游戏业务模块都没有建立,等到游戏场景中再进行业务模块的建立和初始化工做,而后再进行场景切换。具体方案以下:
1.先下载一个资源更新配置文件,此文件中有待资源下载列表、资源校验MD5信息。
2.根据资源下载列表,将校验MD5和本地文件进行对比,若是相同则不下载,若是不一样则下载。
3.下载完毕后,进行MD5校验,若是校验不经过则删除本地文件,从新走下载流程。这里的MD5校验,不只能够校验资源下载是否正确;对于防止资源被恶意修改,资源反做弊也有必定做用。
4.修改cocos引擎源码, 在load-pipeline中,将资源读取替换成读取本地的下载文件。
因为游戏运营中可能会有Bug发生,须要下发客户端补丁。资源更新配置文件可能会被屡次修改,而CDN更新会有延迟问题,致使部分玩家下载的配置文件多是较旧的版本。并且有部分中小运营商,为了成本考虑,会缓存旧的文件。以往的项目在发生这种状况时,通常是联系玩家进行定位,发现是运营商问题再反馈给运维同窗,由网络部门的同事推进运营商进行修改,效率不高。为了减小这种状况发生的可能性,咱们使用了双CDN策略。
具体的作法是,对于同名文件增长版本号机制,更新文件时将文件内部存储版本号+1,并在2个不一样的CDN进行更新。客户端下载时,下载2份文件,取版本号大的为准。这样当更新配置文件时,2个不一样CDN只要有一个同步到便可,既能减小了CDN更新延迟,又下降了运营商缓存问题出现的几率。
和通常的游戏不一样的是,微信小游戏平台自己的js脚本执行效率较弱,iOS环境小游戏javascript引擎目前使用的是JavaScriptCore,默认没开jit优化,js执行速度会比手机safari慢,从简单测试结果来看,速度会慢两倍左右。从Profiler来看,js脚本执行时间会占到80%左右。所以减小脚本的计算量也是性能优化一个重要的方面。
小米6 |
android小游戏 |
android 微信浏览器 |
android chrome |
---|---|---|---|
57.55 |
53 |
58 |
|
iphone6 |
IOS小游戏 |
IOS 微信浏览器 |
IOS safari |
20 |
48 |
50 |
帧率测试对比
DrawCall
渲染批次合并和大多游戏项目相似,须要合理的规划图集的使用,将同一个层次的GameObj使用的图片资源进行拼图。
能够分为地图背景层、地表、地图物件、坦克、子弹、特效、UI等拼图,尽可能确保同一个层次的游戏对象使用相同的图集,相邻的精灵使用的材质相同。
mask
游戏中会显示玩家的圆形头像,而微信平台下载的头像是矩形。原先头像显示使用的是cocos的mask组件进行渲染,效率较低。咱们本身实现了一个基于mesh的控件,将一个圆等分为n个三角形,给这些三角形顶点赋予相应的UV,从而画出一个圆形头像。减小了头像渲染时的批次开销。
碰撞检测
cocos creator自带的碰撞系统效率不高,没有作空间划分,不适合大量单位的碰撞检测。而且每帧都须要更新碰撞体的碰撞盒。咱们游戏地图中存在大量的静态物件(如地图中的砖块、主基地、钢板等),而玩家在场景中移动时,是经过移动摄像机达到地图视野的变化,因此大量的地图静态物件的世界坐标是不变的,他们的碰撞盒只须要计算一次便可。
为了解决这个问题,咱们给cocos的node增长了一个属性static,static节点的计算结果能够缓存起来,避免重复计算。
对象池
游戏中的坦克、子弹、砖块等采用对象池,进入战斗场景时有足够数量的预加载,战斗过程当中进行复用,避免实时的对象建立与销毁。
避免场景、节点更新
分析cocoscreator的源码发现,当有节点发生active,会触发递归遍历场景,开销较大。
为了不这类开销,游戏中的物体死亡时,不会将其从场景中移除或禁用,而是设置死亡状态,经过移动坐标到很远的地方,代码中不执行相应的逻辑处理。尽可能保持帧率平稳,避免性能曲线的毛刺
裁剪
当物体不在主角视野范围内而且不是持久播放的特效和声音能够进行裁剪不播放。
机型适配
对于美术资源进行了高、中、低3档分级,由策划在资源表格中配置不一样分级下的资源名称。游戏过程当中,根据机型和实际性能表现,选择一种档次进行表现。
图中横坐标是时间(单位秒),纵坐标是FPS,能够看出FPS有了明显提高。经过一系列的优化措施,最终保证了低端机iphone5S基本能知足游戏须要。
以上就是《欢乐坦克大战》微信小游戏开发总结,有兴趣的小伙伴能够一块儿来交流哦~