深入了解精灵

6 深入了解精灵

       精灵可以从单个文件创建,也可以从纹理图册创建。

       纹理图册是指包含多个图像文件的纹理,通常用来保存某个角色的所有动画帧。

       精灵批处理是一种用来加速精灵绘制的技术,它可以提高大量相同精灵的绘制速度,但配合纹理图层使用会更高效。如果将精灵批处理技术与纹理图册配合使用,那么只需一次绘制调用就可以完成纹理图册中全部图像的绘制。

       绘制调用是指传送相关信息到图形硬件以渲染全部或部分纹理的过程。当使用CCSprite时,每个CCSprite节点都会产生一次绘制调用。各次绘制调用的开销累加到一定程度时,就会使帧率降低15%甚至更多。

6.1 CCSpriteBatchNode

       每当在屏幕上绘制一个纹理时,图形硬件都要做前后三个工作:准备渲染、渲染图像和渲染后的清除。这些工作产生了渲染一个纹理所固有的开销。要想缓解此状况,就需要让硬件知道需要进行渲染的这一组精灵使用的是同一纹理。这样一来,图形硬件就会为这组精灵只进行一次准备、渲染和清除的工作。

       CCSpriteBacthNode传入一个图像文件作为参数的原因在于,所有添加到CCSOriteBatchNode节点中的CCSprite节点都必须使用相同的纹理。

6.1.1 何时使用CCSpriteBatchNode

       由于CCSprite节点全部添加到一个CCSpriteBatchNode中,因此它们将以相同的Z轴次序(z-order,即景深)进行绘制。

       CCSpriteBatchNode的另一个不足之处是所有添加到它里面的CCSprite节点都必须使用相同的纹理。但当使用纹理图册时,CCSpriteBatchNode就显得相当重要了。纹理中可以添加很多不同的图像,令CCSpriteBacthNode使用一个纹理图册,这样绘制就不会限制在一幅图像上,而是可以利用同一个CCSpriteBatchNode绘制图册中的所有图像,从而加速图像的渲染。

       在这里,Z轴次序不再是什么问题,可以在CCSpriteBatchNode中直接指定相关CCSprite节点的Z轴次序。如果游戏中使用的图像都可以装进同一个纹理图册里,那么一个CCSpriteBatchNode就可以组成整个游戏。

       除了只接受使用相同纹理的CCSprite节点外,CCSpriteBatchNodeCCLayer类似。

6.1.2 示例项目

       警告:

     通常在默认的初始化函数“-(id) init”中不应该加入除[super init]之外的其他任何调用。如果不得不在类的初始化函数中调用[super initWith...],那么请对初始化函数进行重命名,如“-(id) initWith...”之类

       节点不应该保留任何不属于它的其他节点。

6.2 精灵动画初体验

       CCAnimate动作使用了一个CCAnmation对象,他是动画帧的容器,定义了各帧之间的延时,并给动画指定冷一个名字。动画的名字很有用,可以用来访问特定的动画。也可以用于将动画存入一个CCSprite节点。

       CCSpriteFrame只接受CCTexture2D对象作为输入而不能直接传入图像文件。而纹理使用CCTextCache单件的addImage方法来创建,这样一来,所需的5个文件名就不用分别写出了。

      

       创建并播放精灵动画的方法:

       1)创建一个NSMutableArray对象

       2)对动画各帧:

              为每幅图像创建一个CCTexture2D对象。

              使用CCTexture2D对象创建CCSpriteFrame对象。

              将每个CCSpriteFrame对象都加入到NSMutableArray序列中。

       3)使用NSMutableArray中的帧创建一个CCAnimation对象。

       4)将CCAnimation存入CCSprite节点(可选)。

       5)使用CCAnimate动作播放动画。

6.3 用于创建动画的辅助类别

       “类别提供了一种为现有类添加新方法而产生修改的方式。使用类别唯一的不足在于,只能向类中添加新方法,而无法添加成员变量。

       Objective-C中,类别的@interface后面跟的名字是需要被扩展的类名,之后是位于圆括号中的类别名。类别名类似于变量名,其中不可以包含空格或其他不能在变量名中使用的字符,如标点符号。@interface中也不能包含花括号,因为不允许向类别中添加成员变量。

6.4 使用纹理图册

       纹理图册可以帮助我们节约宝贵的内存,同时提高精灵的渲染速度。因为纹理图册本质上就是一张大的纹理,所以可以使用CCSpriteBatchNode渲染其中的所有图像,从而减少绘制调用的开销。纹理图册的使用为提高性能保险的同时减少内存使用提供了解决方案。

6.4.1 何为纹理图册

       纹理图册就是一张尺寸为2的方幂的大图像,里面包含许多小图像。对于里面的每张图像,都有一个与之对应的精灵框架。精灵框架是一个CGRect结构,它定义了纹理图册中每张小图像的矩形范围,使用cocos2d便可从纹理图册中取出特定的单个图像进行渲染。精灵框架保存在一个独立的.plist文件中。

