本人程序猿一枚,正在开发一款类似《杀戮尖塔》的卡牌游戏,寻找美术方面的小伙伴,有意愿合作的密我,微信号:zzg831,邮箱:zzg83@sina.cn
技术分享:前几年为了深入地学习游戏开发,基于cocos2d-x-3.1.1版本,我重新搭建了一套自己的游戏引擎架构,由于各种原因,没时间继续搞下去了,现共享出来,有学习意愿的同学可以参考下。这是我自己边学习边弄的,肯定比不上Cocos2d官方的,不喜勿喷。
共享资料的地址:
百度云盘: https://pan.baidu.com/s/1mJVB4FjcqANbxxqzYNSJAQ
提取码:8pgo
我开始学习的时候,Cocos2d当时最新的版本就是cocos2d-x-3.1.1,已经是几年前的版本了,我主要在以下几个地方进行了改进:
从游戏开发者角度来看,改进的地方主要集中在以下几个方面:
- 场景编辑器
类似于Unity3D的编辑器,场景树是通过GameObject串联起来的,用户只要在编辑器上向GameObject上添加各种组件就可以构建游戏场景,然后将构建出来的场景导出,游戏程序就可以读取该导出文件并加载该场景。
由于我不擅长GUI界面开发,为了方便快速开发各种组件,我使用的是Java语言做的编辑器界面,没有提供场景即时查看的功能,看起来有点Low。
编辑器中提供了很多常用的组件,如:Mesh多边形、文本组件(支持多国语言自动切换)、音频播放组件、视频播放组件、骨骼动画播放组件、鼠标事件响应组件、键盘事件响应组件等等。
(备注:我使用的JDK版本为1.6)
编辑器截图:
- 相关的工具链
由于我的游戏引擎通过组件的方式对外提供功能,因此需要将音频文件、视频文件、骨骼动画等转换成我的游戏引擎支持的格式,所以我自己开发了一系列相关的工具,用于将常见音频文件、视频文件、Spine的骨骼动画等数据转换成我的游戏引擎所支持的数据格式,还有一套工具专门用于处理用户编写的材质、Shader等脚本,以及将各种资源文件打包成文件包供游戏程序使用。
在学习的过程中,为了研究其它游戏,通过汇编、Hook等技术手段,编写了一些我个人觉的有用的小工具,有兴趣的同学可以参考下
在代码层面,从游戏引擎架构来看,改进的地方主要集中在以下几个方面:
- 文件管理系统
cocos2d原有的代码对直接调用操作系统的API对磁盘上的文件进行读取,缺少对文件包、流文件的读取处理。我重新进行了文件管理系统的设计,主要实现了以下功能:
- 同时支持对文件包中的文件、文件夹目录下的文件的读取,用户可以将大量文件打成一个文件包来使用,将文件打包的目的,主要是为了防止外部用户直接读取、修改游戏程序的数据以及提升文件数据读取的效率
- 提供以流的方式读取文件数据,主要是针对体积较大的视频文件、音频文件的读取
- 对于纹理、材质、Shader等常用的数据进行了单独的索引处理,以便于这些资源数据的使用、查找、快速加载
- 支持从多个文件包文件或者磁盘目录中读取数据,用户将常用的文件打包成一个数据包,直接拷贝到另一个项目中就可以复用资源数据
-
音频、视频播放
cocos2d原有的代码对音频播放的处理非常简陋,缺少对于大文件的缓冲处理,而且没有视频播放功能。我重新编译了OpenAL、ffmpeg等开源库,并对其进行了封装,主要提供了以下功能:
1).支持对视频的播放(视频图像数据被解压到了纹理中,用户可以将该视频图像作为贴图进行其它特效处理)
2).强化了对音频的播放,提供了三种播放模式,以优化性能和内存消耗:
“边播放边加载”模式,主要针对大文件,减少内存的消耗
“全部加载到内存,但是不解码”模式,主要适用于文件体积中等,需要经常播放的音频文件,例如:背景音乐等等。
“全部加载到内存,并解码”模式:主要适用于播放频繁、但是体积小的音频文件,如:武器攻击的声音等等。
备注:百度云盘共享文件夹中的游戏引擎源代码中的AudioVideo文件下放的就是音频、视频处理的源代码,关于开源软件OpenAL、ffmpeg的编译、使用,根据我自己的经验,将其形成了文档,以方便有需求的同学进行参考,文档路径:百度云盘共享文件下的《005. 开源软件的编译手册》目录下的《001. glfw库的编译.rar》、《002. ffmeg核心库的编译和使用指南.rar》、《003. OpenAL库的编译和使用指南.rar》 -
材质、Shader
cocos2d-x-3.1.1原有的框架中,是没有材质Material这个概念的,如果需要向Shader程序中传递参数,必须通过代码才能实现,对使用者来说非常不方便。我对此进行了封装处理,类似Unity3D中的Shader那样,在编辑器界面中就可以向Shader中传递参数,无需必须通过代码来控制参数的传递
编辑器界面:
材质脚本:
-
资源的加载、卸载
改进了游戏资源的加载机制,类似Unity3D那样,GameObject所依赖的音频、视频、图片、Shader、材质等资源都是会自动加载、自动回收的,用户无需关心,只需要在编辑器中直接使用这些资源即可,用户也可以主动去加载资源,提供了同步加载、异步加载 -
渲染线程、计算线程的分离
为了提升效率,游戏引擎分离了渲染线程和计算线程,渲染线程专门用于同GPU进行交互,负责窗口的渲染,不进行任何数据计算,数据计算完全由计算线程来完成,这两个线程对于用户而言是透明的,用户无需关心这两个线程是如何交互的。 -
脚本系统
最初是采用Lua作为脚本语言的,但是在编写脚本时,Lua的语法与我常用的Java、C/C++差别太多,很不习惯,而且我跟踪测试Lua的源代码,对Lua从脚本层代码到C/C++代码层的切换效率有点不满意,尤其是对Lua_State消耗的内存严重不满(可能是我自己的用法有问题,感觉Lua_State消耗的内存太严重了),比Java、C#之间的切换效率相差太多,当时考虑到Java无法运行在苹果机上,于是自己开发了一套sol语言,该语言的语法规范与Java相近,主要是强化了脚本代码与C/C++原始层代码之间的切换效率(切换效率比Java/C#之间的切换效率要高),并且脚本运行时消耗的内存很少,向脚本中注册自定义Class、函数非常方便。不过由于没有实现JIT,代码的运行效率比Java/C#差,但是仍然要比Lua的执行效率高的多。
备注:百度云盘共享文件夹中的游戏引擎源代码中的SimpleObjectLanguage文件夹下存放的是实现该语言的源代码。
现在我转向到了Unity3D,发现我开发的那个sol脚本语言相对于C#缺少很多有用的功能,对自由扩展代码很多不便,由于时间不充裕,缺少了继续改进的动力,后续有时间的话把游戏引擎中的脚本语言改成C#。(备注:我对比过C#和Java语言哪个做脚本更合适,发现Java在脚本代码层与C/C++原始层代码之间的切换效率比C#差很多,用的是Mono的虚拟机进行的测试。
备注:关于如何编译Mono的源代码以及Mono的使用指南,请参照文档:百度云盘共享文件下的《005. 开源软件的编译手册/004. mono开发环境的搭建.rar》 -
渲染裁剪
cocos2d-x-3.1.1原有的框架中,是遍历所有的Node节点,然后判断每个节点是否需要渲染到屏幕上,当节点非常多时,计算量比较大,效率不高。我将其进行了改进,使用四叉树管理场景中的所有的渲染物体,Camera摄像机会自动裁剪出位于视口区域内的物体进行渲染显示,位于Camera摄像机视口区域之外的物体不会进行渲染处理。 -
渲染顺序排序
提供了渲染层、渲染Order来进行渲染排序,类似与Unity3D的排序层、排序层索引。
近期我转向了Unity3D,在使用Unity3D的过程中,之前很多引擎架构上的问题,发现Unity3D解决的很好,,后续如果有时间的话,我会考虑继续改进游戏引擎,争取做成一个类似Unity3D那样引用的引擎。