天天看點

CCSpriteBatchNode 和 CCTextureAtlas 詳解

CCSpriteBatchNode的初始化隻要一張圖檔,也就是那張大圖。

然後把所有用到那張大圖裡面的小圖的sprite都加到 CCSpriteBatchNode的child,繪制效率就會提高。

下面是TestCpp中的Demo,SpriteTest

SpriteBatchNode1::SpriteBatchNode1()

{

    setTouchEnabled( true );//讓目前Layer接收觸摸事件

     //建立SpriteBatchNode對象和 CCTextureAtlas 的 四邊形的 容量(預設29)

    CCSpriteBatchNode* BatchNode = CCSpriteBatchNode::create("Images/grossini_dance_atlas.png", 50);

    //首先要把batchNode添加到Layer 可以通過 kTagSpriteBatchNode引用

    addChild(BatchNode, 0, kTagSpriteBatchNode);

    CCSize s = CCDirector::sharedDirector()->getWinSize();

    addNewSpriteWithCoords( ccp(s.width/2, s.height/2) );//添加一個子Sprite,所有的Sprite是添加到batchNode的child Sprite

}

void SpriteBatchNode1::addNewSpriteWithCoords(CCPoint p)

{

    CCSpriteBatchNode* BatchNode = (CCSpriteBatchNode*) getChildByTag( kTagSpriteBatchNode );//得到BatchNode

    int idx = CCRANDOM_0_1() * 1400 / 100;

    int x = (idx%5) * 85;

    int y = (idx/5) * 121; 

    CCSprite* sprite = CCSprite::createWithTexture(BatchNode->getTexture(), CCRectMake(x,y,85,121));                  //建立Sprite

    BatchNode->addChild(sprite); // 将建立好的Sprite添加到BatchNode

   sprite->setPosition( ccp( p.x, p.y) );//設定坐标

    //處理動畫

   CCActionInterval* action;

    float random = CCRANDOM_0_1();

    if( random < 0.20 )

        action = CCScaleBy::create(3, 2);

    else if(random < 0.40)

        action = CCRotateBy::create(3, 360);

    else if( random < 0.60)

        action = CCBlink::create(1, 3);

    else if( random < 0.8 )

        action = CCTintBy::create(2, 0, -255, -255);

    else 

        action = CCFadeOut::create(2);

    CCActionInterval* action_back = action->reverse();

    CCActionInterval* seq = (CCActionInterval*)(CCSequence::create(action, action_back, NULL));

    sprite->runAction( CCRepeatForever::create(seq));// 在新建立的Sprite中應用動畫

}

void SpriteBatchNode1::ccTouchesEnded(CCSet* touches, CCEvent* event)

{

    CCSetIterator it;

    CCTouch* touch;

    for( it = touches->begin(); it != touches->end(); it++) 

    {

        touch = (CCTouch*)(*it);

       if(!touch)

            break;

      CCPoint location = touch->getLocation();

        addNewSpriteWithCoords( location );//在觸摸點添加Sprite層

    }

}

/對SpriteBatchNode中的Sprite進行排序

void SpriteBatchNodeZOrder::reorderSprite(float dt)

{

    CCSpriteBatchNode* batch= (CCSpriteBatchNode*)(getChildByTag( kTagSpriteBatchNode ));

    CCSprite* sprite = (CCSprite*)(batch->getChildByTag(kTagSprite1));

     int z = sprite->getZOrder();

        if( z < -1 )

        m_dir = 1;

    if( z > 10 )

        m_dir = -1;

        z += m_dir * 3;

    batch->reorderChild(sprite, z);

}

/對SpriteBatchNode中的Sprite進行remove和add

void SpriteBatchNodeColorOpacity::removeAndAddSprite(float dt)

{    CCSpriteBatchNode* batch= (CCSpriteBatchNode*)(getChildByTag( kTagSpriteBatchNode ));

    CCSprite* sprite = (CCSprite*)(batch->getChildByTag(kTagSprite5));

        sprite->retain();

    batch->removeChild(sprite, false);

    batch->addChild(sprite, 0, kTagSprite5);

       sprite->release();

}

//在運作時動态修改紋理,适用于NPC更新,會影響所有的child Sprite

  CCSpriteBatchNode* batch = (CCSpriteBatchNode*) getChildByTag( kTagSpriteBatchNode );

    if( batch->getTexture() == m_texture1 )

        batch->setTexture(m_texture2);

    else

        batch->setTexture(m_texture1); 

//SpriteFrameCatcher與SpriteBatchNode結合使用

