cocos2dx 源碼學習2 CCAnimationCache

我們經常會使用到CCSprite這個類,在cocos2dx源碼中,用Visual Studio打開後他位於libcocos2d項目的sprite_node文件夾下:


CCAnimationCache類用來保存CCAnimation,這樣後續就可以直接用於創建CCAnimate動畫作用於CCSprite。下面看一下CCAnimationCache的源碼:

一.公有成員函數


(1)從頭文件中我們可以看到,最基本的類的構造函數和析構函數。

 (2)void addAnimation(CCAnimation *animation, const char * name);

添加一個CCAnimation對象後跟一個參數name,因爲CCAnimationCache採用字典的形式來存儲的,在cpp文件中我們可以看到這樣的實現

void CCAnimationCache::addAnimation(CCAnimation *animation, const char * name)
{
    m_pAnimations->setObject(animation, name);
}

m_pAnimations爲CCAnimationCache類的私有變量,可以看出是一個字典類型

private:
    CCDictionary* m_pAnimations;

(3) void removeAnimationByName(const char* name);

這個一看函數名就知道,是移除之前添加的對應name的CCAnimation 對象。cpp是這樣實現的:

void CCAnimationCache::removeAnimationByName(const char* name)
{
    if (! name)
    {
        return;
    }


    m_pAnimations->removeObjectForKey(name);
}

先判斷name是不是爲空,然後再移除。

(4)CCAnimation* animationByName(const char* name);

根據name在字典中查找CCAnimation,找到則返回此對象,用於後續CCSprite的動畫。在cpp中是這樣實現的

CCAnimation* CCAnimationCache::animationByName(const char* name)
{
    return (CCAnimation*)m_pAnimations->objectForKey(name);
}

(5)void addAnimationsWithDictionary(CCDictionary* dictionary,const char* plist = NULL);

從一個字典中添加CCAnimation,就是說,我們先把CCAnimation存入字典中,在把這個字典作爲參數。後跟一個plist,plist可傳可不傳,表示對應的plist文件,所以我們事先必須先用 CCSpriteFrameCache把我們需要的資源文件加載。其中CCDictionary有一個函數createWithContentsOfFile,可以直接把plist文件中的動畫直接保存在字典中。下面舉一例子:

 CCDictionary* pDict = CCDictionary::createWithContentsOfFile("animations.plist");

animCache->addAnimationsWithDictionary(pDict);


(6) void addAnimationsWithFile(const char* plist);

從一個plist中加載。我們看下源代碼就知道他是如何實現的:

void CCAnimationCache::addAnimationsWithFile(const char* plist)
{
    CCAssert( plist, "Invalid texture file name");


    std::string path = CCFileUtils::sharedFileUtils()->fullPathForFilename(plist);
    CCDictionary* dict = CCDictionary::createWithContentsOfFile(path.c_str());


    CCAssert( dict, "CCAnimationCache: File could not be found");


    addAnimationsWithDictionary(dict,plist);
}

從中可以看出,其實是調用了前一個函數 addAnimationsWithDictionary實現的,其中也用到了我們之前說的函數createWithContentsOfFile。

二.私有成員函數

除了上面的公有函數外,CCAnimationCache還有兩個靜態成員函數,其次CCAnimationCache被設計成了單例模式:


(1)static CCAnimationCache* sharedAnimationCache(void);

既是靜態成員函數,也是單例實現函數。

CCAnimationCache* CCAnimationCache::s_pSharedAnimationCache = NULL;


CCAnimationCache* CCAnimationCache::sharedAnimationCache(void)
{
    if (! s_pSharedAnimationCache)
    {
        s_pSharedAnimationCache = new CCAnimationCache();
        s_pSharedAnimationCache->init();
    }


    return s_pSharedAnimationCache;
}

在頭文件中聲明保護成員:

private:
    CCDictionary* m_pAnimations;
    static CCAnimationCache* s_pSharedAnimationCache;

如果我們想自己寫的類也變成單例,我們也可以仿照這樣來實現。

(2) static void purgeSharedAnimationCache(void);

此函數用來釋放單例對象,刪除所有的保存的CCAnimation


下面例舉官方實例TestCpp中的實現:

        CCSpriteFrameCache *frameCache = CCSpriteFrameCache::sharedSpriteFrameCache();
frameCache->addSpriteFramesWithFile("grossini.plist");
frameCache->addSpriteFramesWithFile("grossini_gray.plist");
frameCache->addSpriteFramesWithFile("grossini_blue.plist");

// Purge previously loaded animation
CCAnimationCache::purgeSharedAnimationCache();


