使用Cocos2d-x v4 C++时,CSV瓦片地图(tmx文件)的加载错误。

huangapple go评论95阅读模式
英文:

Incorrect loading of CSV Tilemap (tmx file) using Cocos2d-x v4 C++

问题

我正试图将从Tiled Map Editor生成的2D平铺地图(.tmx + .tms文件)加载到Cocos2d-x版本4中。我正在使用Visual Studios 2022构建项目 - Win32

我试图尽可能简化场景,使平铺地图尽可能简单以使其正常工作,但一直未能成功。

以下是我试图加载的场景的完整代码:

#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;
};

以下是Tiled Editor生成的Trees.tmx文件:

<?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>

以下是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>

右侧的图像是Trees.png,由tsx文件引用:
使用Cocos2d-x v4 C++时,CSV瓦片地图(tmx文件)的加载错误。

在平铺地图编辑器中,我的地图应该如下所示(放大时):
使用Cocos2d-x v4 C++时,CSV瓦片地图(tmx文件)的加载错误。

但是,在运行Cocos2d-x-4时,我得到了完全错误的输出:
使用Cocos2d-x v4 C++时,CSV瓦片地图(tmx文件)的加载错误。


一个需要注意的事项是,在调试期间我发现不能理解的一点是:

 auto sprite = layer->getTileAt(Vec2(i, j));

有时会返回NULL精灵,尽管我的地图上没有空白瓷砖。我不确定我是否设置了Cocos2d-x或其他什么东西。

请帮助


更新:

Cocos2d-x无法正确加载文件,因为Tiled Editor版本1.10在csv数据中添加了换行符,破坏了Cocos2d-x导入数据的方式。

将Tiled Editor更改为以base64格式导出数据可以解决问题。但是,我仍然希望csv格式也能正常工作。

英文:

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 &quot;cocos2d.h&quot;

USING_NS_CC;

class TileTestScene : public Scene
{
public:
  virtual bool init() 
  {
    auto map = TMXTiledMap::create(&quot;tmx/Trees.tmx&quot;);
    layer = map-&gt;getLayer(&quot;Trees&quot;);

    auto mapSize = layer-&gt;getLayerSize();

    auto visibleSize = Director::getInstance()-&gt;getVisibleSize();

    for (int i = 0; i &lt; mapSize.width; ++i)
    {
      for (int j = 0; j &lt; mapSize.height; ++j)
      {
        auto sprite = layer-&gt;getTileAt(Vec2(i, j));
        
        if (!sprite)
        {
        
        }
      }
    }

    this-&gt;addChild(map);

    map-&gt;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:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;map version=&quot;1.10&quot; tiledversion=&quot;1.10.1&quot; orientation=&quot;orthogonal&quot; renderorder=&quot;right-up&quot; width=&quot;4&quot; height=&quot;4&quot; tilewidth=&quot;34&quot; tileheight=&quot;34&quot; infinite=&quot;0&quot; nextlayerid=&quot;2&quot; nextobjectid=&quot;1&quot;&gt;
 &lt;tileset firstgid=&quot;1&quot; source=&quot;trees.tsx&quot;/&gt;
 &lt;layer id=&quot;1&quot; name=&quot;Trees&quot; width=&quot;4&quot; height=&quot;4&quot;&gt;
  &lt;data encoding=&quot;csv&quot;&gt;
1,7,4,2,
3,8,5,6,
1,7,4,2,
3,8,5,6
&lt;/data&gt;
 &lt;/layer&gt;
&lt;/map&gt;

And below is trees.tsx

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;tileset version=&quot;1.10&quot; tiledversion=&quot;1.10.1&quot; name=&quot;trees&quot; tilewidth=&quot;34&quot; tileheight=&quot;34&quot; tilecount=&quot;9&quot; columns=&quot;3&quot;&gt;
 &lt;image source=&quot;trees.png&quot; width=&quot;102&quot; height=&quot;102&quot;/&gt;
&lt;/tileset&gt;

And image to the right is Trees.png, referenced by the tsx file:
使用Cocos2d-x v4 C++时,CSV瓦片地图(tmx文件)的加载错误。

In the tiled map editor, my map should look like the following (when zoomed in):
使用Cocos2d-x v4 C++时,CSV瓦片地图(tmx文件)的加载错误。

But, when then running Cocos2d-x-4 I get the following completely wrong output:
使用Cocos2d-x v4 C++时,CSV瓦片地图(tmx文件)的加载错误。


One thing of note which I found during debugging, which I cannot understand is the on the code line of:

 auto sprite = layer-&gt;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.

答案1

得分: 1

以下是您要翻译的部分:

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);
    }
}
英文:

(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-&gt;getLayerAttribs() &amp; TMXLayerAttribCSV)
        {
            unsigned char *buffer;

            TMXLayerInfo* layer = tmxMapInfo-&gt;getLayers().back();

            tmxMapInfo-&gt;setStoringCharacters(false);
            std::string currentString = tmxMapInfo-&gt;getCurrentString();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
			// Fix bug when tilemap data is in csv format.
			// We have to remove all &#39;\r&#39; from the string
			currentString.erase(std::remove(currentString.begin(), currentString.end(), &#39;\r&#39;), 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(&quot;[\n\r ]&quot;), &quot;&quot;); 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(&quot;[\n\r ]&quot;), &quot;&quot;);

    if (tmxMapInfo-&gt;isStoringCharacters())
    {
        std::string currentString{tmxMapInfo-&gt;getCurrentString()};
        currentString += text;
        tmxMapInfo-&gt;setCurrentString(currentString);
    }
}

huangapple
  • 本文由 发表于 2023年7月18日 14:31:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76710046.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定