Search code examples
c++cocos2d-xbox2dcocos2d-x-3.0tmx

Cocos2d/Box2d. How to generate a physics body from a tilemap .tmx?


I am new to game development.

What I'm trying to do is load the .tmx tilemap I've created from Tiled to my game as a physics body(ies), I'm using C++ and Boxd2. My tilemaps show only the tiles I want to be collideable, like the floor and some platforms.

It's important to note that i'm programming for windows and all documentation I found were about IOS or for an older version, some functions like b2BodyDef bodyDef doesn't seem to work.


Solution

  • I am currently doing what you are describing in my latest game, the only difference being that I use cocostudio to build everything in my game, including my maps. The reason I did this was so that I can have control over everything I needed, I use pre-defined naming conventions to indicate physical edges which I then read up and determine its dimensions and construct my edge bodies.

    High-Level overview

    Before continuing here are the assumptions I am making about your .tmx tilemap. You have unique identifiers for the objects you would like to create as a physical object (something in it's name that you can use to pull it out and inspect it).

    1. Read in the .tmx file and give it to your fileParser.
    2. Get all the "Nodes", "Sprites" that have your physical body identifier in it.
    3. Since you are using a tile map I'm assuming that all your collision areas wil be square.
    4. Give the list of nodes to your PhysicsBodyFactory and use the following code to construct the bodies you require.

    pseudo-ish code below

    auto tileNode = listOfNodes.at(nodeIndex);
    
    b2BodyDef tileBodyDef;
    tileBodyDef.type = b2_staticBody;
    tileBodyDef.position.Set(tileNode->getPositionX() / Pixel_To_Meter_Ratio,
                             tileNode->getPositionY()/ Pixel_To_Meter_Ratio);
    
    auto b2PolygonShape tileShape;
    tileShape.SetAsBox(tileNode->getBoundingBox().size.width / Pixel_To_Meter_Ratio,
                       tileNode->getBoundingBox().size.height / Pixel_To_Meter_Ratio);
    
    auto tileBody = physicsWorld->CreateBody(tileBodyDef);
    // This can be used later on when you want to have different reactions for different collisions.    
    tileBody->SetUserData("CollidableTile"); 
    

    This will create and place these object in your physics world, allowing other bodies in there to collide with it. If your player has its own body in the world, the basic collision will be handled for you.

    I am writing a blog post on using cocostudio as more than a UI tool, which will cover this exactly. I hope this helps, please let me know if this solution is what you are looking for.