SFML community forums

Help => Graphics => Topic started by: BeautiCode on July 21, 2014, 04:23:12 am

Title: Problem returning sf::Texture
Post by: BeautiCode on July 21, 2014, 04:23:12 am
//Data.h
class Data
{
public:

    bool playing=false;
    float W_HEIGHT=576,W_WIDTH=768;
    sf::Texture dirt,grass,water,man;
    sf::Sprite layout[9][13];
    sf::Text error;
    sf::Font default_font;
    int tiles[9][13]={
    {2,2,2,2,2,2,2,2,2,2,2,2,2},
    {2,2,2,2,2,2,2,2,2,2,2,2,2},
    {2,2,2,2,2,2,2,2,2,2,2,2,2},
    {2,2,2,2,2,2,2,2,2,2,2,2,2},
    {2,2,2,2,2,2,2,2,2,2,2,2,2},
    {2,2,2,2,2,2,2,2,2,2,2,2,2},
    {2,2,2,2,2,2,2,2,2,2,2,2,2},
    {2,2,2,2,2,2,2,2,2,2,2,2,2},
    {2,2,2,2,2,2,2,2,2,2,2,2,2}
    }; //1=water,2=dirt,3=grass
};

//Verifications.h
class Verifications : public Data
{
public:
    sf::Texture getObject(int tile);
private:


};

//Verifications.cpp
#include "verifications.h"
sf::Texture Verifications::getObject(int tile)
{
    switch(tile)
    {
    case 1:
        {
            return water;
        } break;
    case 2:
        {
            return dirt;
        } break;
    case 3:
        {
            return grass;
        } break;
    default:
        return dirt;
    //Add "default", return an X or ? or Message.
    }
}

//actions.h
class Actions : public Data
{
public:
    Verifications Ver;
    Actions(sf::RenderWindow* temp) : win(temp)
    {

    }
    void initgame();
    void gameerror();
    void loadscreen();
private:
    sf::RenderWindow* win;
};

//loadscreen() in Actions.h
void Actions::loadscreen()
{
    //win->clear(sf::Color(205,133,63));
    //Ver.getObject(tiles[y][x])

    for(int x=0,y=0;;x++)
    {
        if(x==12) {x=0;y++;}
        if(y>8) {break;}
        layout[y][x].setPosition(x*64,y*64);
        layout[y][x].setTexture(Ver.getObject(tiles[y][x]));
        std::cout<<tiles[y][x];
        std::cout<<Ver.test();
        win->draw(layout[y][x]);
    }
    win->display();
}

 

For some reason it doesn't display the dirt sf::Texture that should be from getObject(). The id is passed into getObject() by tiles[y][ x ] and if it gets 2, it should return the dirt sf::Texture.
But when I change the argument from Ver.getObject(tiles[y][ x ]) to just dirt , it displays everything how it should be.
I even  tried directly passing2into getObject(),but it still doesn't display. So it's a problem with the return
Title: Re: Problem returning sf::Texture
Post by: Strelok on July 21, 2014, 04:51:01 am
I'm quite sure getobject(int) calls sf::texture's copy constructor so that you have a copy of dirt every get object. You might want to use a shared pointer or a reference to sf::texture.
Title: Re: Problem returning sf::Texture
Post by: BeautiCode on July 21, 2014, 04:51:56 am
I'm quite sure getobject(int) calls sf::texture's copy constructor so that you have a copy of dirt every get object. You might want to use a shared pointer or a reference to sf::texture.
I tried that as-well.
Title: Re: Problem returning sf::Texture
Post by: Strelok on July 21, 2014, 04:58:59 am
 http://sfml-dev.org/documentation/2.1/classsf_1_1Sprite.php#a3729c88d88ac38c19317c18e87242560  (http://sfml-dev.org/documentation/2.1/classsf_1_1Sprite.php#a3729c88d88ac38c19317c18e87242560) the texture of get object is destroyed right after set texture
That's why only settexture (dirt) works.
Title: Re: Problem returning sf::Texture
Post by: BeautiCode on July 21, 2014, 05:03:57 am
I did the reference thing again, and also called loadFromFile() a secondtime, but inside the getObject()function.
Now it works...But why?
Title: Re: Problem returning sf::Texture
Post by: Strelok on July 21, 2014, 05:17:52 am
sf::Texture::setTexture(const sf::Texture&, bool) saves a pointer to your sf::Texture. Dirt has the lifespan of Data, while get object copies dirt and creates a temporary sf::Texture that will be destroyed after set texture, now the sprite has an invalid pointer to a texture, leading to an undefined behaviour. By returning a reference to dirt in getobject you almost do the same as settexture(dirt) ensuring that the pointer will be valid as long Data is valid and dirt correctly initialized.
Sorry for the confusion, it's 5:20 AM and I am writing from a tablet :D.
Title: Re: Problem returning sf::Texture
Post by: BeautiCode on July 21, 2014, 05:39:24 am
sf::Texture::setTexture(const sf::Texture&, bool) saves a pointer to your sf::Texture. Dirt has the lifespan of Data, while get object copies dirt and creates a temporary sf::Texture that will be destroyed after set texture, now the sprite has an invalid pointer to a texture, leading to an undefined behaviour. By returning a reference to dirt in getobject you almost do the same as settexture(dirt) ensuring that the pointer will be valid as long Data is valid and dirt correctly initialized.
Sorry for the confusion, it's 5:20 AM and I am writing from a tablet :D.
Ooh, alright thank you! :)