loop_in_codes

低调做技术__欢迎移步我的独立博客 codemaro.com 微博 kevinlynx

游戏资源包简单设计

一般的资源包文件格式基本上是由包文件头和包内容组成。文件头描述资源包内打包的文件
信息,例如文件名、在资源包里的偏移、大小、压缩加密相关信息等;包内容则是实际文件
打包在一起后的内容,可能直接是未打包前文件连续存放在一起的内容,也可能是相同类型
文件除掉文件头的内容(例如某个资源包里打包的全部是相同格式的图片文件,那么这些图
片文件被打包后包内只需要保存一个图片文件头,包内容全部是直接的图片数据)。

网络游戏资源包有个显著的需求就是支持补丁包更新。更新程序会把补丁包内的更新资源文
件插入到老的资源包里。最简单的解决办法,就是在包文件头里预留一定的空间,用于将来
插入新的文件描述。当然,新的文件内容可以直接插入到包尾。一个简单的文件格式如下:

pkg_fmt

pkg_header是一个对整个资源包综合描述的结构,可能包含的域为:

struct PkgHeader {
    int ver; /* 版本号 */
    int ctx_offset; /* 文件内容偏移 */
    int file_tag_cnt; /* 文件标记数量 */
    int empty_tag_cnt; /* 空标记数量 */
};

pkg_header后面则是文件标记(信息)结构体集合,每一个标记用于描述打包的一个文件的
信息,可能包含的域有:

struct FileTag {
    char name[128]; /* 包含目录名的文件名,用于索引,如./model/character.dat */
    int offset; /* 该文件在资源包内的偏移 */
    int size; /* 在资源包中的大小 */
    int orig_size; /* 原始大小,即未压缩/加密前大小 */
    int crc; /* crc校验 */
};

如果要支持客户端自己下载数据更新,考虑到断点续传功能,可能还会添加一些成员用于标
记当前文件获得的数据大小。

empty_tags则是一些空的FileTag。当要往包里插入新的文件时,则会在这里申请。同样,
如果要删除文件,也可以将前面的file_tag转移过来。因为采取这种包格式,文件实际内容
的偏移基本上是不会改变的,所以,每一次都可以直接重新排列file_tags和empty_tags。

接下来包的内容就直接是文件内容。如果中间的文件大小有变化,会涉及到其他文件数据的
移动。

对于只需要读取资源包的游戏客户端而言(不包括更新程序),可以只读取pkg_header和
file_tags。程序将file_tags置于一个索引表中,效率考虑,可以标记每一个file_tag是否
已在内存中。每一次应用层请求一个资源文件时,就从该表中查找。若资源已在内存中,就
直接取出使用,否则根据file_tag的描述从资源包里取出(这里涉及到IO操作)。

posted on 2010-06-19 14:59 Kevin Lynx 阅读(4690) 评论(5)  编辑 收藏 引用 所属分类: game develop

评论

# re: 游戏资源包简单设计 2010-06-21 09:40 饭中淹


另外,文件分配表的位置最好放在包末尾,这样就没有数量限制了,也不用预留empty_tags。

  回复  更多评论   

# re: 游戏资源包简单设计 2010-06-21 11:36 Kevin Lynx

@饭中淹
对啊,好方法。移动分配表的代价比移动文件内容小多了。不错。  回复  更多评论   

# re: 游戏资源包简单设计 2010-06-23 15:28 秒大刀

可以研究下其他已有的开源包结构zip、rar、7z等,魔兽的mpq也不错  回复  更多评论   

# re: 游戏资源包简单设计 2010-07-08 17:47 大虾

如何实现替换文件?  回复  更多评论   

# re: 游戏资源包简单设计 2010-07-09 09:26 Kevin Lynx

@大虾
把文件内容直接替换了,然后修改file_tag  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理