cocos2d-x 2.2.3 通過plist創建sprite的過程簡單分析(轉)

原始文章地址:http://blog.csdn.net/a102111/article/details/38657323

// 通過plist載入緩存
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("test.plist");
// 通過緩存載入sprite
CCSprite* sp = CCSprite::createWithSpriteFrameName("test01.png");

以上2句代碼,可以通過plist創建一個sprite,簡單分析下過程。

通過plist載入緩存
首先是通過plist載入緩存,跟蹤到源碼看到如下片段:

void CCSpriteFrameCache::addSpriteFramesWithFile(const char *pszPlist)
{
    CCAssert(pszPlist, "plist filename should not be NULL");
    // 判斷是否加載過該文件 如果沒加載過,才做以下這些事情
    if (m_pLoadedFileNames->find(pszPlist) == m_pLoadedFileNames->end())
    {
    // 獲取完整路徑名,創建dict
        std::string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszPlist);
        CCDictionary *dict = CCDictionary::createWithContentsOfFileThreadSafe(fullPath.c_str());

        string texturePath("");
    // 嘗試獲取textureFileName,如果需要指定,格式大概長這樣:
    // <key>metadata</key>
    // <dict>
    //  <key>textureFileName</key>
    //  <string>tex.png</string>
    // </dictt>
    // 指定載入tex.png
        CCDictionary* metadataDict = (CCDictionary*)dict->objectForKey("metadata");
        if (metadataDict)
        {
            // try to read  texture file name from meta data
            texturePath = metadataDict->valueForKey("textureFileName")->getCString();
        }
    // 如果有指定tex文件,則直接查找完整路徑
        if (! texturePath.empty())
        {
            // build texture path relative to plist file
            texturePath = CCFileUtils::sharedFileUtils()->fullPathFromRelativeFile(texturePath.c_str(), pszPlist);
        }
        else    // 沒有指定tex文件,載入plist對應的png,比如plist文件名:abc.plist,則載入的png爲:abc.png
        {
            // build texture path by replacing file extension
            texturePath = pszPlist;

            // remove .xxx
            size_t startPos = texturePath.find_last_of("."); 
            texturePath = texturePath.erase(startPos);

            // append .png
            texturePath = texturePath.append(".png");

            CCLOG("cocos2d: CCSpriteFrameCache: Trying to use file %s as texture", texturePath.c_str());
        }
    // 載入圖片
        CCTexture2D *pTexture = CCTextureCache::sharedTextureCache()->addImage(texturePath.c_str());

        if (pTexture)
        {
        // 載入spriteFrames
            addSpriteFramesWithDictionary(dict, pTexture);
            m_pLoadedFileNames->insert(pszPlist);
        }
        else
        {
            CCLOG("cocos2d: CCSpriteFrameCache: Couldn't load texture");
        }

        dict->release();
    }

}

然後到了這裏:

void CCSpriteFrameCache::addSpriteFramesWithDictionary(CCDictionary* dictionary, CCTexture2D *pobTexture)
{
/*
// format 4種格式支持
Supported Zwoptex Formats:

ZWTCoordinatesFormatOptionXMLLegacy = 0, // Flash Version
ZWTCoordinatesFormatOptionXML1_0 = 1, // Desktop Version 0.0 - 0.4b
ZWTCoordinatesFormatOptionXML1_1 = 2, // Desktop Version 1.0.0 - 1.0.1
ZWTCoordinatesFormatOptionXML1_2 = 3, // Desktop Version 1.0.2+
*/
// 分離2個dict
CCDictionary *metadataDict = (CCDictionary*)dictionary->objectForKey("metadata");
CCDictionary *framesDict = (CCDictionary*)dictionary->objectForKey("frames");
int format = 0;
// 從metadata獲取格式 默認爲0
if(metadataDict != NULL) 
{
    format = metadataDict->valueForKey("format")->intValue();
}
// 檢測format 支持0-3
CCAssert(format >=0 && format <= 3, "format is not supported for CCSpriteFrameCache addSpriteFramesWithDictionary:textureFilename:");
// 遍歷frames
CCDictElement* pElement = NULL;
CCDICT_FOREACH(framesDict, pElement)
{
    CCDictionary* frameDict = (CCDictionary*)pElement->getObject();
    std::string spriteFrameName = pElement->getStrKey();    // 取key作爲sprite名
// 如果已經加載過 不再處理
    CCSpriteFrame* spriteFrame = (CCSpriteFrame*)m_pSpriteFrames->objectForKey(spriteFrameName);
    if (spriteFrame)
    {
        continue;
    }
// 根據format處理
    if(format == 0) 
    {
        float x = frameDict->valueForKey("x")->floatValue();
        float y = frameDict->valueForKey("y")->floatValue();
        float w = frameDict->valueForKey("width")->floatValue();
        float h = frameDict->valueForKey("height")->floatValue();
        float ox = frameDict->valueForKey("offsetX")->floatValue();
        float oy = frameDict->valueForKey("offsetY")->floatValue();
        int ow = frameDict->valueForKey("originalWidth")->intValue();
        int oh = frameDict->valueForKey("originalHeight")->intValue();
        // check ow/oh
        if(!ow || !oh)
        {
            CCLOGWARN("cocos2d: WARNING: originalWidth/Height not found on the CCSpriteFrame. AnchorPoint won't work as expected. Regenrate the .plist");
        }
        // abs ow/oh
        ow = abs(ow);
        oh = abs(oh);
        // create frame
        spriteFrame = new CCSpriteFrame();
    // 對照一下,大概就明白了
    // initWithTexture(CCTexture2D* pobTexture, const CCRect& rect, bool rotated, const CCPoint& offset, const CCSize& originalSize)
        spriteFrame->initWithTexture(pobTexture, 
                                    CCRectMake(x, y, w, h), 
                                    false,
                                    CCPointMake(ox, oy),
                                    CCSizeMake((float)ow, (float)oh)
                                    );
    } 
...// 以下類似

    // 加入緩存,名字用spriteFrameName <span style="font-family: Arial, Helvetica, sans-serif;"> m_pSpriteFrames是一個dict</span>
    m_pSpriteFrames->setObject(spriteFrame, spriteFrameName);
    spriteFrame->release();
}

}

於是,這部分的大概流程就是:
載入plist,載入texture,根據plist選擇texture的區域,載入spriteFrame,加入到緩存。

通過緩存載入sprite

CCSprite* CCSprite::createWithSpriteFrameName(const char *pszSpriteFrameName)
{
    // 從緩存裏取對應名字的spriteFrame
    CCSpriteFrame *pFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(pszSpriteFrameName);

#if COCOS2D_DEBUG > 0
    char msg[256] = {0};
    sprintf(msg, "Invalid spriteFrameName: %s", pszSpriteFrameName);
    CCAssert(pFrame != NULL, msg);
#endif

    return createWithSpriteFrame(pFrame);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章