Problems with tiled maps

Look at this tutorial:https://youtu.be/AmLDslUdepo

I used it to learn libgdx years ago. You will understand it (it is java tho).
Maybe it will help you.

Yep, probably default body is static. Thanks for open my eyes :slight_smile:
Yes, i will add the line. The code is better with all lines… without assuming anything…

Yep, i’m sure that i’m wrong. But how to fix it? I would like to the car collides with the invisible circle. I tried everything with category and maskBits… :thinking:

https://www.iforce2d.net/b2dtut/top-down-car

Ok, i discovered the problem.
I’m using b->SetTransform in update() and that’s the problem because SetTransform sets new position to a body, and even though this one was colliding, i was imposing a new position over and over again.

So, I changed it to b->SetLinearVelocity and now it works.
Summarizing: TiledBodyCreator works perfect, you only need set dynamic to all bodys that you want to collide and not use SetTransform in update, for detect collisions correctly.

Ok, Point 1 solved.

About the Point 2:

I understood how cocos2d::Follow works. As I tested, by default, Follow follows to a Node/Sprite that you sends by parameter around the map. But the most important is: the Node/Sprite always is in the center of the screen. To make it possible, Follow moves the position of the tiled map (remember that in my case, the car is the map’s child).

That’s the reason because the Tiled Map is in another position when i use Follow. Because the car wasn’t in the center of the map, then Follow moves the car to the center of the screen and the map is moved. This is what I was not understanding. But now i understand how it works, and i will use it :

tiledMap->runAction(Follow::create(tiledMap->getChildByName("myCar")));

About the Point 3:

About this point, i’m continue with a doubt about the scaling…
The question is: should I scale the tiled map, or not?

We can separate the question in two:
Why scale? Because I want to see the map in the same way in iPhone as in Tablet, etc. For example, if my map has 32x32, on the screen I always want to see 10x10, be it an iPhone, a Tablet, etc. Is this possible?

Why not scale? Because my map will be very large and will always be bigger than all my iphone or tablet screen. Also, if in some movement I “leave” the map, instead of seeing black spaces I can add a background with an image for cover always the screen.

This last option is the one that convinces me most. What you think? @stevetranby
I ask the same question to @smitpatel88. As I know, you’ve experience with tiled maps, you opinion is very important for me :slight_smile:

Thanks.

  1. Nice, glad Box2D has an easy to use LinearVelocity so you don’t have to deal with impulses/forces/mass/etc.
  2. Personally I’d write my own “camera” system for any game to get full control, but if it’s working for you now, great, especially if just to get the game up and playing. Also, you can possibly wrap Follow with the various cocos2d’s various Ease actions to get it interpolating.
  3. Scaling is the most common case for games I think, so you see mostly the same thing on any device, but in the few games I’ve worked (maps/worlds larger than screen in both X and Y axes) on it was decided to see more of the game world or map on larger devices by having different default “base” zoom level. UI on the other hand is scaled to mostly have similar physical size.

Ok, as I understand, you would like to scale the map.
How? Do you’ve an Example? Remember: my map is larger than screen in both X, Y (in iPhone, Tablet, etc).
I thought about zoom. Do you’ve an example?
You would like to zoom and NOT scale the map?

Advices/examples are welcome.

If i want to “zoom” the tiled map, i could use setScale:
tiledMap->setScale(1.5);

and every time I move the car, i could call moveWorld():

void GameManager::moveWorld() {
  cocos2d::TMXTiledMap *tiledMap = Game::getInstance()->getTiledMap();
  Sprite *myCar = (Sprite*)tiledMap->getChildByName("myCar");

  auto ws = myCar->getParent()->convertToWorldSpace(myCar->;getPosition());
  auto ns = tiledMap->getParent()->convertToNodeSpace(ws);
  tiledMap->setPosition(tiledMap->getPosition() - ns + Director::getInstance()->getWinSize() / 2);
}

moveWorld simulates Follow’s behavior (thanks @grimfate :slight_smile:) . The problem with using Follow is that it doesn’t work when I zoom the tiled map (it doesn’t follow the car correctly).
This could be a way to zoom the map…

But i’m not fixing multi-resolution / multi-devices problem. In other words, despite of i’m scaling the map, it has different views in iPhone than in Tablet, etc…
Examples are welcome :smiley:

Sorry, i forgot test it.
It doesn’t work for me.

My box2d debug class works, but i don’t see the bodys/fixtures in the tiled map. I think it’s because the bodys/fixtures are drawing behind the sprites and tiled map. But i don’t know how to fix it…

But the class works because i tested it without adding tiled map / backgrounds and it works.

To check the Debug stuff over visible tile map background here are my classes/resources for the test project.
TileMapTest-Archive-Steve.zip (800.3 KB)

If you search for XTLayer you should find a few discussions on touch gestures for pinch/move zoom/pan.

There are probably plenty of examples on this board and elsewhere, but a lot of this is going to require both trial+error and learning. Read the Follow class code, understand how it works, figure out where to apply some scale factor mult/div to factor in maps scale, etc, etc, etc.

1 Like

You saved my day !!
Your Box2d debug class works in my tiled map.
My class didn’t work.

Now I see all the drawings made by TiledBodyCreator :smiley:
However… hmmm… did you try to draw a Polyline in the map?
Is rare. The drawing is disproportionate. It is bigger than the drawing on the map. :thinking:
Sounds like a bug in TiledBodyCreator? :thinking:

The circle and rectangle sizes are correct. But when you draw a Polygon or a Polyline, the sizes are disproportionate.