CCAnimationCache *animCache = CCAnimationCache::sharedAnimationCache();
CCDictionary* pDict = CCDictionary::createWithContentsOfFile("animations.plist");

animCache->addAnimationsWithDictionary(pDict);//用字典創建
// Add an animation to the Cache
//animCache->addAnimationsWithFile("animations.plist");   //用plist文件創建


CCAnimation *normal = animCache->animationByName("dance_1");
normal->setRestoreOriginalFrame(true);
CCAnimation *dance_grey = animCache->animationByName("dance_2");
dance_grey->setRestoreOriginalFrame(true);
CCAnimation *dance_blue = animCache->animationByName("dance_3");
dance_blue->setRestoreOriginalFrame(true);

CCAnimate *animN = CCAnimate::create(normal);
CCAnimate *animG = CCAnimate::create(dance_grey);
CCAnimate *animB = CCAnimate::create(dance_blue);

CCSequence *seq = CCSequence::create(animN, animG, animB, NULL);

// create an sprite without texture
CCSprite *grossini = CCSprite::create();

CCSpriteFrame *frame = frameCache->spriteFrameByName("grossini_dance_01.png");
grossini->setDisplayFrame(frame);

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

grossini->setPosition(ccp(winSize.width/2, winSize.height/2));

addChild(grossini);

// run the animation
grossini->runAction(seq);


pilst文件格式如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>animations</key>
<dict>
<key>dance_1</key>
<dict>
<key>delay</key>
<real>0.2</real>
<key>frames</key>
<array>
<string>grossini_dance_01.png</string>
<string>grossini_dance_02.png</string>
<string>grossini_dance_03.png</string>
<string>grossini_dance_04.png</string>
<string>grossini_dance_05.png</string>
<string>grossini_dance_06.png</string>
<string>grossini_dance_07.png</string>
<string>grossini_dance_08.png</string>
<string>grossini_dance_09.png</string>
<string>grossini_dance_10.png</string>
<string>grossini_dance_11.png</string>
<string>grossini_dance_12.png</string>
<string>grossini_dance_13.png</string>
<string>grossini_dance_14.png</string>
</array>
</dict>
<key>dance_2</key>
<dict>
<key>delay</key>
<real>0.2</real>
<key>frames</key>
<array>
<string>grossini_dance_gray_01.png</string>
<string>grossini_dance_gray_02.png</string>
<string>grossini_dance_gray_03.png</string>
<string>grossini_dance_gray_04.png</string>
<string>grossini_dance_gray_05.png</string>
<string>grossini_dance_gray_06.png</string>
<string>grossini_dance_gray_07.png</string>
<string>grossini_dance_gray_08.png</string>
<string>grossini_dance_gray_09.png</string>
<string>grossini_dance_gray_10.png</string>
<string>grossini_dance_gray_11.png</string>
<string>grossini_dance_gray_12.png</string>
<string>grossini_dance_gray_13.png</string>
<string>grossini_dance_gray_14.png</string>
</array>
</dict>
<key>dance_3</key>
<dict>
<key>delay</key>
<real>0.2</real>
<key>frames</key>
<array>
<string>grossini_blue_01.png</string>
<string>grossini_blue_02.png</string>
<string>grossini_blue_03.png</string>
<string>grossini_blue_04.png</string>
</array>
</dict>
</dict>
</dict>
</plist>


因爲addAnimationsWithDictionary函數在進行解析時,是先查找animations關鍵字段。從源碼可以看出:

void CCAnimationCache::addAnimationsWithDictionary(CCDictionary* dictionary,const char* plist)
{
    CCDictionary* animations = (CCDictionary*)dictionary->objectForKey("animations");


    if ( animations == NULL ) {
        CCLOG("cocos2d: CCAnimationCache: No animations were found in provided dictionary.");
        return;
    }


    unsigned int version = 1;
    CCDictionary* properties = (CCDictionary*)dictionary->objectForKey("properties");
    if( properties )
    {
        version = properties->valueForKey("format")->intValue();
        CCArray* spritesheets = (CCArray*)properties->objectForKey("spritesheets");


        CCObject* pObj = NULL;
        CCARRAY_FOREACH(spritesheets, pObj)
        {
            CCString* name = (CCString*)(pObj);
            if (plist)
            {
                const char* path = CCFileUtils::sharedFileUtils()->fullPathFromRelativeFile(name->getCString(),plist);
                CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile(path);
            } 
            else
            {
                CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile(name->getCString());
            }            
        }
    }


    switch (version) {
        case 1:
            parseVersion1(animations);
            break;
        case 2:
            parseVersion2(animations);
            break;
        default:
            CCAssert(false, "Invalid animation format");
    }
}



發佈了23 篇原創文章 · 獲贊 1 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章