Possible bug in TMXTiledMap::create() for csv based tmx files (extra blank tiles inserted)

I was working on a tile game with Coco2dx V4, loading a level using a tmx map from Tiled.exe v1.2.2 on Windows 10.

When I loaded and showed the level it had blank cells at the start of each “line” in the tilemap, shifting the subsequent tiles left. For a tile map like this

123
456
789

I got this displayed, where X is a blank black tile

X12
3X4
56X

I know I get a warning only v1 not v1.2.2 of Tiled is supported, but a web post in (I think) Chinese when translated seem to say it is not a problem and can be ignored.

It seemed like a strange bug not to have been found already, so I assumed a recent problem.
I had a look at the recent change log, and noticed TMXTiledMap() had support for CSV added.
I had a look in Tiled.tmx, and yes the map is saved as a block of CSV

1,2,3,
4,5,6,
7,8,9

I then noticed that Tiled would let me save map as xml. When I did this it worked and displayed correctly.

It seems the new Cocos2dx v4 code for handling tmx files using CSV format has a bug.

Steps to reproduce

  1. Make a tmx map in Tiled v1.2.2 and save using the CSV option (default I think)

  2. Load with Coco2dx v4 using TMXTiledMap::create()

  3. Show the tiled map

  4. BUG see a diagonal line of black tiles, and some of last tiles missing

Workaround:
Save the map in XML not CSV in Tiled.exe v1.2.2

Suggestions:
This seems like an off by one loop error in code, adding a blank tile. Possibly from interpretation of CSV data. This may be related to line termination in CSV block in tmx file being mishandled, possible a \r \n or \r\n mismatch where Windows by default use \r\n but other systems like linux like just \n.
(if this was the case it may explain how this was missed in testing if testing was on a *nix machine)

I have not tried it, but editing the csv based tmx to delete or change the line breaks from \r\n to \n may also work.

I can ask engineering to have a look.

Thanks slackmoehrle :slight_smile:

If you don’t want to bother fixing or worrying on your end, just export as .xml and keep working.


otherwise:

I’d first try Tiled 1.7.2 and if that doesn’t load your map try one of the older ones, 1.5.x, 1.4.x, 1.3.x, 1.2.5, to confirm it’s not a tiled bug.

(A map you created in 1.2.2 should open just fine even in the latest 1.7.2, but if not you can try an older version that’s more recent than 1.2.2 - you just open and re-export.)

If you still have an issue you should post your full exported .csv file and ideally the associated tileset images, but even if not we can test the .csv out by itself with a dummy tile set. (or if you want to confirm with a test tilemap you can create a small map with a dummy tileset yourself in case you can’t share your full map)

After thinking about this for a little bit it is also possible that everyone has just learned to export to XML as maybe that’s the format that has the most supported features? I’d hope the CSV version is meant to be the same feature support, but with Cocos2D everything is sort of updated based on someone’s needs/wants.

Thanks @stevetranby
I should try Tiled 1.7.2, although the file from 1.2.2 looks ok by visual inspection
Example:

<?xml version="1.0" encoding="UTF-8"?>
<map version="1.2" tiledversion="1.2.2" orientation="orthogonal" renderorder="right-down" width="3" height="3" tilewidth="32" tileheight="32" infinite="0" nextlayerid="2" nextobjectid="1">
 <tileset firstgid="1" name="medieval_castle_platform_tileset_01_32x32" tilewidth="32" tileheight="32" spacing="2" margin="1" tilecount="36" columns="9">
  <image source="medieval_castle_platform_tileset_01_32x32.png" width="306" height="136"/>
 </tileset>
 <layer id="1" name="Tile Layer 1" width="3" height="3">
  <data encoding="csv">
1,2,3,
4,5,6,
7,8,9
</data>
 </layer>
</map>

I confirmed the line termination of CSV part is 0x0D0A, or \r\n in case it matters.
I tried deleting the \r\n from file CSV data bit and reloading

<layer id="1" name="Tile Layer 1" width="3" height="3">
  <data encoding="csv">1,2,3,4,5,6,7,8,9</data>
 </layer>

and this fixed the problem!
(note the lack of \r\n between “>” and “1”)

So I think we can confirm it is a Cocos2d bug in how it handles \r\n in the block.

2 Likes

or worrying on your end, just export as .xml and keep working

Well that is what I’ve been doing for now. :slight_smile:
If it really bugs me I may have a look at code in debug and see if I can fix it since my suspicion on what problem was (\r\n) seems confirmed above.

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

If \r\n is the bug, should be an easy fix i’ll take a look tonight, just for completeness sake.

2 Likes

So, I’m never 100% certain how windows C libraries behave if the “\n” delimiter does NOT parse a “\r\n” the same as “\n” then it looks like that is the bug and issue. So, what you probably end up with is a tiled map that has the tiles:

1 2 3 \r 4 5 6 \r 7 8 9

which probably translates to a 3x3 tiled map of:

1 2 3
\r 4 5
6 \r 7

where 8 and 9 tiles aren’t even displayed?

Again, while I test on windows, and have done a bunch of dev in the past, and working with developers who develop on windows I’m fully aware of the annoying behavior of newlines between platforms, ugh! :smiley:

I’ll do an actual test sometime over the next week or two when I find some time to set aside, but either the newline delimiter needs to be done either in some platform-independent c++ standard library way, or just need to first convert all “\n\r” into “\n”, or less efficiently only parse the first N columns based on the maps’ width. Hopefully the first idea works and is easy enough to find in cppreference or wherever.

It’s likely very few people use Tiled on windows, and for those few they probably just resorted to using the base64 encoding (optionally compressed) - which is actually probably likely since cocos2d did start from python, which is highly platform-independent and probably didn’t have this bug, and then was mostly used with iPhone development almost certainly by developers using MacOS …

Anyway, remind me if I haven’t replied in a week or two (unless you go in an fix it yourself :D)

1 Like

The related code in the engine’s TMXMapInfo class:

while(getline(filestr, sRow, '\n')) {
    string sGID;
    istringstream rowstr(sRow);
    while (getline(rowstr, sGID, ',')) {
        gidTokens.push_back(sGID);
    }
}
1 Like