// 通过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,如果需要指定,格式大概长这样:

// metadata

//

// textureFileName

// tex.png

//

// 指定载入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  m_pSpriteFrames是一个dict

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);

}