《欢乐坦克大战》是一款支持3V3实时对战并首批参与上线的微信小游戏中的作品。因为该游戏为微信小游戏中的重度之作,项目开发周期非常短,所以游戏复杂度、开发难度、性能挑战也是挺大的;项目组在一个月内就完成了单机、网络对战玩法的开发。
同时,因为客户端开发团队的核心成员有多年的cocos2dx引擎开发经验,所以项目组决定使用CocosCreator V1.6.1版本的引擎进行开发。而对于微信小游戏平台采用的javascript语言,开发团队基本上是从0开始做,边学边做,对自身挑战很大。
一、架构
网络通信方面项目采用了WebSocket协议进行通信,而通信格式是json。为了迎合tdr的xml协议,项目组自己开发了tdr->json的转换工具。
由于开发进度紧张,需要同时开发单机和PVP玩法。所以我们封装了一个命令层(CMD层)来进行战斗逻辑驱动。比如使用摇杆控制坦克运动,是由表现层发送CMD命令给逻辑层进行处理,在单机模式下CMD会存储于客户端本地列表,然后由命令管理器CMDMgr在Update时读取本地命令列表驱动逻辑层进行处理。而在对战模式中,CMD命令会被发往服务器,由服务器广播给所有玩家,玩家客户端的命令管理器CMDMgr在Update时驱动逻辑层进行处理。引入命令层(CMD层)之后,战斗逻辑层是抽象独立的,开发不需要关心当前的玩法模式,可以方便的复用,减少了开发成本。
我们PVP实时对战采用的是c/s模式的同步架构,客户端做碰撞检测,将碰撞检测结果通知服务器,服务器进行校验并做伤害计算,然后广播给其他玩家。游戏支持断线重连、客户端crash重连机制,服务器拥有战斗中的所有状态数据,重连时将所有数据发送给客户端,客户端进行战斗场景还原。
玩家位置同步采用了基于时间戳的位置点同步算法。这个算法原先应用于《全民飞机大战》的双打模式、对抗模式中。《全民飞机大战》中实时对战采用的是UDP通信。而在《欢乐坦克大战的》WebSocketTCP环境下也取得了不错的效果。算法原理如下:
二、挑战
在开发过程中,我们也遇到了不少挑战,但是我们都一一解决了,具体遇到的问题如下:
1、微信小游戏平台增加了动态执行代码的限制
微信小游戏平台增加了动态执行代码的限制,比如:eval('console.log(1)')、new Function(‘console.log(1)')、setTimeout('console.log(1)’) 等调用方式无法调用。而在CocosCreatorV1.6.1源码中大量使用了Function,为了解决这个问题,我们和cocos引擎开发商的沟通了下,又参考cocos在1.7版本(当时尚未发布)中的修改,修改了一些源码,解决了此问题。
2、微信小游戏不允许超过4M
正如标题所示,微信小程序严格要求了大小,为了解决这个问题,我们又想了不少办法。
措施1:引擎定制裁剪去掉不必要的模块减少引擎体积,这块通过设置引擎模块即可。
措施2:图片压缩
使用png图片压缩工具pngquant,可以有效的减小png图片的文件大小(通常能压缩60%-70%)左右。
通过以上2个措施,资源仍然会超标,只能采用资源动态下载的方案了。
措施3:资源动态下载
我们在游戏中增加了一个资源更新场景。游戏启动时,场景进行资源更新时游戏业务模块都没有创建,等到游戏场景中再进行业务模块的创建和初始化工作,然后再进行场景切换。具体方案如下:
1.先下载一个资源更新配置文件,此文件中有待资源下载列表、资源校验MD5信息。
2.根据资源下载列表,将校验MD5和本地文件进行对比,如果相同则不下载,如果不同则下载。
3.下载完毕后,进行MD5校验,如果校验不通过则删除本地文件,重新走下载流程。这里的MD5校验,不仅可以校验资源下载是否正确;对于防止资源被恶意修改,资源反作弊也有一定作用。
4.修改cocos引擎源码, 在load-pipeline中,将资源读取替换成读取本地的下载文件。
由于游戏运营中可能会有Bug发生,需要下发客户端补丁。资源更新配置文件可能会被多次修改,而CDN更新会有延迟问题,导致部分玩家下载的配置文件可能是较旧的版本。而且有部分中小运营商,为了成本考虑,会缓存旧的文件。以往的项目在发生这种情况时,一般是联系玩家进行定位,发现是运营商问题再反馈给运维同学,由网络部门的同事推动运营商进行修改,效率不高。为了减少这种情况发生的可能性,我们使用了双CDN策略。
具体的做法是,对于同名文件增加版本号机制,更新文件时将文件内部存储版本号+1,并在2个不同的CDN进行更新。客户端下载时,下载2份文件,取版本号大的为准。这样当更新配置文件时,2个不同CDN只要有一个同步到即可,既能减少了CDN更新延迟,又降低了运营商缓存问题出现的概率。
3、性能优化
和一般的游戏不同的是,微信小游戏平台本身的js脚本执行效率较弱,iOS环境小游戏javascript引擎目前使用的是JavaScriptCore,默认没开jit优化,js执行速度会比手机safari慢,从简单测试结果来看,速度会慢两倍左右。从Profiler来看,js脚本执行时间会占到80%左右。因此减少脚本的计算量也是性能优化一个重要的方面。
小米6
android小游戏
android 微信浏览器
android chrome
57.55
iphone6
IOS小游戏
IOS 微信浏览器
IOS safari
帧率测试对比
为了解决这些问题,项目组做了以下优化
DrawCall
渲染批次合并和大多游戏项目类似,需要合理的规划图集的使用,将同一个层次的GameObj使用的图片资源进行拼图。
可以分为地图背景层、地表、地图物件、坦克、子弹、特效、UI等拼图,尽量确保同一个层次的游戏对象使用相同的图集,相邻的精灵使用的材质相同。
mask
游戏中会显示玩家的圆形头像,而微信平台下载的头像是矩形。原先头像显示使用的是cocos的mask组件进行渲染,效率较低。我们自己实现了一个基于mesh的控件,将一个圆等分为n个三角形,给这些三角形顶点赋予相应的UV,从而画出一个圆形头像。减少了头像渲染时的批次开销。
碰撞检测
cocos creator自带的碰撞系统效率不高,没有做空间划分,不适合大量单位的碰撞检测。并且每帧都需要更新碰撞体的碰撞盒。我们游戏地图中存在大量的静态物件(如地图中的砖块、主基地、钢板等),而玩家在场景中移动时,是通过移动摄像机达到地图视野的变化,所以大量的地图静态物件的世界坐标是不变的,他们的碰撞盒只需要计算一次即可。
为了解决这个问题,我们给cocos的node增加了一个属性static,static节点的计算结果可以缓存起来,避免重复计算。
对象池
游戏中的坦克、子弹、砖块等采用对象池,进入战斗场景时有足够数量的预加载,战斗过程中进行复用,避免实时的对象创建与销毁。
避免场景、节点更新
分析cocoscreator的源码发现,当有节点发生active,会触发递归遍历场景,开销较大。
为了避免这类开销,游戏中的物体死亡时,不会将其从场景中移除或禁用,而是设置死亡状态,通过移动坐标到很远的地方,代码中不执行相应的逻辑处理。尽量保持帧率平稳,避免性能曲线的毛刺
裁剪
当物体不在主角视野范围内并且不是持久播放的特效和声音可以进行裁剪不播放。
机型适配
图中横坐标是时间(单位秒),纵坐标是FPS,可以看出FPS有了明显提升。通过一系列的优化措施,最终保证了低端机iphone5S基本能满足游戏需要。
用户评论
我最近在玩那个《欢乐坦克大战》,真是又刺激又过瘾!
有16位网友表示赞同!
这款微信小游戏《欢乐坦克大战》太好玩了,简直就是个时间杀手。
有7位网友表示赞同!
《欢乐坦克大战》啊,它的游戏界面和音乐都好棒,让人瞬间投入战场。
有7位网友表示赞同!
玩《欢乐坦克大战》时,朋友间的对决特别有意思,乐趣多多。
有20位网友表示赞同!
这游戏的操控流畅,我根本停不下来,《欢乐坦克大战》真的是个佳作。
有15位网友表示赞同!
在微信上找到《欢乐坦克大战》,一天内都没摸到其他东西!
有19位网友表示赞同!
强烈推荐给所有喜欢策略与冒险的朋友,玩《欢乐坦克大战》准没错。
有14位网友表示赞同!
玩《欢乐坦克大战》后发现自己的反应速度都有了提升,还不错呢。
有11位网友表示赞同!
在《欢乐坦克大战》中挑战好友,每次都能学到新的战术。
有12位网友表示赞同!
感觉这款游戏不仅对玩家的手指有要求也挺考验策略思维的,《欢乐坦克大战》很过瘾!
有13位网友表示赞同!
我超级喜欢《欢乐坦克大战》,它让我仿佛置身于真实的战争中体验战斗快感。
有13位网友表示赞同!
《欢乐坦克大战》微信小游戏,里面的炮弹声和爆炸特效非常逼真,让人心跳加速。
有17位网友表示赞同!
《欢乐坦克大战》给我的游戏体验是全新的,让人着迷难以自拔。
有7位网友表示赞同!
玩得不亦乐乎,《欢乐坦克大战》的小细节做得太好了,每场战斗都很公平。
有5位网友表示赞同!
作为粉丝,我只能说《欢乐坦克大战》让我在微信小游戏上享受到了前所未有的快乐。
有7位网友表示赞同!
即使玩了那么多次,《欢乐坦克大战》的挑战模式也能给我不一样的惊喜体验。
有17位网友表示赞同!
《欢乐坦克大战》里的装备系统和升级机制真的很吸引人,让人有继续探索的动力。
有10位网友表示赞同!
想挑战极限吗?快来试试《欢乐坦克大战》,你的游戏生涯可能会因它而不同。
有8位网友表示赞同!
在忙碌时来上一局《欢乐坦克大战》,能让我短暂地逃离现实压力,充满爽快感。
有8位网友表示赞同!
"欢乐"两字太贴切了,《欢乐坦克大战》让我的朋友圈多了不少共同话题和欢笑。
有16位网友表示赞同!