Here i developed an example showing the polylines problem:

TileMapTest-New.zip (409.9 KB)

(add cocos2d and proj.ios_mac folders)
And in resources, plz add all the files that are in Resources folder (i created a new tiled map for test).

As you can see, the object “Collision” (in the tiled map) has 2 polylines (called “raceTrackLimitLeft” and “raceTrackLimitRight”). The objective is to establish the limit on the race track.

If you run the game (debug box2d is on), these polylines are much longer than the tiled map. The polylines are well drawn (I recommend you wait a few seconds, so that the car reaches the curve). It has the correct forms and is well located. But the size is incorrect… :thinking:

This is the method in TiledBodyCreator.cpp for draw polylines:

FixtureDef* TiledBodyCreator::createPolyline(ValueMap object)
{
    ValueVector pointsVector = object["polylinePoints"].asValueVector();
    auto position = Point(object["x"].asFloat() / PTMRATIO, object["y"].asFloat() / PTMRATIO);
    
    b2ChainShape *polylineshape = new b2ChainShape();
    
    int verticesCapacity=32;
    b2Vec2* vertices = (b2Vec2*)calloc(verticesCapacity, sizeof(b2Vec2));
    
    int vindex = 0;
    
    auto fix = new FixtureDef();
    
    for(Value point : pointsVector) {
        if(vindex>=verticesCapacity)
        {
            verticesCapacity+=32;
            vertices = (b2Vec2*)realloc(vertices, verticesCapacity*sizeof(b2Vec2));
        }
        vertices[vindex].x = (point.asValueMap()["x"].asFloat() / PTMRATIO + position.x);
        vertices[vindex].y = (-point.asValueMap()["y"].asFloat() / PTMRATIO + position.y);
        vindex++;
    }
    
    polylineshape->CreateChain(vertices, vindex);
    fix->fixture.shape = polylineshape;
    
    return fix;
}

The polylines are much longer than the tiled map because of this lines:

    vertices[vindex].x = (point.asValueMap()["x"].asFloat() / PTMRATIO + position.x);
    vertices[vindex].y = (-point.asValueMap()["y"].asFloat() / PTMRATIO + position.y);

But… what’s the error?
I tried editing PTMRatio from 32 to 64 or 128 and the polylines are more small…
But how to find exactly the values for match exactly with the tiled map sizes???
Might be just a small math issue. :smile:

hmm… I pretty much do the same. Here’s the code below.

 b2ChainShape chainShape;
        chainShape.CreateChain(vertices, count);
        chainShape.m_hasPrevVertex = fixtureValue1["chain"].get("hasPrevVertex",false).asBool();
        chainShape.m_hasNextVertex = fixtureValue1["chain"].get("hasNextVertex",false).asBool();
        fixtureDef.shape = &chainShape;
        body->CreateFixture(&fixtureDef);
b2Body* GameLayer::createChainFromJson(std::vector<Json::Value>& values, b2Vec2 startPos) {
    b2BodyDef bd;
    bd.position.Set(startPos.x, startPos.y);
    auto body = _world->CreateBody(&bd);
    
    int numVertices = 0;
    
    for (int i = 0; i < (int)values.size(); i++) {
        auto fixtureValue = values[i];
        numVertices += fixtureValue["chain"]["vertices"]["x"].size();
    }

    numVertices = numVertices - ((int)values.size() - 1);    
    float offsetX = 0;
    for (int i = 0; i < (int)values.size(); i++) {
        auto fixtureValue1 = values[i];
        auto count = fixtureValue1["chain"]["vertices"]["x"].size();
        auto vertices = new b2Vec2[count];
        
        for (int j = 0; j < count; j++) {
            auto v = b2dJson::jsonToVec("vertices", fixtureValue1["chain"], j);
            v.x = offsetX + v.x;
            vertices[j] = v;
        }
        
        auto last = vertices[count - 1];
        auto first = vertices[0];
        auto dist = last.x - first.x;
        
        offsetX = offsetX + dist;
        
        b2FixtureDef fixtureDef;
        
        fixtureDef.restitution = jsonToFloat("restitution", fixtureValue1);
        fixtureDef.friction = jsonToFloat("friction", fixtureValue1);
        fixtureDef.density = jsonToFloat("density", fixtureValue1);
        fixtureDef.isSensor = fixtureValue1.get("sensor",false).asBool();
        
        b2ChainShape chainShape;
        chainShape.CreateChain(vertices, count);
        chainShape.m_hasPrevVertex = fixtureValue1["chain"].get("hasPrevVertex",false).asBool();
        chainShape.m_hasNextVertex = fixtureValue1["chain"].get("hasNextVertex",false).asBool();
        fixtureDef.shape = &chainShape;
        body->CreateFixture(&fixtureDef);
        delete[] vertices;
    }   
    return body;
}

createChainFromJson ? I don’t have a json file :thinking: I only have a tmx (plz download the last example that i uploaded). I would like to edit createPolyline

The json values are just bunch of x,y coords to create the b2ChainShape. I will try to check out your sample over the weekend.

The math above doesn’t look right to me.

Yes, I know that there are tools to automatically generate json files and create the shapes in box2d. But I do not use tools or json to generate the shapes. I do everything manually by code.

Yes, something is wrong. In that we agree :smiley:

Anyone can help? :frowning:

what issue you are facing right now?
Also i think you have to invert ‘Y’ position, as in Tiled 0,0 is at left-top corner and in cocos 0,0 is at bottom-left corner.
Try to add any one polyline only and see what x,y you are getting it.