加载自由尺寸 pvr 的可行方案"/>
cocos2d 加载自由尺寸 pvr 的可行方案
之前看到一篇文章,就是说使用 [CCSprite spriteWithFile:@"test.png"] 这种方式来管理内存的用度是不可取的!
思忖了一下确实觉得有道理,你让程序去自动管理内存,程序是做不到像人这样对程序的理解的,
无可厚非,程序无法在资源不再会被用到的时候马上将之请出内存,
java 是的内存回收机制是这样, objective-c 的 autorelease 也是这样,
要想得到高效运行的程序,你就得付出额外的努力去做一些处理!
spriteWithFile 得到的就是一个 autorealse 的 sprite,
在这个过程中会将一张图片绑定为 opengl 的纹理,
cocos2d里面,opengl 的每一张纹理都由一个 CCTexture2D 对象来管理。
如上,采用 spriteWithFile 加载进来的图片,也是由程序自动管理何时释放的。
那么,到底是何时释放呢?这个答案在网上看到过无数次:在机器的内存不够用的时候才会释放!
我的看法和上面说的写那篇文章的人有点儿出入,即是不一定非得去用 CCSprite alloc] initWithTexture:....这样。
具体请参照我之前转载的那篇文章。
不过,对于 CCTexture2D 的管理,确实得亲力亲为,不需要的时候就给移除了吧。
其实说是这么说,考虑到游戏会重来什么的,有的图片你刚卸载掉,说不定马上又得加载到内存里面
这不是一件容易的事情,你得权衡到底要不要释放,不一定在不需要的时候释放掉了就一定好。
缓存是能够带来性能上的提升的,不过却要耗费额外的内存。
数据库缓存,浏览器缓存,服务器缓存,cpu也有缓存,可以想见,缓存其实也是一个很重要的概念,你不能去无视他。
好吧,讨论一些理论上的东西会显得有些枯燥,让我们来看一些具体的做法:
NPOT 的问题一定要到过吧,稍微有点儿使用 cocos2d 经验的。
NPOT 这个 bug 出现的原因就是因为所使用的 pvr 的尺寸不符合2的n次幂!
但是在一定情况下,不符合 2 的 n 次幂的尺寸的图片美工都给你出好了,你怎么办?
让美工返工,全部改成 2 的 n 次幂?估计你要找打~
这时候推荐一个工具 , texturePacker,通过这个工具你能将不符合尺寸要求的图片放置到另一张复合尺寸要求的图片中。
不过这里将衍生出一个新的问题,生成的东西变成了 2个:
一个是pvr 文件,一个是指明有效图片在容器图片中位置,高宽等数据的 plist 文件。
若要亲力亲为去高效管理 texture,那么就要将目光由 CCSprite 转向 CCTexture2D,
而如上所生成的两个文件,现在已经不能用 CCTextureCache 的 addImage 方法来加载成 CCTexture2D 对象了,
原因很简单,有效纹理只是占据了整张纹理的一部分,用起来十分不方便~
这个时候要用 CCSpriteFrameCache 来进行管理, 用 CCSpriteFrameCache 的 addSpriteFramesWithFile 方法。
使用的使用很简单,CCSprite spriteWithSpriteFrameName 即可。
因为这里并不涉及的打包纹理集,所以说,一份pvr、plist 仅仅对应一张的纹理图片。
完美控制内存释放没有问题,但就是有点儿麻烦:
1。CCSpriteFrameCache 调用 removeSpriteFramesFromFile 将相关的 spriteFrame 对象销毁掉,
这不执行完毕之后,相关 texture 的引用计数会 -1,但-1之后还未达到 0,因此不会被销毁,依然占据内存。
2。CCTextureCache 调用 removeTextureForKey ,这里又会将 相关 texture 的引用计数 -1,
这里依然不能达到0, 因此 texture 又不会被销毁。
3。这步不用你管了,texture 而今只被 sprite 引用着了,等到这个sprite 被自动销毁的时候,texture 就会马上被请出内存。
我用了一点儿小策略,用一个数组成员变量将纹理图片的名字(不带文件后缀)保存了起来,
在dealloc 的时候取出数组中存储的名称作为键,按照前述的步骤对纹理做即时释放~
阐述的不是很清晰,下次得空整理下思路把示例代码贴上来再写一篇~
转载于:.html
更多推荐
cocos2d 加载自由尺寸 pvr 的可行方案
发布评论