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

Author Topic: Vector of structs which contains sprites  (Read 2066 times)

0 Members and 2 Guests are viewing this topic.

another27

  • Newbie
  • *
  • Posts: 3
    • View Profile
    • Email
Vector of structs which contains sprites
« on: February 08, 2020, 01:44:41 am »
Im trying to do a vector of struct elements to draw them in RenderWindow;

my struct for non-ui objects:

struct element{
    sf::Texture texture;
    sf::Sprite sprite;
    sf::IntRect rect;
    sf::Text text;
};


my struct for ui objects:

struct uiElement: element{
    sf::Text text;
    bool clickable;
};


Im adding elements like that:

std::vector<uiElement> ui;

uiElement el;

el.texture.loadFromFile("../res/textures/background.jpg");
ui.push_back(el);
ui.back().sprite.setTexture(ui.back().texture);


and it works!But, only if my "std::vector<uiElement> ui;" has one element;

when i try to add more with cycle:

for (int i = 0;i < 4;i++){
                    uiElement btn;
                    btn.texture.loadFromFile("../res/textures/button.png");
                    ui.push_back(btn);
                    ui.back().sprite.setTexture(ui.back().texture);
}


draws only last object in my "std::vector<uiElement> ui;" and the other are just white

my drawing part of code:

for (auto & element : ui){
        window.draw(element.sprite);
}


How can I fix it??

thanks in advance :)

Fx8qkaoy

  • Newbie
  • *
  • Posts: 42
    • View Profile
Re: Vector of structs which contains sprites
« Reply #1 on: February 08, 2020, 08:22:06 pm »
Im trying to do a vector of struct elements to draw them in RenderWindow;

my struct for non-ui objects:

struct element{
    sf::Texture texture;
    sf::Sprite sprite;
    sf::IntRect rect;
    sf::Text text;
};


my struct for ui objects:

struct uiElement: element{
    sf::Text text;
    bool clickable;
};


Im adding elements like that:

std::vector<uiElement> ui;

uiElement el;

el.texture.loadFromFile("../res/textures/background.jpg");
ui.push_back(el);
ui.back().sprite.setTexture(ui.back().texture);


and it works!But, only if my "std::vector<uiElement> ui;" has one element;

when i try to add more with cycle:

for (int i = 0;i < 4;i++){
                    uiElement btn;
                    btn.texture.loadFromFile("../res/textures/button.png");
                    ui.push_back(btn);
                    ui.back().sprite.setTexture(ui.back().texture);
}


draws only last object in my "std::vector<uiElement> ui;" and the other are just white

my drawing part of code:

for (auto & element : ui){
        window.draw(element.sprite);
}


How can I fix it??

thanks in advance :)

At the first glance the way u use the std::vector really drags my attention, and this is what I think it's happening in ur for loop:
- create a uiElement named btn
- load its texture
- !!! push into the vector a COPY of the btn
- !!! set texture of a sprite of an ANOTHER COPY from the vector

push_back() and back(), if I'm not wrong, both takes the parameter (or returns it) by value, which means u set the sprite for a completely different obj, that u discard after. U're pushing and getting back copies, and not the original obj which u try to draw later. A way that I use most of times would be to make ur vector of pointers (uiElement*). If u're a beginner this may not be the best method since u must take care of freeing the memory after and stuff. U could, as another example, pushing into the vector after u set the sprite. Another way is to rather than using back(), get the address of the last element in vector, maybe like "&ui[ui.size() - 1]" if I'm not wrong, and change stuff on the pointer u get (pointer = &obj)

another27

  • Newbie
  • *
  • Posts: 3
    • View Profile
    • Email
Re: Vector of structs which contains sprites
« Reply #2 on: February 08, 2020, 10:43:00 pm »
1. "U could, as another example, pushing into the vector after u set the sprite."
When I do that - all sprites are turning to white -> because ui.back().sprite cant find texture -> because ui.back().sprite thinking that texture is in uiElement btn; but when i draw ui.back().sprite  uiElement btn; is didnt exist already.

I tried to do that before, so next step was add to std::vector<uiElement> ui; btn only with texture, then assign that texture to sprite and ui.back().sprite would link texture not from uiElement btn; but from ui.back().texture.
Aaaand that didn't work((

2. " make ur vector of pointers (uiElement*)"
At first - I initialize all elements in my class constructor. And if i use pointers - will my alements exist in memory after my constructor?
At second - I dont learn yet how to work with memory(((

3. "rather than using back(), get the address of the last element in vector"

I tried and changed my for:

for (int i = 0;i < 4;i++){
                    uiElement btn;
                    btn.texture.loadFromFile("../res/textures/button.png");
                    ui.push_back(btn);
                    Texture* t_ptr = &ui.back().texture;
                    ui[ui.back()].sprite.setTexture(*t_ptr);
}


And result was the same(( Only last button has correct texture and sprite,  the other are white(

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: Vector of structs which contains sprites
« Reply #3 on: February 08, 2020, 11:04:35 pm »
You're experiencing the white square problem. In this case it happens because you attempt to store the textures in a vector. Pushing an object into a vector will cause the vector to resize (if a specific size has not been reserved) moving everything the vector holds around in memory, which is why all but your last sprite appears white. Generally some sort of resource management is used to hold all your textures/shaders/audio buffers so that they can then be shared with any game entities that use them. The SFML Game Development book has a good example of how to do this.