I am attempting to load a 2d tiled map (.tmx + .tms files) generated from Tiled Map Editor into Cocos2d-x version 4. I am building the project using Visual Studios 2022 -- Win32
I'm trying to make the scene as simple as possible, and the tiled map to be as simple as possible to just get it to work, -- to no avail.
Below is the full code of the Scene I'm trying to load:
#include "cocos2d.h"
USING_NS_CC;
class TileTestScene : public Scene
{
public:
virtual bool init()
{
auto map = TMXTiledMap::create("tmx/Trees.tmx");
layer = map->getLayer("Trees");
auto mapSize = layer->getLayerSize();
auto visibleSize = Director::getInstance()->getVisibleSize();
for (int i = 0; i < mapSize.width; ++i)
{
for (int j = 0; j < mapSize.height; ++j)
{
auto sprite = layer->getTileAt(Vec2(i, j));
if (!sprite)
{
}
}
}
this->addChild(map);
map->setPosition(visibleSize.width / 2.0f, visibleSize.height / 2.0f);
return true;
}
CREATE_FUNC(TileTestScene)
private:
TMXLayer* layer;
};
Below is the Trees.tmx file generated by Tiled Editor:
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-up" width="4" height="4" tilewidth="34" tileheight="34" infinite="0" nextlayerid="2" nextobjectid="1">
<tileset firstgid="1" source="trees.tsx"/>
<layer id="1" name="Trees" width="4" height="4">
<data encoding="csv">
1,7,4,2,
3,8,5,6,
1,7,4,2,
3,8,5,6
</data>
</layer>
</map>
And below is trees.tsx
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.10" tiledversion="1.10.1" name="trees" tilewidth="34" tileheight="34" tilecount="9" columns="3">
<image source="trees.png" width="102" height="102"/>
</tileset>
And image to the right is Trees.png, referenced by the tsx file:
In the tiled map editor, my map should look like the following (when zoomed in):
But, when then running Cocos2d-x-4 I get the following completely wrong output:
One thing of note which I found during debugging, which I cannot understand is the on the code line of:
auto sprite = layer->getTileAt(Vec2(i, j));
it sometimes returns back NULL sprites, even though there are no blank tiles on my map. I'm unsure if I have set something up incorrectly for Cocos2d-x or something else. Please help
UPDATE:
Cocos2d-x fails load the file properly because Tiled Editor version 1.10 added in newline characters in the csv data, -- breaking the Cocos2d-x importing the data.
Changing Tiled Editor to export data in base64 works. -- However, I would still like the csv format to work too.
(As requested, moving my initial comment to a full response.)
There is a fix that exists for this issue here: https://github.com/cocos2d/cocos2d-x/pull/20483
You can merge the changes in that PR to address your problem.
Original fix:
void TMXMapInfo::endElement(void* /*ctx*/, const char *name)
{
...
else if (tmxMapInfo->getLayerAttribs() & TMXLayerAttribCSV)
{
unsigned char *buffer;
TMXLayerInfo* layer = tmxMapInfo->getLayers().back();
tmxMapInfo->setStoringCharacters(false);
std::string currentString = tmxMapInfo->getCurrentString();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
// Fix bug when tilemap data is in csv format.
// We have to remove all '\r' from the string
currentString.erase(std::remove(currentString.begin(), currentString.end(), '\r'), currentString.end());
#endif
...
}
One thing that doesn't make sense about that fix though is that it seems to apply only to the Windows build of Cocos2d-x, but you want it to be applied to any platform, so it may be best not to use the pre-processor check for the platform (the #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
).
A somewhat better fix for this issue exists in Axmol (a fork of Cocos2d-x v4), which you can also apply. This change replaces all "\n\r" end-line characters that exist in the file, which fixes any issues related to the end of line characters. You can see the fix here: https://github.com/axmolengine/axmol/commit/ed3bb5eaf82ba4e74dc9784da57f621d8501aff6
It's just adding text = std::regex_replace(text, std::regex("[\n\r ]"), "");
to the TMXMapInfo::textHandler
function.
void TMXMapInfo::textHandler(void* /*ctx*/, const char* ch, size_t len)
{
TMXMapInfo* tmxMapInfo = this;
std::string text(ch, 0, len);
text = std::regex_replace(text, std::regex("[\n\r ]"), "");
if (tmxMapInfo->isStoringCharacters())
{
std::string currentString{tmxMapInfo->getCurrentString()};
currentString += text;
tmxMapInfo->setCurrentString(currentString);
}
}