一. 起源
为什么想着做这样的一个工具呢?
事情是这样的, 在游戏后期的优化过程中, 发现特效在资源的总量中占比很大, 所以打算压缩下特效的尺寸. 我们特效是由策划用 TexturePacker 打成 plist + png
的形式, 因为项目经手了好多人, 所以好多特效的源文件都已丢失. 因此想到做一个这样的脚本来实现这个功能.
首先想到的是 @偶尔e网事 同学的Anti_TexturePacker, 非常好用, 我经常推荐给有需要的朋友. 不过目前只能运行在 Windows 上, 而且不支持命令行, 我们的特效有好几百个, 一个一个来的话会死人的哦~
下来找到的是这个, texture_unpacker_scirpt, 一看还不错, 简单测试了下集成到了开发环境中, 不过后来发现部分 trim+rotate
过的 frame 解析是不正确的.
一种造轮子的冲动涌上心头.
二. 分析
试着分析下这个项目, 主要分为这几点:
1.plist 文件的解析和分析.
plist 文件其实就是 xml 文件, 可以用 xml.etree.ElementTree
来解析, 恰好之前做过一个 ccb2lua
的项目, 搞起来也是轻车熟路.
plsit 中关键的一个结构是:
1 | <key>oooo_001.png</key> |
字段 | 含义 |
---|---|
frame | 在大图上的坐标和尺寸信息 |
offset | trim 过的图片和原图之间的偏移 |
rotated | 是否进行了旋转 |
sourceColorRect | 原始图上的坐标和尺寸信息 |
sourceSize | 原始图片尺寸 |
我做了一张图来解释这些参数:
这里要注意:
- 一张图片是否旋转, 都会保存相同的
frame.w
,frame.h
这点比较坑. - 如果没有裁剪,
sourceColorRect
的x
,y
就是0
,w,h
和sourceSize
一致.
2. 图像的切取和保存.
图像 python 的还是选用了 PIL 来搞, 用到的接口也不多:
Image.open(file) ⇒ image
打开图像
Image.new(mode, size) ⇒ image
创建一张图像
im.crop(box) ⇒ image
截图图像一个区域
im.paste(image, box)
将一张图像粘贴到一个区域
三. 实现
这里我大概讲一下实现, 具体大家可以去看源码.
1.plist 读取
cocos2d-x 的这个 plist 的格式是比较奇怪的 xml, 每一个 key 的 value 都是在下一行:
1 | <key>format</key> |
所以比较方便的实现是一次获取两行, 如下:
1 | data = {} |
2.图片的 trim+rotate
这个着实令人蛋疼, 因为旋转之后, frame
标签记录的宽高值并没有改变, 所以还得自己去判断下有没有旋转. trim+rotate
之后更是令人发指, 因为这样 sourceColorRect
的宽高,xy偏移都会互换. 这里若是思路不清晰, 极有可能被绕晕.
因为开始参考了texture_unpacker_scirpt的实现, 所以思路一直按照它的路线走, 代码中多次判断了是否旋转. 后来发现代码过于晦涩, 于是完全抛弃了它的实现.
最终核心代码如下:
1 | src_image = Image.open(_imagefile) |
可以看到只有两处判断了旋转. 大家点这里可以看下texture_unpacker_scirpt的实现, 就会发现它的逻辑确实略显晦涩.
四.用法
用法已经更新, 大家到这里查看.
五.后记
项目现已开源至github, 地址https://github.com/justbilt/untp, 并提供了 windows 和 mac 的可执行文件, 位于 Release Page, 有问题欢迎评论或 issue 告知!
(–EOF–)