Problems with tiled maps

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.

@smitpatel88
As I mentioned before, here i developed an example showing the polylines problem:
TileMapTest-New.zip (411.0 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 RaceTrackMap64.tmx) 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…

But the position of the polyline is correct…
The problem is the polyline sizes…

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?

Here I also show the images.
As I mentioned before, I drew two polyline at the limits of the track and the curve.
Debugging with box2d, the green lines represent the polyline.
The position of them is correct, but the size not.

The car accelerates, and the curve in the first image (draw) is seen in the fourth image (box2d draw), with the car out of the map. However, on the map the polyline is drawn correctly. It’s a polyline size problem…

Map config:

Captura

From screens above looks either you need to scale box2d to fit the image or scale the image to fit box2d. It might be easier to scale the image.

Just fyi I never used tile maps before… I rolled my own so maybe I am not the best person.

How to prevent players from moving through the tiledmap layer,help me

If you see my code, i’m not scaling the tiled map

tileMap = new TMXTiledMap;
tileMap->initWithTMXFile("RaceTrackMap64.tmx");
tileMap->setPosition(Vec2(origin.x, origin.y));
addChild(tileMap, 0);

But if I had to scale it to solve this, I would not know with what criteria to do it.
Anyone … help… :sob:

Well… finally i discovered the problem.
I posted the solution in the official topic: Create Box2D bodies with TMX Objects layer! Cocos2d-x 3.0

The polyline and the polygon points were not using the content scale factor :pensive:
Thanks all!

The problem that i would like to solve now is about the scaling in the tiled map.
Thanks @stevetranby for your answer about this:

Does it bother you if we resume the discussion? :smiley:
Ok, as I understand, you would like to scale the map.
How? Do you’ve an Example? Remember: my map is bigger than the screen in 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?

I tried to scale the map but I am not solving the problem of multiple resolution / multiple devices. In other words, even though I am scaling the map, it looks different on iPhone than on Tablet, etc.
Tips / examples are welcome.

@smitpatel88 i invite you to join to this discussion as well :smiley:

I remember my point of view:

:thinking:

the tiled map editor + box2d + cocos2d-x V3.17 = DONT MIX??? is that what you’re saying?

I fixed my problem with box2d.
Don’t read old post, that was fixed :smiley:

Read my last post here, now i’m trying to find the best method for see well the tiled map in multiple devices / resolutions (should i use scale? or not? why?). Examples are welcome.

Sure, i want to, but was busy in so many things.

Normally we dont apply any scale to Maps or sprites based on different aspect ratio devices.
We make game for 1.77 aspect ratio device only with BG with bigger size, so on 1.5 & 2.0 aspect ratio device will have bigger width/height. So it wont stretch on those devices.
This is really big topic to explain in details. But once adapted this then its easy to code for all device.

Box2d works well only in a scale of 1 : 10000 where 1 is your smallest object and 10000 is your biggest object. The issue - rather: this ratio - comes from floating point math being more unprecise with huge differences in two floating point values. So by dont allowing huge differences, the math behind it will work precisely.

Your racetrack seems to be alot bigger than the cars, so just split the racetrack in pieces.

This will not fix your issue but is the root of your issue I think.

Because box2d has this 1:10000 ratio (or so, just google it) and your game might actually be alot bigger in pixels, you will scale the box2d objects by a factor down to make them fit this 1:10000 ratio.

Of course it will be nice if the box2d world exactly matches the racetrack image. It doesnt have to tho.

My solution (worked for me): Create the box2d world with a factor so that everything is between 1 and 10000.
Keep this factor in mind because each time you step your world the car will move some amount.
This amount is very small compared to the actual pixel distance, so you will multiply the box2d distance (or the new position) by 1/factor (or just divide it by the factor). This will give the car the correct position (in pixels) on the racetrack.

This might lead to a problem: jumping
While the distance in the box2d world might be very small, the pixel distance might be very large (as you multiply it by a rather big value) this will lead to your car jumping small amounts in the game.
What you want to do then:
-Try to minimize the scale factor
-Interpolate between the old and the new position
-Not only scale the box2d world down, but also the game by the same factor (the game will look very small then, but you simply can zoom the camera by the factor and everything will be the equaly sized, but movement will look smoother)

1 Like

Nice! I think we think the same.
That was my idea: DO NOT scale the Map and add a fullscreen background in x, y to cover black spaces (for example, if the player moves out of the map).

The main advantage: the map doesn’t stretch on any device.
The main disadvantage: the map will not look exactly the same on an iPhone as on a Tablet (for example, the background can be displayed more on the tablet than on the iPhone). But this is not so bad. :yum: