一. 删除无用资源

在我们版本迭代的过程中, 总有一些图片被废弃掉, 如果当时忘记删除的话, 久而久之也就忘记了. 如果在上线前不做一次整理的话, 它们就会残存在你的资源中, 浪费包的体积.

为避免这种情况, 我们可以做的是:

1. 废弃的图片一定要及时删除

2. 编写废弃资源查找工具

可以用到的系统命令是 ack, 我们可以通过 brew install ack 安装, 使用的效果:

关于 ack 的更多用法请移步这里.

二. 使用替代对象

1. 使用9图

大家都知道图片在拉伸的过程中会失真, 那么如何避免这个情况呢? 使用9图.

注: 配图来自http://mux.baidu.com/?p=1506

这样我们就可以将一张很大的图缩小到很小, 然后使用9图拉伸, 起到节省资源的目的. 9图在 cocos 中的对象是 Scale9Sprite, 具体用法可以参考这篇文章.

2. 通过修改色调实现资源复用

知乎上有一篇问题讲的就是这个:
拳皇中的人物变色是如何实现的?
知乎日报上的这篇

cocos2d-x 版由 @偶尔e网事 大神实现, 对应的对象是 SpriteWithHue, 目前已经默认集成到了 cocos2d-x 中.

这样我们就可以将原来只是色调差异的图片用程序来实现啦~

3. 使用平铺

注: 配图来自http://bullteacher.com/7-textures.html

游戏中的有些图片完全可以通过平铺实现, 这样的话我们就可以让美术只出一个平铺单元的图片,在程序中去实现平铺.

首先, 平铺的这个功能是 opengl 层面就支持的, 详情大家可以移步这里, cocos2d-x 中实现平铺很简单:

1
2
3
4
5
6
-- 首先, 使用平铺单元图片创建一个精灵
local sprite = cc.Sprite:create("your_repeat_image.png")
-- 然后, 设置纹理参数
sprite:getTexture():setTexParameters(gl.LINEAR, gl.LINEAR, gl.REPEAT, gl.REPEAT)
-- 最后, 将这个精灵的纹理矩形设置为我们想要的大小
sprite:setTextureRect(cc.rect(0,0,1024,1024))

注意: 平铺单元图片的尺寸只能是2的幂

三. 压缩

1. 无损压缩

无损压缩还是十分值得推荐的, 它的原理知乎上这个答案讲的很清晰, 我节选其中的关键文字:

1.核心原理很简单,通俗的解释一下,就是由于PNG格式的灵活性,他可以有很多种方式表示同一张图片,不同方式有时就会导致文件大小不一样…
2.还有一点是PNG采用的是deflate算法,也非常的灵活,他的压缩率和encoder的实现有关,不同的encoder使用的时间,压缩出来的大小都不一样…
3.当然除了上面这两点是真正的无损压缩以外,还有减小PNG文件大小的方式就是去除一些对图片本身没有任何影响的metadata…

所以无损压缩纯粹是单方面的受益, 是一定要做的.

我们无损压缩主要用到的工具: ImageOptim

2. 有损压缩

有损压缩会损失一部分的图片质量, 但带来的受益还是十分可观的. 这是一个抉择的过程, 以最小的代价获取最大的受益, 甚至不能批量处理, 可能需要一张一张的人肉对比压缩.

我们有损压缩主要用到的工具: PP鸭

四. 选择正确的图片格式

1. 将无 alpha 通道的 png 图片存储为 jpg

2. 选用压缩率更高的图片格式

五. 其他

1. 圆形图片只使用 1/4

然后在程序中翻转3次,得到其他角度的图片. 一般会用在图片尺寸特别大的场景.

如上图, 我们游戏中一个全屏幕的雷达就是通过这个方案减少图片体积的.

2. 缩小图片

将展示精度不强的图片(比如: 游戏背景上的小装饰, 爆炸的序列帧)缩小, 在程序中放大.

3. 特殊方案分离png的透明通道

用jpg和黑白色png作为遮罩实现透明
用shader使图片背景透明
cocos2dx中使用JPG图和只带Alpha的PNG图合成渲染

我们之前曾经采取过其中的一个方案, 将一张 png 图片拆分为 jpg+alpha.png 的形式, 整体的包体小了近 25% , 不过也带来的其他的一些副作用.

建议大家使用这类黑科技前一定要做好调研和测试用例, 评估一下实际的收益.