欢迎参与讨论,转载请注明出处。
前言
在游戏开发的领域里,图集(SpriteSheet)是一个很重要的概念,其好处在链接处也已言明。但若是引擎没提供相关的支持,那么便需要自己搞个解决方案了。而LÖVE也恰好是没有提供相关支持的,那么只好自己动手丰衣足食了,本文便记录其中心得。
装箱问题
要实现图集的核心便是对图片进行拼合打包,其实类似的工具市面上亦有存在(如TexturePacker)。从功能上而论,TexturePacker完全可以满足需求(有提供命令行模式,可实现自动化)。可惜TexturePacker的免费版根本不堪使用,而破解也相继失败。而其他类似的工具要么无法满足需求,要么不支持macOS。只好自己手写一套了。
实现的图集的难点无非在于拼合时图片排列的算法,由Claris告知得这种属于装箱问题,目前并无最优解。由装箱问题为关键字进行展开搜索,发现一种名为MaxRectsBinPack的算法可解决问题,我将之翻译成了Python版。如此装箱问题便解决了。
拼合问题
接下来的问题便是“谁和谁拼合成一张图”了,我对此立下三个原则:
- 关联性不高者不拼(拼成大图的代价便是成为资源共同体,如果关联性不高的拼合一块则会造成极大的内存浪费)
- 黑底与透明者不拼(黑底图拼成大图必须得保证全图无透明点,否则游戏里会出现奇怪的线条)
- 拼合后过大者不拼(需保证图片大小在4096*4096及以下,否则恐怕出现上限问题)
以这三原则来看,是无法做到以文件夹为单位进行粗暴的拼合了。所以采用了编写配置的方式进行。
|
|
配置以JSON形式存储,配置中的key代表着合图文件夹的层级,value则为欲拼合的图片文件夹,若无/
开头则代表以当前文件夹层级为路径,反之则为全路径。以这套方案便可很自由地选择拼合的方案了。
配置问题
图片的拼合问题解决后,便是游戏要如何以最低的代价去兼容新的图片形式了。解决方案自然是为原图片生成路径一致的配置文件,游戏通过读取配置文件以无缝对接新的图片形式。配置文件格式如下:
|
|
配置文件记录了所属合图的路径以及在合图中的坐标宽高,如此便可清晰无比地取得了。由于Python的lupa模块装不上,为此还专门写了个Lua与JSON的转换器。
大小问题
一般而言,因为光栅化需要对纹理采样进行快速取值,图片大小需要遵循2的N次幂(256、512、1024…)。这种符合的图片被称为POT(Power-Of-Two),同理不满足的称为NPOT(Non-Power-Of-Two)。在早期POT纹理可以说是必须的,而今在OpenGL ES2.0后支持了NPOT。但为了能满足ETC压缩以及兼容性,个人推荐还是对合图进行POT化。
后记
其实从这个问题来看,选择流行的大引擎的确会更为方便。在Unity里可以由后台自动完成的事情现在却要一篇文章来总结,不过贼船已经上了,就只能走到黑了。