// 通过plist载入缓存 CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("test.plist"); // 通过缓存载入sprite CCSprite* sp = CCSprite::createWithSpriteFrameName("test01.png");
以上2句代码,可以通过plist创建一个sprite,简单分析下过程。
首先是通过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,加入到缓存。
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); }