首先介绍一下纹理的相关概念。
Image ----》 纹理 (Texture) ---》内存 ---》GPU
游戏在运行过程中要把所有要使用到的图片都加载成GPU可以理解执行的OpenGL ES纹理,注意图像填充到纹理中时,其长度和宽度都应该是2的N次方。
CCTexture2D 这是cocos2d中内置的一个纹理类,用于管理纹理的相关信息,它知道如何将自己绘制到屏幕上,我们可以通过这个类创建纹理的实例对象。
CCTextureCache 纹理缓存管理,负责加载图片并对生成的纹理进行管理。通过“字典”来进行快速的查询,作为单例使用。
CCTextureAtlas 纹理图集,就是把多个纹理合并成的一个大的纹理图。
CCTexture2D *text2d = [[CCTextureCache sharedTextureCache] addImage:file];
下面介绍一下与精灵有关的内容。
通过上面的这个关系图,我们可以知道,CCSprite 精灵和 CCSpriteFrame 精灵帧都是由Texture 纹理绘制的,CCTexture2D就是封装了Texture纹理的类,精灵和精灵帧都必须被赋予一个CCTexture2D的对象才能工作。所以,通过CCTextur2D的实例对象可以创建精灵和精灵帧。
而CCSpriteBatchNode精灵表单是用于管理CCSprite精灵的,它其实是很多精灵的集合。那么它有什么作用呢?
一般我们使用精灵sprite的时候,我们是通过addChild的方式把精灵添加到一个layer中,sprite的draw函数在每一帧调用时都会执行opengl es调用来完成
sprite的渲染。那么当你有多个精灵都通过addChild的方式添加到layer的时候,就会单独绘制多次,就会调用多次的opengl es对精灵进行渲染,那这样的话是很
浪费资源和时间的。
而有了精灵表单CCSpriteBatchNode 后,我们是先把任意个的精灵添加到精灵表单之后,再把精灵表单addChild到layer,这个时候才调用opengl es对精灵
表单中所有的精灵进行渲染。
举个例子,假如我们需要添加100个精灵
①如果不使用精灵表单,那么底层的绘制过程我们可以这样理解 for(int i= 0;i<100;i++){open-draw-close;}
②使用精灵表单的话,那么就是对这100个精灵集合的精灵表单进行一次渲染,也即 open-draw(100次绘制)-close
从以上两种方式可以看出两者的区别了,第二种使用精灵集合省去了99次open和close的过程,从而达到优化处理的作用;
CCSpriteFrame 精灵帧
CCSpriteFrameCache 精灵帧缓存
精灵帧主要是用来制作动画的,cocos2d用CCAnimation保存一个精灵帧序列,然后用CCAnimate这个行为类根据序列定时切换精灵的当前帧实现动画效果,而精灵帧缓存就是主要存放精灵帧的,其主要作用也是优化精灵帧。
下面介绍一下动画,其实动画也是属于CCAction。
通过上面这张关系图讲解动画。
1、首先要了解三个概念:
CCAnimate 动画动作 在sprite对象上执行的动画动作
CCAnimation 动画 在CCAnimate动作的对象
CCAnimationCache 这个类是单例,缓存CCAnimation动画,也是用于优化的。
2、普通创建动画的步骤:
①首先创建sprite,并add到当前节点
②创建CCAnimation动画动作的对象,添加帧内容(精灵帧)
③创建CCAnimate动画动作,并指定动作的对象animation
④sprite执行动作
示例代码如下:
CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:@"dragon.png"]; CCSpriteBatchNode *spriteBatchNode = [CCSpriteBatchNode batchNodeWithTexture:texture]; [self addChild:spriteBatchNode]; NSMutableArray *framesArray = [NSMutableArray array]; for (int i=0; i<8; i++) { for (int j =0; j<10; j++) { CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:texture rect:CGRectMake(j*75, i*70, 75, 70)]; [framesArray addObject:frame]; } } CCAnimation *animation = [CCAnimation animationWithSpriteFrames:framesArray delay:0.1]; CCAnimate *animate = [CCAnimate actionWithAnimation:animation]; CCSpriteFrame *frame1 = [CCSpriteFrame frameWithTexture:texture rect:CGRectMake(0, 0, 72, 70)]; CCSprite *sprite = [CCSprite spriteWithSpriteFrame:frame1]; id repeatAction = [CCRepeatForever actionWithAction:animate]; [sprite runAction:repeatAction]; [sprite setPosition:ccp(150, 150)]; [self addChild:sprite];
这个是上面代码中所用到的资源图片。
3、
通过上面的普通创建动画的步骤可以知道,动画中包含着多个精灵帧,如果我们使用单独的精灵,那么每次都需要调用OpenGl ES 绘图命令,当游戏中有很多的精灵时,速度就会大大降低。那么就要考虑如何优化。
通常的方式是--精灵表单 CCSpriteBatchNode
关于精灵表单,就好像一张由很多个精灵的小图片拼接而成的大图,精灵表单会提供一个文件plist,在其中指定单个精灵的边界和大小,使用时从表单中提取单个精灵。
关于制作精灵表单,可以使用Zwoptex这个工具。它可以将我们需要用到的所有精灵图片制作成一个精灵表单大图png和一个plist文件。
有了png和plist就可以创建动画了。
步骤:
①使用plist文件将精灵纹理图添加到CCSpriteFrameCache中
②创建精灵表单CCSpriteBatchNode,添加到当前的节点。
注意:当需要从精灵表单中创建某一精灵对象时,我们应将其添加为精灵表单的子节点,而不能将其直接添加为当前层的子节点。
③从CCSpriteFrameCache(精灵帧缓存)中获取与图片名称相对应的精灵帧,然后创建精灵帧数组
④创建CCAnimation动画对象,传入精灵帧数组作为参数
⑤创建精灵,CCAnimate,执行CCAnimation动画对象
说明:这里动画包含的精灵帧愈多,那么动画的效果会愈好。
// 1.使用plist文件将精灵帧纹理添加到精灵帧缓存中 [[CCSpriteFrameCache sharedSpriteFrameCache]addSpriteFramesWithFile:@"MyPanda_default.plist"]; // 2.创建一个CCSpriteBatchNode(精灵表单)对象,并把它添加到当前的layer中,就会一次性加载这张精灵表单大图了。 CCSpriteBatchNode *batchNode = [CCSpriteBatchNode batchNodeWithFile:@"MyPanda_default.png"]; [self addChild:batchNode]; // 3.创建图片帧列表(数组) NSMutableArray *walkAnimFrames = [NSMutableArray array]; for(int i=1; i<=3;i++){ [walkAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache]spriteFrameByName:[NSString stringWithFormat:@"pandawalk%d.png",i]]]; } // 4.通过精灵帧数组创建动画对象 CCAnimation *walkAnim = [CCAnimation animationWithSpriteFrames:walkAnimFrames delay:0.5]; // 5.创建精灵对象,并运行动画动作 CGSize size = [CCDirector sharedDirector].winSize; //从精灵表单中的pandawalk1.png图片来创建sprite,项目中并没有这个图片文件 CCSprite *panda = [CCSprite spriteWithSpriteFrameName:@"pandawalk1.png"]; panda.position = ccp(size.width*0.8,size.height*0.4); id walkAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:walkAnim]]; [panda runAction:walkAction]; //注意这里:我们从精灵表单中创建了精灵,所以我们要把它添加为精灵表单的子节点 [batchNode addChild:panda];
下面简单的解释一下这段代码。
我们通过plist文件初始化了精灵帧缓存,以后我们可以根据精灵帧所对应图片的名称来找到相应的精灵帧(plist中都保存着这些信息),所以注意图片资源文件的命名规则,都是以数字1 2 3 ...结尾的。
接着用纹理大图初始化精灵表单,通过add就可以一次性加载所有的精灵了。