Tileson - A Tiled json parser for Modern C++

Hello!
I have no idea if this fits in here, but I’m posting it anyways.
I’ve created a Tiled json parser for Modern C++, and want to share it here in case it would be useful for someone. Any feedback is welcome! Also: If you find a bug, you are very welcome to report it.
If you have any suggestions on how to improve the library, I encourage you to share them :slight_smile:

You can find the parser here:

If this is inappropriate for this forum: Feel free to remove the post.

Sincerelly, Robin.

2 Likes

That is great that you provide another option for C++ developers! I’ve added your library here:

https://doc.mapeditor.org/en/latest/reference/support-for-tmx-maps/#id1

And to this new page, which is still a WIP and not linked from anywhere:

With the above page, I tried to make it easier to maintain and make the information a bit more structured. But I really don’t like working on websites…

Thank you very much for adding my library to the list! :slight_smile:
Hope people find it useful!

As it is created to not only be a parser, but to have functionality to make it easier to use the data parsed in a project, I am very open for suggestions to improve the library, as well as keeping it updated with Tiled itself :slight_smile:

1 Like

Hello SSBM,
Thanks for sharing your work.

Sorry to pollute your topic but I got a trivial question.
Is there any way I can get a drawable object?
Could you eventually explain how?

(I’m a total newbie in Tiled and parsing (by the way the translation of “parser” in french is so foggy I’m not even sure I can use a parser in my project).

(If you have any tutorial in mind I can read or watch, it can be great too)

@RacheProu:
This is absolutely on topic, so no pollution at all. I do in fact encourage anyone to ask questions in cases where things are a little unclear :slight_smile:

In short words, “parser” means “reader”. In other words, Tileson reads the data from Tiled maps in json format. You can get a tiled map in .json format by simply exporting it to json, and you will be able to parse/read the data from the map without any problem using C++ with ha modern compiler.

I just created another example in an attempt to help you using data to create drawable objects. Please go ahead and ask me further if you got more questions :slight_smile:

This is a quickly written example just to showcase how you can use some of the data:

    tson::Tileson t;
    tson::Map map = t.parse("../../content/test-maps/ultimate_test.json");

    if(map.getStatus() == tson::Map::ParseStatus::OK)
    {
        //Gets the layer called "Object Layer" from the "ultimate_demo.json map
        tson::Layer *objectLayer = map.getLayer("Object Layer"); //This is an Object Layer

        //Example from an Object Layer.
        if(objectLayer->getType() == tson::Layer::Type::ObjectGroup)
        {
            tson::Object *goomba = objectLayer->firstObj("goomba"); //Gets the first object with this name. This can be any object.

            //If you want to just go through every existing object in the layer:
            for(auto &obj : objectLayer->getObjects())
            {
                tson::Vector2i position = obj.getPosition();
                tson::Vector2i size = obj.getSize();
                tson::Object::Type objType = obj.getObjectType();

                //You may want to check the object type to make sure you use the data right.
            }

            tson::Object::Type objType = goomba->getObjectType();

            /*!
             * tson::Object::Type is defined like this.
             * They are automatically detected based on what kind of object you have created
             * enum class Type : uint8_t
                {
                    Undefined = 0,
                    Object = 1,
                    Ellipse = 2, //<-- Circle
                    Rectangle = 3,
                    Point = 4,
                    Polygon = 5,
                    Polyline = 6,
                    Text = 7,
                    Template = 8
                };
             */

            if (objType == tson::Object::Type::Rectangle)
            {
                tson::Vector2i size = goomba->getSize();
                tson::Vector2i position = goomba->getPosition();

                //If you have set a custom property, you can also get this
                int hp = goomba->get<int>("hp");

                //Using size and position you can can create a Rectangle object by your library of choice.
                //An example if you were about to use SFML for drawing:
                //sf::RectangleShape rect;
                //rect.setSize(sf::Vector2f(size.x, size.y));
                //rect.setPosition(sf::Vector2f(position.x, position.y));
            }
            else if (objType == tson::Object::Type::Polygon)
            {
                for(auto const &poly : goomba->getPolygons())
                {
                    //Set a point on a shape taking polygons
                }
                tson::Vector2i position = goomba->getPosition();
            }
            else if (objType == tson::Object::Type::Polyline)
            {
                std::vector<tson::Vector2i> polys = goomba->getPolylines();
                for(auto const &poly : goomba->getPolylines())
                {

                }
                tson::Vector2i position = goomba->getPosition();
            }
        }

        tson::Layer *tileLayer = map.getLayer("Main Layer"); //This is a Tile Layer.
        tson::Tileset *tileset = map.getTileset("demo-tileset"); //You will also need the tileset used
                                                                       //by the tile map to make sense of everything

        int firstId = tileset->getFirstgid(); //First tile id of the tileset
        int columns = tileset->getColumns(); //For the demo map it is 8.
        int lastId = (tileset->getFirstgid() + tileset->getTileCount()) - 1;

        //Example from a Tile Layer
        //I know for a fact that this is a Tile Layer, but you can check it this way to be sure.
        if(tileLayer->getType() == tson::Layer::Type::TileLayer)
        {
            //pos = position in tile units
            for(auto &[pos, tile] : tileLayer->getTileData()) //Loops through absolutely all existing tiles
            {
                fs::path imagePath;
                std::string pathStr;
                //With this, I know that it's related to the tileset above (though I only have one tileset)
                if(tile->getId() >= firstId && tile->getId() <= lastId)
                {
                    imagePath = tileset->getImagePath();
                    pathStr = imagePath.u8string();
                }

                //Get position in pixel units
                tson::Vector2i position = {std::get<0>(pos) * map.getTileSize().x,std::get<1>(pos) * map.getTileSize().y};
                int tileId = tile->getId();
                //The ID can be used to calculate offset on its related tileset image.
                int offsetX = (tileId % columns) * map.getTileSize().x;
                int offsetY = (tileId / 8) * map.getTileSize().y;

                //Now you can use your library of choice to load the image (like SFML), then set the offset
                //to get the right image representation of the tile.
            }
        }
    }

Edit:
To actually be able to draw any object you will need a library that is able to draw them. Tileson just gives you the data from Tiled to be able to know how to create them.

@SSBMTonberry
Thanks for this more precise than I could imagine.

It’s reassuring to see (at least I understood the base concept :sweat_smile:)

I’m very grateful for this!
I understand all the parts

I promise I will. :grinning:

Thanks!