哈喽,最近忙于工作就所以没有更新博客,今天腾出时间起来签到,我们继续接着上期说。
游戏分包设计
框架的游戏文件在'Game/game/'
目录中,打开我们会发现如下结构;
Game/game/
├─── boot/ 启动包
├─── main/ 主包
└─── demo/ demo包
没错, 游戏文件并不在同一个目录中,现在我们把他分为了3个包;
'boot'
包负责游戏的启动,检查更新及更新操作;这是一个通用包,一般不会与具体游戏有关,或者可以通过微小修改适应各种游戏。'main'
包为游戏的主包,基本上包含了游戏的模块和逻辑。当然游戏的通用模块是可以单独分出一个包的,这里把他们包含在一起了。这个包除开通用模块部分都是和具体游戏相关的。'demo'
包是游戏的剧本包。框架的示例是rpg游戏,游戏的内容是以剧本组织的,每一个剧本也可以是一个单独的包。特别要注意的,'main'
包虽然包含了游戏的逻辑,但是是没有剧情的,也就是说'main'
包的游戏逻辑是游戏内容框架逻辑,并没有剧情把他们组织起来。
这3个包各施其职组成了当前的游戏所有内容,当然游戏分包是没有数量和其他限制的,可以任意。
我们为什么要分包?
因为原cocos2dx是没有分包的,分包设计的主要目的是把游戏的内容分类。比如游戏启动更新可以是和具体游戏无关的,这可以是框架的部分;游戏的通用模块一般是精炼的程序,是和具体游戏无关的,这也是框架的部分。这样框架部分就是我们的技术储配,如果需要可以快速应用于其他游戏,可能根本不需要更改。(啰嗦,提高技术水平一种方式就是把具体的项目内容模块,总结精炼为通用的模块,这个模块就是你的水平也是你的储备)
分包文件夹的打包
现在游戏的内容已经分为多个文件夹了,哪么我们要怎么把他们添加到游戏中呢?
cocos2dx提供了一种最简单的方式,FileUtils:addSerachPath(path)
可以把分包文件夹包含到搜索路径中,这样cocos2dx就能引用到分包中的文件。
当然,如果分包只是为了提供内容分类工作,我们现在就实现了。但是,现在我们考虑一个问题,游戏如何热更?
如果游戏分包是通过addSerachPath
添加搜索路径实现的,那么我们唯一的方式就是替换分包文件夹中的文件。那么这样就又产生了几个问题;游戏分包的版本怎么控制、游戏具体应该怎么更新?
这样做的话,游戏版本控制最安全的方式就是在游戏分包中某个文件标记版本号,游戏更新方式差不多就是替换全部文件或者替换某几个文件。这样做的优缺点很明显;
* 优点
* 简单
* 缺点
* 分包版本标记存在于分包中的具体文件中,热更模块通用性减弱,也不利于自动化
* 分包文件整体替换,存在不必要的下载流量,并不一定所有包文件都需要替换
* 分包文件替换几个文件,也存在不必要的下载流量和不方面操作的问题,分包的更新也不利于自动化。
解决上面问题的方式就是 分包文件夹打包
游戏分包文件夹打包
就是把分包文件夹中的文件打包为一个文件,这样分包的版本号就是单个文件的版本号,分包热更可以通过生成文件补丁的方式以达到最小的下载流量,而且整个分包的操作可以很好的自动化。(当然分包文件夹打包的优点不止于此),大致流程如下图
分包文件夹如何打包?
分包文件夹打包很简单,就是把文件的标识和文件的内容写入二进制文件中。
文件的标识可以是一个UUID,也可以是文件的相对路径。这样就在二进制文件中组成了分包文件的映射表。
文件的标识最好是用文件的相对路径,因为这样可以和当前的游戏使用方式兼容,在游戏调试阶段可以不打包使用本地文件,毕竟打包需要时间。当前游戏框架就是使用的文件相对路径。
当然,在包文件夹打包阶段是可以进行特殊处理,比如文件加密
、压缩
、对lua文件进行编译
、对json文件进行优化
或者对图片进行压缩
等处理。
分包文件加载
现在,我们已经把分包文件夹中的文件写入一个分包文件中。这个文件就包含有当前分包所有文件的映射,那么我们如何在游戏中使用呢?
cocos2dx本身并不支持paack这种打包文件,如果是使用zip方式,那么就不需要加入此种解压方式,我们需要对cocos2dx的文件加载进行改造。Game/frameworks/cocos2d-x/cocos/L/FileManager.h
FileManager是我们对cocos2dx FileUtils的封装,它在原有的FileUtils上层,封装了对分包文件使用的支持,当然FileManager也支持对本地文件的使用。(注意在FileManager上使用本地文件时,文件路径需要加上前缀~/
)
FileManager 有如下常用函数:
* loadFilePack(packPath)
加载指定包文件 (注意文件包文件为本地文件,路径需要前缀~/
) PS:应该没有把包文件放进包文件这种需求。
* releaseFilePack(packName)
释放指定包文件,一旦释放后,则包内的文件不能访问到。
* getPackVersion(packName)
获得已经加载的包文件的版本号, packName
为已经加载的包文件名。
* lookPackVersion(packPath)
查看指定包文件的版本号 (注意文件包文件为本地文件,路径需要前缀~/
)。
如此,只要调用FileManager::loadFilePack
加载指定包文件后,我们就可以在cocos2dx中使用包文件中的文件了,使用方式不变。
分包文件使用的注意事项
- 由于FileManager是在原有FileUtils的上层进行封装,所以游戏中默认会使用包文件,如果需要访问本地文件需要在路径上前缀
~/
- 由于查找包文件中的文件是根据路径映射表,所以使用文件时必须要规范路径, 当前框架中使用的路径分隔符为
/
, 不能使用连续多个路径分隔符,也不能使用.
、..
等相对路径符。合法的路径形如/res/boot/boot.lua
或者res/boot/boot.lua
。 - 虽然包文件不是通过cocos2dx原有的文件工具使用,但是
addSerachPath
还是有用的。在FileManager中,addSerachPath
也可以作为包文件中的文件的搜索路径。当然如果你要设置本地文件的收索路径,你需要在FileManager上获得本地文件工具,然后在本地文件工具上调用addSerachPath
。
更多作用思考
- 整个游戏初始大小可以根据添加的包调整,不需要额外设置,即使只有一个启动包
boot
也可以运行。 - 如果分包内部包含解包密钥,是不是把自己的分包给别人用,而源代码并不会泄露。