void SpriteFrameTest::onEnter()

{

    SpriteTestDemo::onEnter();

    CCSize s = CCDirector::sharedDirector()->getWinSize();

    // IMPORTANT(重要聲明):

    // The sprite frames will be cached AND RETAINED, and they won't be released unless you call

  //SpriteFames被緩存和重新引用,需要在不用的适用調用下面方法釋放這些SpriteFrames

    //     CCSpriteFrameCache::sharedSpriteFrameCache()->removeUnusedSpriteFrames);

    CCSpriteFrameCache* cache = CCSpriteFrameCache::sharedSpriteFrameCache();

    cache->addSpriteFramesWithFile("animations/grossini.plist");

    cache->addSpriteFramesWithFile("animations/grossini_gray.plist", "animations/grossini_gray.png");

    cache->addSpriteFramesWithFile("animations/grossini_blue.plist", "animations/grossini_blue.png");

    //

    // Animation using Sprite BatchNode 使用BatchNode建立動畫

    m_pSprite1 = CCSprite::createWithSpriteFrameName("grossini_dance_01.png");//從SpriteFameCache中建立一個Sprite

    m_pSprite1->setPosition( ccp( s.width/2-80, s.height/2) );

    CCSpriteBatchNode* spritebatch = CCSpriteBatchNode::create("animations/grossini.png");//建立SpriteBatchNode 這裡要和 CCSpriteFrameCache一緻

    spritebatch->addChild(m_pSprite1);//将Sprite添加到SpriteBatchNode

    addChild(spritebatch); //将SpriteBatchNode添加到目前layer

    CCArray* animFrames = CCArray::createWithCapacity(15);

    char str[100] = {0};

    for(int i = 1; i < 15; i++) 

    {

        sprintf(str, "grossini_dance_%02d.png", i);

        CCSpriteFrame* frame = cache->spriteFrameByName( str );  //建立動畫的多幀SpriteFrame

        animFrames->addObject(frame);  //添加到CCArray集合

    }

    CCAnimation* animation = CCAnimation::createWithSpriteFrames(animFrames, 0.3f);//建立動畫對象

    m_pSprite1->runAction( CCRepeatForever::create( CCAnimate::create(animation) ) );//Sprite載入動畫Action

   // to test issue #732, uncomment the following line

    m_pSprite1->setFlipX(false);

    m_pSprite1->setFlipY(false);

    //

    // Animation using standard Sprite,根據标準的Sprite建立動畫

    //

    m_pSprite2 = CCSprite::createWithSpriteFrameName("grossini_dance_01.png");

    m_pSprite2->setPosition( ccp( s.width/2 + 80, s.height/2) );

    addChild(m_pSprite2);

   CCArray* moreFrames = CCArray::createWithCapacity(20);

    for(int i = 1; i < 15; i++) 

    {

        sprintf(str, "grossini_dance_gray_%02d.png",i);

        CCSpriteFrame *frame = cache->spriteFrameByName(str);

        moreFrames->addObject(frame);

    }

   for( int i = 1; i < 5; i++) {

        sprintf(str, "grossini_blue_%02d.png",i);

        CCSpriteFrame *frame = cache->spriteFrameByName(str);

        moreFrames->addObject(frame);

    }

 // append frames from another batch

    moreFrames->addObjectsFromArray(animFrames);

    CCAnimation *animMixed = CCAnimation::createWithSpriteFrames(moreFrames, 0.3f);

   m_pSprite2->runAction(CCRepeatForever::create( CCAnimate::create(animMixed) ) );

   // to test issue #732, uncomment the following line

    m_pSprite2->setFlipX(false);

    m_pSprite2->setFlipY(false);

  schedule(schedule_selector(SpriteFrameTest::startIn05Secs), 0.5f);

    m_nCounter = 0;

}

void SpriteFrameTest::onExit()  //釋放 CCSpriteFrameCache中沒有使用的 SpriteFrame

{

    SpriteTestDemo::onExit();

    CCSpriteFrameCache *cache = CCSpriteFrameCache::sharedSpriteFrameCache();

    cache->removeSpriteFramesFromFile("animations/grossini.plist");

    cache->removeSpriteFramesFromFile("animations/grossini_gray.plist");

    cache->removeSpriteFramesFromFile("animations/grossini_blue.plist");

}

CCTextureAtlas 紋理圖集。說白了,它本身儲存一張大圖的紋理和一個記錄畫大圖某一區域的資訊結構體的數組。

5  int  m_uCapacity ,四邊形的容量。