0

I am trying to do a simple tile map. I have a problem: when I set up the map, there are only white squares. I'm normally loading the texture, so I don't know why it is like that.

Here is the code:

class Tile
{
private:
sf::Sprite sprite;
sf::Texture tex;

public:
     Tile(int x, int y, sf::Texture tex)
    {
this->tex = tex;
this->sprite.setTexture(this->tex);
this->sprite.setPosition(x, y);

    }
    void render(sf::RenderWindow* target)
    {
    target->draw(this->sprite);
    }


class Tilemap
{
private:
Tile tiles[36][64];
sf::Texture tex[4];

public:
//const/dest
Tilemap()
{
this->tex[0].loadFromFile("Resources/Tilemap/Water/water1.png");

int x = -WIDTH+WIDTH/2;
int y = -HEIGTH/2;
for (int i = 0; i < 36; i++)
{
    for (int j = 0; j < 64; j++)
    {
        this->tiles[i][j] = Tile(x, y, this->tex[0]);
        x += 60;
    }
    y += 60;
    x = -WIDTH + WIDTH / 2;
}

}


render(sf::RenderWindow* target, sf::Vector2f pos)
{
for (int i = 0; i < 34; i++)
{
    for (int j = 0; j < 64; j++)
    {
        this->tiles[i][j].render(target);
    }
}
 };
 Tilemap map;
 map = Tilemap();
4
  • Did you check whether loadFromFile returned true? Commented Jan 7, 2020 at 16:12
  • @Botje ye i did Commented Jan 7, 2020 at 16:13
  • 1
    Then I don't see anything out of the ordinary. Please rework your question to an minimal reproducible example so we can run it for ourselves. Commented Jan 7, 2020 at 16:16
  • @Bojte ok i will rework it Commented Jan 7, 2020 at 16:19

1 Answer 1

2

You have dangling reference in sprite.

This dangling reference occurs in the below line:

this->tiles[i][j] = Tile(x, y, this->tex[0]);

What does reference say about Sprite::setTexture ?

The texture argument refers to a texture that must exist as long as the sprite uses it. Indeed, the sprite doesn't store its own copy of the texture, but rather keeps a pointer to the one that you passed to this function. If the source texture is destroyed and the sprite tries to use it, the behavior is undefined.

Where exactly is problem ?

Tile(x, y, this->tex[0]);

Here, new instance of Tile is created. tex and sprite are member variables of Tile. And sprite by setTexture is referring to tex.

tiles[i][j] = Tile(x,...);

In the above line, copy assignment operator is called which copies sprite/tex from temporary object - created by Tile(x,y,..)). As a result in tiles[i][j] you have sprite member which refers to texture of temporary instance - Tile(..) (sprite just holds pointer to texture). And finally, at the end of the full expression temporary instance is destroyed, tex of Tile(..) is deleted, and tiles[i][j].sprite holds invalid pointer to texture.

Solution?

You have to add copy constructor (copy assignment operator) of Tile to properly initialize sprite for holding its own tex (no reference to the instance the copy is made from):

For example:

 Tile& operator=(const Tile& theOther)
 {
      this->tex = theOther.tex;
      this->sprite.setTexture(this->tex);
      return *this;
 }

in default generated copy assignment operator this->sprite points to theOther.tex texture, which is wrong.

Sign up to request clarification or add additional context in comments.

3 Comments

I am sorry to bother you again and thank you for your answer but I don't know how can I implement it. I tried many options but none worked. If you will don't answer then it's okay, I'll try to somehow figure it myself. Thank you.
@Torsmel Here is link where I added copy ctor and copy assignment operator to Tile class. Check it and let me know if it helped.
Thank you so much but how can I concretely use it when I'm creating the map like above? I hope it doesn't bother you a lot.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.