I got class a with access to all standard SFML stuff:
class A{
public:
A(int type, Vector2f pos){
if(type == 1) tex.loadFromFile(path1);
else if(type == 2) tex.loadFromFile(path2);
//etc. etc.
shape.setTexture(&tex);
//then I set up the radius, and the position (from the constructor)
//I debugged this part and it seemed to work so I wont bother typing it out
};
Texture tex;
CircleShape shape;
};
In another class B I got an std::vector of A:
class B{
public:
void update(){
//under a bunch of conditions
list.push_back(A(1,Vector2f(100,100)); //examples
list.push_back(A(1,Vector2f(200,200))
}
std::vector<A> list;
};
Anyhow the textures don't load properly and I'm left with white spheres. I tried putting it in a separate function and calling that with back()
and it loaded only the first one, but not the second. It's very strange behaviour and I don't know what's causing it.
By calling shape.setTexture(&tex)
, a pointer to your Texture object is stored in shape.
The problem is that you are using std::vector
to manage your A objects.
A std::vector
manages an array on the heap. But this array is not dynamic, it cannot change its size. So, in order to increase its size, a vector allocates a completely new array with the required size, copies the elements from the old array into the new one and deletes the old array.
Now, the pointer inside your Shape object is invalidated since it has not been updated and it now points to a memory location that could have anything in it.
The website https://en.cppreference.com/w/cpp/container/vector shows under "Iterator invalidation" what iterators (which are basically pointers) are invalidated by what methods when using a std::vector
.
That is the reason why your textures are not working properly.
In order to fix this issue, I would suggest using some type of pointer to the tex
object inside your A class.
You could use a raw pointer that points to a Texture object that you created with new
inside your constructor. But be sure to delete
the object in the destructor.
As an alternative, you could use a std::unique_ptr
or a std::shared_ptr
to automatically manage the destruction of the Texture object.
By using a pointer to a seperate object, pointer invalidation to the Texture object can be avoided since the object itself is not moved.
Alternatively, you could use a std::list
instead of a std::vector
because adding objects to a list does not invalidate pointers to objects in that list.
From https://en.cppreference.com/w/cpp/container/list:
Adding, removing and moving the elements within the list or across several lists does not invalidate the iterators or references. An iterator is invalidated only when the corresponding element is deleted.
The downside to lists is that they do not provide random access.