6.4.2 Zwoptex工具介绍

       Zwoptex是专门用来将图像放入纹理图册并标出精灵框架的2D精灵打包工具。网址:http://zwoptexapp.com

6.4.3 使用Zwoptex桌面版创建纹理图册

       Zwoptex工具的使用十分简单,大体的步骤只有简单几步。真正花费事件的是微调各项设置以生成最优纹理图册所需的时间。

       第一步是将希望添加到纹理图册中的图像文件导入,可以在软件使用的任何时刻添加新图像或删除原有图像。

       刚添加进来的图像都堆在了左上角。这时需要在Layout窗格中单击Apply按钮以按照当前的布局设置来布局精灵。在某些情况下,你可以通过试验找出使纹理图册能够容纳更多的最优布局设置——但这是一项耗时的工作,而且最终接到的结果也差不多。所以建议你不要在这上面花太多事件,特别是对于Sort OnSort Order这两个选项,直接使用Use Best即可。                      

       警告:

       除非你是专门为iPhone 3GSiPadiPhone4或其他未来产品开发游戏,否则不要使用宽度或高度为2048像素的画布,因为老的设备最多支持1024*1024像素大小的纹理。

       选中Layout窗格中的Allow Rotation复选框后,将会允许Zwoptex对图像旋转90度,有时这样做有助于在纹理相册中容纳更多图像,尤其是对某些特别宽或特别高的图像。

       旋转并不影响精灵在屏幕上的显示。cocos2d会将纹理图册中图像的旋转考虑在内,在显示前将图像旋转到原来的方向。

       警告:

       如果在对图像进行了手工选择,并且在Layout窗格中选中Allow Rotation复选框并应用布局,那么可能会丢失之前旋转操作的结果。

       Zwoptex可以将图像额外的透明边缘去掉以减少图像尺寸,从而节省纹理图册中的空间。而在图像显示时,cocos2d会把去掉边缘所造成的偏移计算上,这样可以使图像显示在正确的位置上。

Padding选项指定了各个图像间所留空隙的大小,单位是像素。默认是两个像素,它能够保证纹理图册中的所有图像可以正常显示。Padding的值小于2时,图像显示时边界周五会出现散乱的像素点,像素点的数目和颜色取决于纹理图册中该图像周围图像的像素。这属于技术性问题,与图形硬件过滤纹理的方式有关,唯一的解决方法就是将Padding设为一定数值,使纹理图册中的图像之间保持一定的间距。

6.4.4 cocos2d中使用纹理相册

       首先要做的饿是将新生成的纹理图册添加到Xcode项目的Resource组中——只需将.png.plist文件添加进来即可,其他的话如.zss.zssxml这类Zwoptex设置文件不必添加。

       注意:

       如果需要用到512*512或更大尺寸的纹理图册中的纹理,那么应该在游戏进行之前加载纹理。加载这类大的纹理需要花费一定的是将(如果在游戏时加载,最坏的情况会导致游戏停滞数秒)。

6.4.5 改进CCAnimation辅助类别

6.4.6 将所有图像都放入一个纹理图册中

       操作代码时,应该将代码根据逻辑进行分块,而使用纹理图册时则不同,应该在每个纹理图册中放入尽可能多的图像以减少空间浪费。

       由于cocos2d自动缓存所有图像,因此需要一个方法来卸载不同的纹理。绝大多数情况下,可以使用cocos2d中的如下方法完成这项工作:

[[CCSpriteFrameCache sharedSpriteFrameCache]   

removeUnusedSpriteFrames];

[[CCTextureCache sharedTextureCache] removeUnusedTextures];

       很明显只有当存在不使用的纹理时才能调用这两个方法,而且通常是在更换场景后再卸载纹理,而不是在游戏进行中。记住,只有当新场景完成初始化后,前一个场景才会从内存中释放。这就意味着你不能在一个场景的init方法中使用removeUnused方法,除非在前后场景间加上一个第5章介绍过的LoadingScene,为其添加代码,使其在被新场景替换之前移除前一场景不用的纹理。

       如果非要在加载新的纹理之前从内存中移除所有旧的纹理,那么应该使用如下的purge方法:

       [CCSpriteFrameCachepurge SharedSSpriteFrameCache];

       [CCTextureCache purgeSharedTextureCache];

6.5 自己动手

       可以使用免费的Seashore作为图像编辑器,它的下载网址为http://seashore.sourceforge.net。至于动画处理,也有一个名为Pixen的免费开源软件,下载地址:http://opensword.org/Pixen

       至于音频制作,如果想自己制作歌曲或音效,可以使用GarageBand,它已经预装在你的Mac上了。你只需用一个麦克风录制声音,花点时间处理音频,最后在合适的地方使用即可。

6.6 本章小结

<!--EndFragment-->

猜你喜欢

转载自bsr1983.iteye.com/blog/1628524