将plist中的单图提取出来

转载自:http://www.cocoachina.com/bbs/read.php?tid=188226

使用TexturePacker可以将若干小图,合成一张大图, 

生成的.png和.plist文件可以让cocos2dx解析。 

cocos2dx可以将这些小图从大图中“取出”。 

如果反过来呢? 

能否将这张大图分解出若干小图呢? 

自然也是可以的。 

使用TexturePacker编辑时,记得要保存.tps文件,也要保存好原来的单图,因为有可以会遇到之后要修改其中的某个单图的情况。 

两年前,我遇到一个项目,这个项目最恐怖的地方就是, 

美术和程序都找不到大图中的小图的原文件了。 

因为不断修改,整个项目可以用“混乱”二字来形容,谁遇到过一个项目,程序和美工都找不到这个项目原来图片的情况? 

而在这种混乱的情况下,竟然还要修改其中的一些单图。 

此时,急需一个工具可以将那些小图从合成的大图中分解出来。 

面临的难题就是,如何使用.plist和.png文件将这些小图分解出来。 

既然cocos2dx可以通过.plist和.png分解出小图, 

那么,直接使用cocos2dx来当成这个分解工具不就可以了吗? 

源代码引用 开始 


void CCSpriteFrameCache::addSpriteFramesWithFile(const char *pszPlist) 

CCAssert(pszPlist, "plist filename should not be NULL"); 

if (m_pLoadedFileNames->find(pszPlist) == m_pLoadedFileNames->end()) 

std::string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszPlist); 
CCDictionary *dict = CCDictionary::createWithContentsOfFileThreadSafe(fullPath.c_str()); 

string texturePath(""); 

CCDictionary* metadataDict = (CCDictionary*)dict->objectForKey("metadata"); 
if (metadataDict) 

// try to read texture file name from meta data 
texturePath = metadataDict->valueForKey("textureFileName")->getCString(); 


if (! texturePath.empty()) 

// build texture path relative to plist file 
texturePath = CCFileUtils::sharedFileUtils()->fullPathFromRelativeFile(texturePath.c_str(), pszPlist); 

else 

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

addSpriteFramesWithDictionary(dict, pTexture); 
m_pLoadedFileNames->insert(pszPlist); 

else 

CCLOG("cocos2d: CCSpriteFrameCache: Couldn't load texture"); 


dict->release(); 




源代码引用 结束 


重点在于这条语句 addSpriteFramesWithDictionary(dict, pTexture); 

将解析后的.plist信息进一步处理。 

源代码引用 开始 


void CCSpriteFrameCache::addSpriteFramesWithDictionary(CCDictionary* dictionary, CCTexture2D *pobTexture) 

/* 
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+ 
*/ 

CCDictionary *metadataDict = (CCDictionary*)dictionary->objectForKey("metadata"); 
CCDictionary *framesDict = (CCDictionary*)dictionary->objectForKey("frames"); 
int format = 0; 

// get the format 
if(metadataDict != NULL) 

format = metadataDict->valueForKey("format")->intValue(); 


// check the format 
CCAssert(format >=0 && format <= 3, "format is not supported for CCSpriteFrameCache addSpriteFramesWithDictionary:textureFilename:"); 

CCDictElement* pElement = NULL; 
CCDICT_FOREACH(framesDict, pElement) 

CCDictionary* frameDict = (CCDictionary*)pElement->getObject(); 
std::string spriteFrameName = pElement->getStrKey(); 
CCSpriteFrame* spriteFrame = (CCSpriteFrame*)m_pSpriteFrames->objectForKey(spriteFrameName); 
if (spriteFrame) 

continue; 


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(); 
spriteFrame->initWithTexture(pobTexture, 
CCRectMake(x, y, w, h), 
false, 
CCPointMake(ox, oy), 
CCSizeMake((float)ow, (float)oh) 
); 

else if(format == 1 || format == 2) 

CCRect frame = CCRectFromString(frameDict->valueForKey("frame")->getCString()); 
bool rotated = false; 

// rotation 
if (format == 2) 

rotated = frameDict->valueForKey("rotated")->boolValue(); 


CCPoint offset = CCPointFromString(frameDict->valueForKey("offset")->getCString()); 
CCSize sourceSize = CCSizeFromString(frameDict->valueForKey("sourceSize")->getCString()); 

