您的位置:首页 > 移动开发 > Cocos引擎

Cocos2d-x源码解析(1)——地图模块(2)

2014-06-19 14:40 357 查看
接上一章《Cocos2d-x源码解析(1)——地图模块(1)

首先TMX文件本身就是XML格式,我们可以随手做一个来分析TM自身的结构。

<?xml version="1.0" encoding="UTF-8"?>
<map version="1.0" orientation="orthogonal" width="100" height="100" tilewidth="32" tileheight="32">
<tileset firstgid="1" name="210201333565" tilewidth="32" tileheight="32">
<image source="D:/project/games/cocos2d-x-2.2.2/cocos2d-x-2.2.2/template/multi-platform-cpp/Resources/210201333565.png" width="256" height="256"/>
</tileset>
<layer name="块层 1" width="100" height="100">
<data encoding="base64" compression="zlib">
eJztwwEJAAAMBKEL8P3zDpZDwVVTVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVX/AcA31NA=
</data>
</layer>
</map>


我们可以发现,大部分的标签和属性都在每个节点的开始节点(</xxx>是结束节点)

那么我们就可以去看看 代码

void CCTMXMapInfo::startElement(void *ctx, const char *name, const char **atts)
{
CC_UNUSED_PARAM(ctx);
CCTMXMapInfo *pTMXMapInfo = this;
std::string elementName = (char*)name;
std::map<std::string, std::string> *attributeDict = new std::map<std::string, std::string>();
if (atts && atts[0])
{
for(int i = 0; atts[i]; i += 2)
{
std::string key = (char*)atts[i];
std::string value = (char*)atts[i+1];
attributeDict->insert(pair<std::string, std::string>(key, value));
}
}
if (elementName == "map")
{


我们发现cocos将xml的属性预处理到一个Map中,然后根据不同的标签名来做对应的处理。

那么我们拿layer进行举例

else if (elementName == "layer")
{
CCTMXLayerInfo *layer = new CCTMXLayerInfo();
layer->m_sName = valueForKey("name", attributeDict);

CCSize s;
s.width = (float)atof(valueForKey("width", attributeDict));
s.height = (float)atof(valueForKey("height", attributeDict));
layer->m_tLayerSize = s;

std::string visible = valueForKey("visible", attributeDict);
layer->m_bVisible = !(visible == "0");

std::string opacity = valueForKey("opacity", attributeDict);
if( opacity != "" )
{
layer->m_cOpacity = (unsigned char)(255 * atof(opacity.c_str()));
}
else
{
layer->m_cOpacity = 255;
}

float x = (float)atof(valueForKey("x", attributeDict));
float y = (float)atof(valueForKey("y", attributeDict));
layer->m_tOffset = ccp(x,y);

pTMXMapInfo->getLayers()->addObject(layer);
layer->release();

// The parent element is now "layer"
pTMXMapInfo->setParentElement(TMXPropertyLayer);

}


我们发现他将layer的信息都装进了CCTMXLayerInfo,这个类中,因此我们可以知道CCTMXLayerInfo是存储图层信息,CCTMXTilesetInfo是存储瓦片信息,CCTMXMapInfo是存储地图级别的信息。

另外,我们还注意到 pTMXMapInfo->setParentElement(TMXPropertyLayer);这句,cocos通过这样的方式来告诉下一次找到元素时,他的父节点是谁。

但是,就有一个问题,就是这些信息cocos都将他存储到CCArray中,如何能找到每个元素对应的瓦片信息呢。我们在endElement(void *ctx, const char *name)函数中找到了答案:

if(elementName == "data" && pTMXMapInfo->getLayerAttribs()&TMXLayerAttribBase64)
{
pTMXMapInfo->setStoringCharacters(false);

CCTMXLayerInfo* layer = (CCTMXLayerInfo*)pTMXMapInfo->getLayers()->lastObject();

std::string currentString = pTMXMapInfo->getCurrentString();
unsigned char *buffer;
len = base64Decode((unsigned char*)currentString.c_str(), (unsigned int)currentString.length(), &buffer);
if( ! buffer )
{
CCLOG("cocos2d: TiledMap: decode data error");
return;
}

if( pTMXMapInfo->getLayerAttribs() & (TMXLayerAttribGzip | TMXLayerAttribZlib) )
{
unsigned char *deflated;
CCSize s = layer->m_tLayerSize;
// int sizeHint = s.width * s.height * sizeof(uint32_t);
int sizeHint = (int)(s.width * s.height * sizeof(unsigned int));

int inflatedLen = ZipUtils::ccInflateMemoryWithHint(buffer, len, &deflated, sizeHint);
CCAssert(inflatedLen == sizeHint, "");

inflatedLen = (size_t)&inflatedLen; // XXX: to avoid warnings in compiler

delete [] buffer;
buffer = NULL;

if( ! deflated )
{
CCLOG("cocos2d: TiledMap: inflate data error");
return;
}

layer->m_pTiles = (unsigned int*) deflated;
}
else
{
layer->m_pTiles = (unsigned int*) buffer;
}

pTMXMapInfo->setCurrentString("");

}


在地图生成的时候,就已经定义好了这个数值,因此在生成cclayer的时候快速地定位到哪个tile进行贴图。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: