Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: When creating a tile map, sprites do not always texture properly  (Read 4938 times)

0 Members and 1 Guest are viewing this topic.

Mr_Bunkers

  • Newbie
  • *
  • Posts: 11
    • View Profile
So, as the title says, I'm making a tile map loader (using the Tiled format).





The images show 2 instances of the program loading the map. One, the tiles are fine. Another, the tiles are blacked out, but only on one layer. I first thought that this was a problem with the vector in which I store my tiles, but its not. The hex values are pointers to the sf::Textures that I have loaded in my texture manager. You're wondering, well if it works in one instance, then why are you here? The images are the same program. I was stress testing my program; loading the map over and over and noticed this problem. Sometimes it works, sometimes it doesn't. I'm baffled. The textures are fine, cuz the memory is the same. The vector should be reserved correctly, but I'm not sure. The tile id's are the same every single time I load. I'm trusting that SFML is fine, unless I discovered some issue.

Here is my map parsing code. I use RapidXML to parse the .tmx file.

Quote
      bool MapManager::parseData(const std::string& src)
      {
         try
         {
            rapidxml::xml_node<> *node_root = m_document->first_node("map"), *node_layer = node_root->first_node("layer"),
               *node_data = 0;

            std::string encoding = "", compression = "";

            for(; node_layer; node_layer = node_layer->next_sibling("layer"))
            {
               std::deque<unsigned> split;
               node_data = node_layer->first_node("data");

               if(node_data->first_attribute("encoding"))
               {
                  encoding = node_data->first_attribute("encoding")->value();
                  if(encoding == "csv")
                  {
                     split = m_parse_csv(node_data->value());
                  }
                  else if(encoding == "base64")
                  {
                     if(node_data->first_attribute("compression"))
                     {
                        if((compression = node_data->first_attribute("compression")->value()) == "zlib")
                        {
                           split = m_parse_zb64(node_data->value());
                        }
                        else
                        {
                           split = m_parse_b64(node_data->value());
                        }
                     }
                  }
                  else
                  {
                     return false;
                  }

                  for(int y = 0; y < m_height; y++)
                  {
                     for(int x = 0; x < m_width; x++)
                     {
                        int id = split.front();
                        be::Object::TileSet* t = m_decide_tileset(id);

                        if(id != 0 && t && !split.empty())
                        {
                           sf::Vector2i pos(x, y), size(t->width, t->height);
                           sf::IntRect text_split = m_decide_texture_split(id, t);

                           m_tile_map.push_back(new be::Object::Tile(id, pos, size, text_split, t->texture));
                        }

                        split.pop_front();
                     }
                  }
               }
            }
         }
         catch(const rapidxml::parse_error &e)
         {
            return false;
         }

         return true;
      }

Here is what I use to load textures.

Quote
      sf::Texture* TextureManager::getTexture(const std::string& src)
      {
         for(auto i = m_textures.begin(); i != m_textures.end(); i++)
         {
            if(i->first == src)
            {
               std::cout << i->second << std::endl;
               return i->second;
            }
         }

         sf::Texture* t = new sf::Texture;

         if(t->loadFromFile(src))
         {
            std::cout << "Loading a new texture: " << src << std::endl;
            m_textures[src] = t;
            return t;
         }
         else
         {
            delete t;
            return 0;
         }
      }

I won't post more code unless needed to save everyone a headache. I got an itch that this is where the issue lies.

Tiled documentation: https://github.com/bjorn/tiled/wiki/TMX-Map-Format
« Last Edit: May 07, 2013, 03:30:39 pm by Mr_Bunkers »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10801
    • View Profile
    • development blog
    • Email
AW: When creating a tile map, sprites do not always texture properly
« Reply #1 on: May 07, 2013, 05:47:53 pm »
We won't dig in your code and debug it for you, so at best you should do it on your own. ;)
If manage it to narrow down to a minimal and complete example, we might look into it. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Mr_Bunkers

  • Newbie
  • *
  • Posts: 11
    • View Profile
We won't dig in your code and debug it for you, so at best you should do it on your own. ;)
If manage it to narrow down to a minimal and complete example, we might look into it. ;)

Understood. I'm looking into it.

Mr_Bunkers

  • Newbie
  • *
  • Posts: 11
    • View Profile
Re: When creating a tile map, sprites do not always texture properly
« Reply #3 on: May 08, 2013, 12:59:58 am »
Found the problem. It is of no importance to SFML, and I would request that this thread be removed. :)

Roose Bolton of the Dreadfort

  • Full Member
  • ***
  • Posts: 113
  • Full-time Procrastinator, Part-time programmer.
    • View Profile
    • Personal Portfolio/Website/Blog