// create frame 
spriteFrame = new CCSpriteFrame(); 
spriteFrame->initWithTexture(pobTexture, 
frame, 
rotated, 
offset, 
sourceSize 
); 

else if (format == 3) 

// get values 
CCSize spriteSize = CCSizeFromString(frameDict->valueForKey("spriteSize")->getCString()); 
CCPoint spriteOffset = CCPointFromString(frameDict->valueForKey("spriteOffset")->getCString()); 
CCSize spriteSourceSize = CCSizeFromString(frameDict->valueForKey("spriteSourceSize")->getCString()); 
CCRect textureRect = CCRectFromString(frameDict->valueForKey("textureRect")->getCString()); 
bool textureRotated = frameDict->valueForKey("textureRotated")->boolValue(); 

// get aliases 
CCArray* aliases = (CCArray*) (frameDict->objectForKey("aliases")); 
CCString * frameKey = new CCString(spriteFrameName); 

CCObject* pObj = NULL; 
CCARRAY_FOREACH(aliases, pObj) 

std::string oneAlias = ((CCString*)pObj)->getCString(); 
if (m_pSpriteFramesAliases->objectForKey(oneAlias.c_str())) 

CCLOGWARN("cocos2d: WARNING: an alias with name %s already exists", oneAlias.c_str()); 


m_pSpriteFramesAliases->setObject(frameKey, oneAlias.c_str()); 

frameKey->release(); 
// create frame 
spriteFrame = new CCSpriteFrame(); 
spriteFrame->initWithTexture(pobTexture, 
CCRectMake(textureRect.origin.x, textureRect.origin.y, spriteSize.width, spriteSize.height), 
textureRotated, 
spriteOffset, 
spriteSourceSize); 


// add sprite frame 
m_pSpriteFrames->setObject(spriteFrame, spriteFrameName); 
spriteFrame->release(); 



源代码引用 结束 



现在,通过 std::string spriteFrameName = pElement->getStrKey();, 

知道了这张单图的名字, 

也获取了这张单图的 CCSpriteFrame , 

通过之前那篇文章提到的方法, 

static CCRenderTexture* getRenderTexture(int widthP,int heightP,CCNode* nodeP,float node_xP,float node_yP); 
// 
CCRenderTexture* JarodGameTools:: getRenderTexture(int widthP,int heightP,CCNode* nodeP,float node_xP,float node_yP) 

CCRenderTexture *rt = CCRenderTexture::create(widthP, heightP); 
// 
rt->begin(); 
nodeP->setPosition(node_xP,node_yP); 
nodeP->visit(); 
rt->end(); 
// 
return rt; 


static bool createPng(const char* pngName,CCRenderTexture* textureP); 
// 

bool JarodGameTools:: createPng(const char* pngName,CCRenderTexture* textureP) 

CCImage* image = textureP->newCCImage(); 


return image->saveToFile(pngName,false); 


直接就可以将读入的所有.plist文件分解成原来的小图了。 

现在,我不再使用这种方式了,原因是, 

我选择使用保存单图和.tps的方式。 


现在,给出一个 自己测试后运行正确的代码


        //--------------------------------------------------------------------------------------------------------------------------------------------
        CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("stageA.plist");
                                            //第一步,载入一个plist

        CCSpriteFrame* buttonBgFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName( "buttonBg.png" );
                                            //第二步,根据名称提取出 frame

        CCSize sizeTemp = buttonBgFrame->getOriginalSize();
                                            //第三步,获取单图的尺寸

        CCSprite* buttonBgSprite = CCSprite::createWithSpriteFrame(buttonBgFrame);
                                             //创建一个 sprite

        CCRenderTexture* testT = JarodGameTools::getRenderTexture(sizeTemp.width,sizeTemp.height,buttonBgSprite,sizeTemp.width/2,sizeTemp.height/2);
                                             //将这个sprite绘制在图片的几何中心点的位置,因为锚点默认是 (0.5,0.5 )

        JarodGameTools::createPng("testButtonBg.png",testT);
                                            //将这个图片取一个名字,然后提取出来。
        //----------------------------------------------------------------------------------------------------------------------------------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值