iphone游戏开发之cocos2d( 十一 )使用CCSpriteBatchNode和纹理图册,提高精灵动画效率;

来源:互联网 发布:纸模软件apk 编辑:程序博客网 时间:2024/05/16 06:48

holydancer原创,如需转载,请在显要位置注明:

转自holydancer的CSDN专栏,专栏地址:http://blog.csdn.net/holydancer


之前我们简单地介绍了一下自定义一个精灵,使其在初始化的时候即实现动画,并利用了纹理图册精简代码,今天我们着重介绍一下CCSpriteBatchNode,这是一个相当重要的概念,游戏开发不像应用,大量的动画图片,高速的计算,大量的图形占用,所以我们不得不将图形优化放到一个很高的位置,好在cocos2d在这一块儿上封装得很好,我们只需要了解一下一些类的基本用法,就可以很简单地优化代码;

CCSpriteBatchNode是对绘制精灵进行优化的一个辅助类,看类名我们就可以知道其是一个Node,生成精灵的时候我们需要将其放到层上,如果用CCSpriteBatchNode的话,我们只需要将一个CCspriteBatchNode对象放到该层上,其后将一个一个精灵放到该对象上即可;这样说有些笼统,看一个简单的例子:

有一张png图片"fish.png“,我们需要通过其创建一个精灵添加到层上,那么传统的方式就是:

CCSprite *fishSprite = [CCSprite spriteWithFile:@"fish.png"];

[layer addChild:fishSprite];

如果该层上有10个精灵呢?那就加个for循环,代码上我们感觉效率不低,但在硬件底层,openGL在绘制的时候每次绘制一个精灵,都要有一个准备的过程,形象的说,就像一个画家要画十只鱼,画一只鱼的时候,需要准备调色盘,画笔,画完一只,收起来;画第二只的时候,再准备调色盘,再画,画完再收好;如此十次,画得越多,耽误的越多;这样说的话你就会觉得这个画家有点二,但是传统的绘制精灵还真就是这样,机器不是人,他是不知道自己变通的;所以我们就要用到CCSpriteBatchNode了,上面的代码我们可以这样来改动:

CCSpriteBatchNode *fishBatch = [CCSpriteBatchNode batchNodeWithFile :@"fish.png"];

[layer addChild:fishBatch];

CCSprite *fishSprite = [CCSprite spriteWithFile:@"fish.png"];

[fishBatch addChild:fishSprite];

这样写你可能不觉得有什么优化,但是fishBatch里面添加的精灵越多,其优势就越明显,还是刚才的例子,之前每画一条鱼,都会准备,绘制,收起;现在将精灵添加进fishBatch,就像这个画家知道一次性要画多少条鱼,就不会那么死板的进行一次又一次额外重复的工作了;


如果我们将CCSpriteBatchNode与动画相结合的话,没有关系,假设已生成动画anim;

CCSpriteBatchNode *fishBatch = [CCSpriteBatchNode batchNodeWithFile :@"fish.png"];

[layer addChild:fishBatch];

CCSprite *fishSprite = [CCSprite spriteWithFile:@"fish.png"];

[fishSprite runAction: anim];

[fishBatch addChild:fishSprite];

下面我们来看一个将CCSpriteBatchNode,纹理图册,自定义精灵类(默认初始化运行动作),CCSpriteFrameCache结合起来的例子:

自定义精灵类fishSprite.h:

#import <Foundation/Foundation.h>#import "cocos2d.h"@interface fishSprite : CCSprite {    }+(id)fish;@end

fishSprite.m

#import "fishSprite.h"@implementation fishSprite+(id)fish{    return [[self alloc]initWithImage];}-(id)initWithImage{    if ((self=[super init])) {             [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"fish.plist"];        // 将所有fish.plist相关的精灵添加到缓存里;                              self = [CCSprite spriteWithSpriteFrameName:@"fish1.png"];        //这句很关键,不加这句,CCSproteBatchNode和自定义生成的精灵不会采用同一个纹理,这样强行采用这种技术就会报错;                //下面将纹理图册中的纹理组成动画;使用CCSpriteFrameCache和纹理图册结合会很方便;        NSMutableArray *frameArray = [NSMutableArray array];                for (int i = 1; i<15; i++) {            [frameArray addObject:             [[CCSpriteFrameCache sharedSpriteFrameCache ]spriteFrameByName:              [NSString stringWithFormat:@"fish%d.png",i]]];        }               CCAnimation *fishAnimation = [CCAnimation animationWithSpriteFrames:frameArray delay:0.05f];        CCAnimate *animate = [CCAnimate actionWithAnimation:fishAnimation];                                                           [self runAction:[CCRepeatForever actionWithAction:animate]];        //使该精灵一生成就会运动;                                                                         }    return self;}@end


之后在显示层的init方法中这样添加:

-(id)init{    // ask director for the window size       if (self = [super init]) {        CGSize size = [[CCDirector sharedDirector] winSize];                CCSprite *background;                        background = [CCSprite spriteWithFile:@"bg.jpg"];                background.position = ccp(size.width/2, size.height/2);                // add the label as a child to this Layer        [self addChild: background];                        //    //在层上添加精灵;                        CCSpriteBatchNode *fishBatch = [CCSpriteBatchNode batchNodeWithFile:@"fish.png"];        [self addChild:fishBatch];                CCSprite *fish = [fishSprite fish];        fish.position = ccp(140, 150);                [self addChild:fish];        [self scheduleUpdate];            }       return self;}

这样,代码中的注释很明白,这里再强调一下几点:

1、CCSpriteBatchNode中添加的精灵所依赖的生成纹理必须是一样,包括生成CCSpriteBatchNode对象时所使用的纹理;

2、所有添加进去的精灵,z轴都是一样的,即都依赖于CCSSpriteBatchNode对象的z轴;


原创粉丝点击