Re: When creating a tile map, sprites do not always texture properly
« Reply #4 on: May 08, 2013, 11:00:47 am »
What was the problem in the end?
Trying so very hard to finish at-least one project.

Watch out for the RAII police, they will get you.

www.bantersaurus-games.com

Mr_Bunkers

  • Newbie
  • *
  • Posts: 11
    • View Profile
Re: When creating a tile map, sprites do not always texture properly
« Reply #5 on: May 09, 2013, 12:12:07 am »
What was the problem in the end?

Loading TMX requires that you provide information for the tiles, provided in the tilesets in the .tmx file. I was loading the tileset information into a priority queue, which held a custom Object::TileSet class, and had overrode the < operator to compare gid's. However, I put pointers of the Object::TileSet into priority queue, so it was comparing the memory of the pointers, not the gid.

To solve the problem, I just stored references to the Object::TileSet's in the queue and continued on my merry way.

Like I said, not a SFML problem, and probably not helpful to anybody in the future, so this thread can be deleted.

This is what the TileSet looks like now, I changed the operator override from

bool operator<(const TileSet &b)

to

bool operator<(const TileSet &b) const

        namespace Object
        {
                struct TileSet
                {
                        // ctor, dtor...

                        virtual ~TileSet(){}

                        bool operator<(const TileSet &b) const
                        {
                                return this->gid > b.gid;
                        }

                        sf::Texture* texture;
                        int gid, spacing, height, width;
                };
        }
 

Then I changed the priority queue from

std::priority_queue<Object::TileSet*> tileset_queue;

to

std::priority_queue<Object::TileSet> tileset_queue;
« Last Edit: May 09, 2013, 12:22:30 am by Mr_Bunkers »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: When creating a tile map, sprites do not always texture properly
« Reply #6 on: May 09, 2013, 11:08:05 am »
In general, declare binary operators as non-member functions. This treats the two operands symmetrically and allows implicit conversions of both.
bool operator< (const TileSet& lhs, const TileSet& rhs)
{
    return lhs.gid < rhs.gid;
}

If the operator< is not meaningful in other contexts, you can also define a predicate functor:
struct CompareTileSet
{
    bool operator() (const TileSet& lhs, const TileSet& rhs)
    {
        return lhs.gid < rhs.gid;
    }
};

std::priority_queue<TileSet, std::vector<TileSet>, CompareTileSet> queue;
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Mr_Bunkers

  • Newbie
  • *
  • Posts: 11
    • View Profile
Re: When creating a tile map, sprites do not always texture properly
« Reply #7 on: May 09, 2013, 07:57:08 pm »
In general, declare binary operators as non-member functions. This treats the two operands symmetrically and allows implicit conversions of both.
bool operator< (const TileSet& lhs, const TileSet& rhs)
{
    return lhs.gid < rhs.gid;
}

If the operator< is not meaningful in other contexts, you can also define a predicate functor:
struct CompareTileSet
{
    bool operator() (const TileSet& lhs, const TileSet& rhs)
    {
        return lhs.gid < rhs.gid;
    }
};

std::priority_queue<TileSet, std::vector<TileSet>, CompareTileSet> queue;

Why does overriding the () operator work?

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: When creating a tile map, sprites do not always texture properly
« Reply #8 on: May 09, 2013, 08:01:05 pm »
Why does overriding the () operator work?
Because the C++ standard allows it ;)

Overriding the function call operator is the basic idea of functors (function objects). This allows very powerful constructs like std::function in C++11.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Mr_Bunkers

  • Newbie
  • *
  • Posts: 11
    • View Profile
Re: When creating a tile map, sprites do not always texture properly
« Reply #9 on: May 09, 2013, 08:02:54 pm »
Why does overriding the () operator work?
Because the C++ standard allows it ;)

Overriding the function call operator is the basic idea of functors (function objects). This allows very powerful constructs like std::function in C++11.

No, I mean, what does the () operator do in the std::priority_queue? I'm learning something new here.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: When creating a tile map, sprites do not always texture properly
« Reply #10 on: May 09, 2013, 08:13:13 pm »
The same as operator<, it is used to compare different values. The priority queue must reorder the elements according to their priority values. See here for example.

By the way, there is no need for a full quote if the text is just above :)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Mr_Bunkers

  • Newbie
  • *
  • Posts: 11
    • View Profile
Re: When creating a tile map, sprites do not always texture properly
« Reply #11 on: May 09, 2013, 08:32:27 pm »
The same as operator<, it is used to compare different values. The priority queue must reorder the elements according to their priority values. See here for example.

By the way, there is no need for a full quote if the text is just above :)

Understood. Thanks. ::)

 

anything