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

Author Topic: sf::Texture question  (Read 2447 times)

0 Members and 1 Guest are viewing this topic.

c0ffee

  • Newbie
  • *
  • Posts: 13
    • View Profile
sf::Texture question
« on: January 18, 2012, 01:45:08 pm »
I'm going through basic game tutorials at sdltutorials.com and change SDL parts to sfml.
It worked well so far, but recently I've encountered unexpected behavior and would like to know the cause of it.
Here http://www.sdltutorials.com/sdl-maps at CArea.cpp
Code: [Select]
bool CArea::OnLoad(char* File) {
    MapList.clear();
 
    FILE* FileHandle = fopen(File, "r");
 
    if(FileHandle == NULL) {
        return false;
    }
 
    char TilesetFile[255];
 
    fscanf(FileHandle, "%s\n", TilesetFile);
 
    if((Surf_Tileset = CSurface::OnLoad(TilesetFile)) == false) {
        fclose(FileHandle);
 
        return false;
    }
 
    fscanf(FileHandle, "%d\n", &AreaSize);
 
    for(int X = 0;X < AreaSize;X++) {
        for(int Y = 0;Y < AreaSize;Y++) {
            char MapFile[255];
 
            fscanf(FileHandle, "%s ", MapFile);
 
            CMap tempMap;
            if(tempMap.OnLoad(MapFile) == false) {
                fclose(FileHandle);
 
                return false;
            }
 
         tempMap.Surf_Tileset = Surf_Tileset;
 
            MapList.push_back(tempMap);
        }
        fscanf(FileHandle, "\n");
    }
 
    fclose(FileHandle);
 
    return true;
}

first i changed
Code: [Select]
Surf_Tileset = CSurface::OnLoad(TilesetFile) to
Code: [Select]
m_TilesetTexture1.LoadFromFile(TilesetFile)
And it works like it has to.

The problem part is
Code: [Select]
tempMap.Surf_Tileset = Surf_Tileset;which I changed to
Code: [Select]
tempMap.m_TilesetTexture=m_TilesetTexture1;
tempMap.m_TilesetSprite.SetTexture(tempMap.m_TilesetTexture);
and later it shows map with white instead of texture.

Then i changed it to
Code: [Select]
tempMap.m_TilesetTexture=m_TilesetTexture1;
tempMap.m_TilesetSprite.SetTexture(m_TilesetTexture1);
and it shows map fine this time.

Can someone tell why
Code: [Select]
tempMap.m_TilesetTexture=m_TilesetTexture1;
tempMap.m_TilesetSprite.SetTexture(tempMap.m_TilesetTexture);
shows white surface?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
sf::Texture question
« Reply #1 on: January 18, 2012, 01:58:14 pm »
When you push_back tempMap into the MapList container, it stores a copy of it, not the original one. Therefore, your sprite uses the tileset of a temporary CMap which has been destroyed, instead of the one that is stored in the container.
Laurent Gomila - SFML developer

c0ffee

  • Newbie
  • *
  • Posts: 13
    • View Profile
sf::Texture question
« Reply #2 on: January 18, 2012, 02:51:58 pm »
Thanks, Laurent.
I hope I get it.

c0ffee

  • Newbie
  • *
  • Posts: 13
    • View Profile
sf::Texture question
« Reply #3 on: January 20, 2012, 02:24:17 pm »
I changed code, so that tempMap isn't crucial now, but the problem remained. sometimes white texture is replaced with crash.
Code: [Select]
fscanf(FileHandle, "%d\n", &AreaSize);
    int ID=0;
    for(int X = 0; X < AreaSize; X++)
    {
        for(int Y = 0; Y < AreaSize; Y++)
        {
            char MapFile[255];

            fscanf(FileHandle, "%s ", MapFile);
            CMap tempMap;
            MapList.push_back(tempMap);
            if(MapList[ID].OnLoad(MapFile) == false)
            {
                fclose(FileHandle);
                cout<<"error loading map";
                return false;
            }

   
            MapList[ID].m_TilesetTexture.LoadFromFile(TilesetFile);
            MapList[ID].m_TilesetSprite.SetTexture(MapList[ID].m_TilesetTexture);
       
            ID++;
        }
I found that vector::push_back may sometime reallocate memory http://www.cplusplus.com/reference/stl/vector/push_back/
Quote
effectively increases the vector size by one, which causes a reallocation of the internal allocated storage if the vector size was equal to the vector capacity before the call. Reallocations invalidate all previously obtained iterators, references and pointers.
I'm new to c++, can someone confirm, that because sf::Texture contains reference it's unsafe to use it with std::vector, is there some other workaround?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
sf::Texture question
« Reply #4 on: January 20, 2012, 02:31:43 pm »
Yes, you get the same problem with std::vector because it may move objects when it needs more memory.

There are several solutions:
- store pointers instead of objects (so that only the pointer values move in memory, not the objects themselves)
- use std::list, which never invalidates its elements
- link sprites to textures after the entire container is filled, so that they are at their final location in memory
- handle copy correctly inside the CMap class -- look at the last section of the sprite tutorial
Laurent Gomila - SFML developer

c0ffee

  • Newbie
  • *
  • Posts: 13
    • View Profile
sf::Texture question
« Reply #5 on: January 20, 2012, 04:17:39 pm »
Thanks, for good and fast response.
Will try the options.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
sf::Texture question
« Reply #6 on: January 20, 2012, 08:03:50 pm »
std::vector::reserve() might also help you.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

c0ffee

  • Newbie
  • *
  • Posts: 13
    • View Profile
sf::Texture question
« Reply #7 on: January 20, 2012, 08:20:21 pm »
Ye, will use reserve() for now, and move on to others(probably std::deque) in future.
Thanks