我们要做一款打飞机游戏,里面有飞机图片、背景图片、飞机音效、碰撞音效等等非常多的素材。如果将这些资源都放置在一个目录下,将会变得非常混乱。如果按照素材内容来划分目录,程序读取的效率就不高,所以我们需要将这些素材打包在一个资源包内,然后将每个素材都放置在一个虚拟目录内。

因此,今天我们就来如何制作讲解资源包。简单来说,所谓的资源包,就是将游戏的所有资源和素材,进行打包分类,并且进行资源整合,亦或将资源和素材进行压缩,减少游戏体积。

什么是资源包?

我总结了一下,可以从这三个角度来理解什么是资源包。

现在很多游戏公司都不会编写特殊的资源包格式。因为设计一种资源包格式,需要经过一系列复杂的动作,包括包头、包身和包尾。

关于这个格式的设计,一会儿我会给你仔细分析。因为,和我们自定义网络协议包一样,一个好的资源包,能够很方便进行解包、打包、删除文件、插入文件的操作,以及游戏的在线更新、补丁更新、资源包的解包、打包、删除、插入、更新文件等操作。

而一个好的资源包格式,不会占用主程序大量的时间。因为在游戏中,需要直接读取包文件里面的内容。

比如我们之前在Pygame中读取的图片文件,在包裹格式中,可能会这么写伪代码:

load.image(‘package.pack/plane.png’)    

其中package.pack就是包裹,plane.png是存在在包裹里面的其中一幅图片文件。这样,打了包裹后的文件,就不会污染目录。一般一个包裹文件中存在大量资源,而我们只要按照包裹路径读取就可以了。

如果不编写特殊的资源包格式,那应该怎么制作资源包呢?答案是,使用现成的压缩软件库,进行打包压缩,直接在程序内使用。比如我们最常用的zip文件、rar文件,都是可以拿来做资源包文件的。在Python中有内置zip模块,可以直接读取zip文件。我们可以直接在Pygame中结合zip模块进行编程。

资源包的格式

我们要讲解的是资源包的制作,我将会用一种较为通用和简单易懂的方法,解释资源包都包含哪些内容,同时让你理解资源包是怎么制作的。

首先,从编程的格式来理解资源包,你需要了解下列这些内容。

然后,我们需要规定素材的文件名偏移量。比如/game/res/background.jpg。这是告诉我们在/game/res虚拟目录下,拥有background.jpg这个文件。随后需要告诉程序偏移量是多少,一般是存储4个字节的整型数字。

到目前为止,资源包的格式看起来可能是这样的:

INFO100/game/res/background.jpg,[四个字节的偏移量]

在这里,我们看到,偏移量之前多加了一个逗号“,”。这是一个分隔符,也就是告诉程序,这一段在哪里结束。

随后是四个字节的偏移量。所谓的偏移量,就是告诉程序,你要到这个包裹的第几个字节去寻找这个文件的具体内容。

比如素材的本体是个二进制文件,分隔符比如是!@#$,素材的本体里面也存在!@#$这样的内容,这样的情况下,就会出现读取中断,因为程序以为素材内的!@#$就是结束符号,事实上这只是素材本身的内容而已。

我们来看一个完整的资源包,大概是什么样子的。

[资源包头][版本号][是否压缩][资源包目录/素材文件名A][文件A偏移量][文件A长度]…[资源包目录/素材文件名N][文件N偏移量][文件N长度][素材A本体]….[素材N本体][结束符]

了解了资源包的格式内容,我们可以很方便地利用Python或者C语言等来编写相应格式的资源包。

我来给这部分做一个总结:

资源包的存在,有两个目的,一是让游戏目录干净整洁,不然看上去都是乱七八糟的图片和各种配置,二是让游戏程序能更快地从内存中读取游戏资源制作的包裹文件,加速游戏的运行效率。这个包裹文件中含有虚拟目录、资源、资源位置、资源名字等等信息。我们不需要从文件目录中去读取单一文件,只需要从内存中载入的资源包中取出某个文件即可。

如何制作游戏的保存机制?

每一个游戏几乎都有保存和载入的机制。首先你需要知道,只有保存了数据,我们才能载入数据。那么游戏的保存机制是怎么做的呢?

事实上,游戏的保存和游戏的地图编辑器中保存地图的原理,可以说是异曲同工。如果一个游戏中,有地图、坐标、人物、装备、分数,这些都需要被记录下来,那么我们不可能将地图、坐标、人物、装备、分数等全部转换成二进制文件记录下来。那应该怎么做呢?

首先,如果是记录地图,有地图1或者地图2,我们只需要记录地图的ID就好了。假如是地图2,坐标是(x,y)。人物只需要记录人物的ID,再关联到人物。一个游戏中,玩家建立了一个人物角色,就会将这个人物角色进行保存,不至于丢失人物角色。所以,在读取游戏的时候,需要先读取人物角色,再读取保存的游戏内容。

至于分数就很好记录了,记录分数其实就是记录数字,所以记录起来会很方便。

那么装备呢?如果是装备,一般会将装备的所有内容记录下来,如果做得精致的游戏,还会将地图中那些掉落的装备和死去的NPC进行记录。

还有一种做法是,将游戏保存的文件直接导出成一个脚本文件,以后每次读取数据就只需要使用程序读取脚本就可以了。

小结

今天我讲解了资源包的制作以及游戏进度的保存,你需要你记住这些内容。

给你留一个小思考题吧。

在《GTA》中,汽车会有不同程度的损毁,当你保存完游戏重新进入的时候,汽车又复原了,请问这是为什么呢?

欢迎留言说出你的看法。我在下一节的挑战中等你!

评论