最近在做一款麻将类的游戏,需要使用大量的精灵对象,于是顺便学习了一下批处理节点与纹理贴图集。
在Cocos2d中,精灵CCSprite对象可以直接通过加载图片的形式创建,这是最简单的形式,例如:
- CCSprite* background = [CCSprite spriteWithFile:@"Background.png"];
- [self addChild:background];
所谓浪费内存,其原因是在为图片分配内存空间时,需要分配超过图片尺寸的,且是最小的2的幂次的尺寸。例如,对于上述代码中的Background.png图片,如果其长和宽分别是129px和65px,则分配的内存空间需要256*128*每个像素占用的内存字节数。可以发现实际的图片信息大约只占用了内存空间的1/4,也就是说将近3/4的内存空间被浪费了。每通过图片创建一个精灵,就会发生内存浪费的现象。精灵数量越多,内存的浪费越严重。
所谓降低效率,是指在生成精灵CCSprite对象的时候,Cocos2d会进行渲染操作。渲染操作包括图形处理硬件的准备渲染、执行渲染以及最后的清理工作。精灵越多,游戏的执行速度越慢。
那么如何解决呢?可以使用精灵批处理节点CCSpriteBatchNode与纹理贴图集解决,前者主要用于减少相同图片的渲染操作,后者可以有效节约内存。
如果游戏中需要创建很多基于相同图片的精灵,例如屏幕中的大量子弹,如果每次都单独创建一个精灵的话,每次都需要渲染。但是如果将他们加入到精灵批处理节点CCSpriteBatchNode中,则只需执行一次渲染即可。CCSpriteBatchNode类似于图层,它是一个精灵的容器,并且要求这些精灵都基于相同的图片(如果不是相同图片则报错)。基本的代码结构如下:
- CCSpriteBatchNode* batchNode = [CCSpriteBatchNode batchNodeWithFile:@"bullet.png"];
- [self addChild:batchNode];
- for (int i = 0; i < 500; ++i)
- {
- CCSprite* bullet = [CCSprite spriteWithFile:@"bullet.png"];
- [batchNode addChild:bullet];
- }
既然每次通过图片创建精灵都会发生内存浪费的现象,所以何不将所有图片整合成一张大图片呢?这张大图就称作纹理贴图集(Texture Atlas)。通过纹理贴图集和批处理节点,就可以达到既节省内存,又提升渲染速度的目的。纹理贴图集的长和宽都满足2的n次方,应该把尽可能多的图片放入一个纹理贴图集中。
纹理贴图集中的每一个小图片需要对应一个它在贴图集中的尺寸和偏移量信息,这个信息就称作精灵框架(Sprite Frame)。有了精灵框架信息,就能够从大图中取出对应位置的小图。如果你有很多单独的图片,可以使用现有的工具创建贴图集。我个人推荐使用TexturePacker,可以从www.texturepacker.com下载。下次内容将介绍如何使用TexturePacker创建贴图集。