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

接上一章《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进行贴图。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值