Loading objects from TMX files

I’m trying to load objects that I’ve placed in my TMX map files. I need to get their type, and their position. And I also need to get properties from them (like sprite filenames, settings, etc). The CCTMXObjectGroup only has a method returning a CCArray*, but what is it filled with? Is it a bunch of CCDictionary objects? And if that’s it, what keys do I use to access the position, and the type?

Anyone?

Something like this:

    CCTMXObjectGroup *objectsGroup = m_Map->objectGroupNamed("Object Layer 1");
    CCAssert(objectsGroup != NULL, "'Objects' object group not found");

    CCMutableArray *m_pObjects;
    m_pObjects = objectsGroup->getObjects();

    float x, y, x2, y2;
    CCString *name, *type_name;
    ObjectItemInfo *obj;
    int itemNo, iVals[5], iLevel;

    if (m_pObjects && m_pObjects->count() > 0)
    {
        CCMutableArray::CCMutableArrayIterator it;

        for (it = m_pObjects->begin(); it != m_pObjects->end(); ++it)
        {
            name = (*it)->objectForKey(std::string("name"));
            type_name = (*it)->objectForKey(std::string("type"));
            x = (*it)->objectForKey("x")->toFloat();
            y = (*it)->objectForKey("y")->toFloat();
            x2 = x+(*it)->objectForKey("width")->toFloat();
            y2 = y+(*it)->objectForKey("height")->toFloat();

            memset( iVals, 0, sizeof(int)*5 );
            if( (*it)->objectForKey("i0") )
                iVals[0] = (*it)->objectForKey("i0")->toInt();
            if( (*it)->objectForKey("i1") )
                iVals[1] = (*it)->objectForKey("i1")->toInt();
            if( (*it)->objectForKey("i2") )
                iVals[2] = (*it)->objectForKey("i2")->toInt();
            if( (*it)->objectForKey("i3") )
                iVals[3] = (*it)->objectForKey("i3")->toInt();
            if( (*it)->objectForKey("i4") )
                iVals[4] = (*it)->objectForKey("i4")->toInt();

            iLevel=0;
            if( (*it)->objectForKey("level") )
                iLevel = (*it)->objectForKey("level")->toInt();


        }
    }

Thanks. I’ll try and see if I can get it working. I was trying valueForKey but it always returns an empty string. Is that an unsupported function?

I couldn’t say, I wrote that months ago, based on the Test sample project I think. It works though, that’s my code I use from my game Arrow Mania (http://www.arrowmania.com).

Note the values “i0”, “i1”, “level”, etc are values added to the object by me in the editor (Tiled http://www.mapeditor.org), the others “x”,“y”,“width”,“height” are the standard values for each object.

Nope. I’m still getting null strings. I tried using CCString* type = (CCString**)params->objectForKey; params is a CCDictionary** the weird thing is that when I try to use CCMutableArray instead I get errors. It says there’s no such class. I’m using the latest version of Cocos2D-x…

Try with this map file and my code, it should get the data from the object “089_jet_plane_1.png”

Files:
http://www.gmtdev.com/downloads/a_map.tmx

I’m using “cocos2d-1.0.1-x-0.11.0”. One thing I noticed about the later versions was that the TMX tile map code would cause errors when releasing maps (though they did load). Hence I stayed at the old version. I’ve not gone to v2 as I want to support iPhone 3G.

Thanks. I’ll try that when I get to the computer that has my code on it.

I tried. The CCMutableArray doesn’t seem to exist anymore. The map and tileset don’t make any difference either. Is there anyone who has used the latest version to do this?

I’ve even tried copying the code from the ortho object test and it won’t work. I attached my TMX file, maybe there actually IS something wrong with it?

I ended up just writing my own object loader with TinyXML and it works great now.

i have the same question too. the TinyXML can not get the child count .not work to me. anyone have better idea?

I just manually counted children. If anyone’s interested here’s my TinyXML code:
@
std::string fullPath = CCFileUtils::sharedFileUtils()>fullPathFromRelativePath);
unsigned char* pBuffer = NULL;
unsigned long bufferSize = 0;
pBuffer = CCFileUtils::sharedFileUtils
>getFileData, “r”, &bufferSize);
if
{
//Load data
///////////////////////////////////////////////////////////////////////////////////////////////////
tinyxml2::XMLDocument doc;
doc.ParsepBuffer);
tinyxml2::XMLElement* map = doc.FirstChildElement;
if
{
tinyxml2::XMLElement* objects = map~~>FirstChildElement;
if
{
tinyxml2::XMLElement* firstChild = objects~~>FirstChildElement();
if ( firstChild )
{
tinyxml2::XMLElement* nextChild = firstChild;
while ( nextChild != NULL )
{
std::string elementName = nextChild~~>Name;
if )
{
onEntityElement;
}
nextChild = nextChild~~>NextSiblingElement();
}
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
}
@

@
void MapLoader::onEntityElement(tinyxml2::XMLElement* object, cocos2d::CCLayer* scene)
{
//Position and type
float x = object~~>FloatAttribute;
float y = object~~>FloatAttribute(“y”);

float width = object~~>FloatAttribute;
float height = object~~>FloatAttribute(“height”);

//x = (x)m_map>getMapSize().width*32;
y = (y)+m_map>getMapSize().height*32;

CCPoint pos = ccp(x,y);

std::string type = object~~>Attribute;
//Attributes
std::vector params;
tinyxml2::XMLElement* props = object~~>FirstChildElement(“properties”);
if ( props )
{
tinyxml2::XMLElement* firstChild = props~~>FirstChildElement;
if
{
tinyxml2::XMLElement* nextChild = firstChild;
while
{
if ) == std::string )
{
SObjectParam param;
param.m_name = nextChild~~>Attribute(“name”);
param.m_value = nextChild~~>Attribute;
params.push_back;
}
nextChild = nextChild~~>NextSiblingElement();
}
}
}

//Create entity
GameObject* obj = GameObjectFactory::createObject(type, pos, params, width, height);
if ( obj )
{
m_map->addChild(obj);
}
}@

EDIT: Woops. That wasn’t the TinyXML code where I counted the children. But in my other code I just had a counter in the while(nextChild!=NULL) loops.

I’ve just been updating to V2 and the code as in my v1 sample above is now as below. It’s just a slightly modified version of the code found in the taken from the Tests sample.

    CCTMXTiledMap* map = (CCTMXTiledMap*) getChildByTag(kTagTileMap);
    CCTMXObjectGroup* group = map->objectGroupNamed("Object Layer 1");
    CCArray* objects = group->getObjects();

    CCDictionary* dict = NULL;
    CCObject* pObj = NULL;

    CCARRAY_FOREACH(objects, pObj)
    {
        dict = (CCDictionary*)pObj;

        if(!dict)
            break;

        const char* key = "x";
        x = ((CCString*)dict->objectForKey(key))->intValue();
        key = "y";
        y = ((CCString*)dict->objectForKey(key))->intValue();
        key = "width";
        x2 = x+((CCString*)dict->objectForKey(key))->intValue();
        key = "height";
        y2 = y+((CCString*)dict->objectForKey(key))->intValue();         

        printf( "x %i, y %i, x2 %i, y2 %i\n", x, y, x2, y2 );
    }

How did you run project with tinyxml on android? Is it work ?

I’ve been developing on windows.