Текстура SFML не загружается должным образом - PullRequest
0 голосов
/ 30 мая 2020

У меня есть класс a с доступом ко всем стандартным материалам SFML:

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;
};

В другом классе BI получил std :: vector из 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;
 };

Как бы то ни было, текстуры не не загружается должным образом, и у меня остаются белые сферы. Я попытался поместить его в отдельную функцию и вызвать его с помощью back(), и он загрузил только первую, но не вторую. Это очень странное поведение, и я не знаю, что его вызывает.

1 Ответ

1 голос
/ 17 июня 2020

При вызове shape.setTexture(&tex) указатель на ваш объект текстуры сохраняется в форме.

Проблема в том, что вы используете std::vector для управления вашими объектами A. A std::vector управляет массивом в куче. Но этот массив не является динамическим c, он не может изменить свой размер. Итак, чтобы увеличить свой размер, вектор выделяет совершенно новый массив требуемого размера, копирует элементы из старого массива в новый и удаляет старый массив.
Теперь указатель внутри вашего объекта Shape равен аннулирован, так как он не был обновлен, и теперь он указывает на ячейку памяти, в которой могло быть что угодно.

Веб-сайт https://en.cppreference.com/w/cpp/container/vector показывает в разделе «Недействительность итератора», какие итераторы (какие в основном указатели) становятся недействительными, какими методами при использовании std::vector.

Это причина, по которой ваши текстуры не работают должным образом.

Чтобы исправить эту проблему, я бы предложил использовать некоторый тип указателя на объект tex внутри вашего класса A.
Вы можете использовать необработанный указатель, который указывает на объект Texture, который вы создали с помощью new внутри вашего конструктора. Но не забудьте указать delete объект в деструкторе.
В качестве альтернативы вы можете использовать std::unique_ptr или std::shared_ptr для автоматического управления уничтожением объекта текстуры.

Используя указателя на отдельный объект, аннулирования указателя на объект текстуры можно избежать, поскольку сам объект не перемещается.

В качестве альтернативы вы можете использовать std::list вместо std::vector, потому что добавляете объекты в list не делает недействительными указатели на объекты в этом списке.

From https://en.cppreference.com/w/cpp/container/list:

Добавление, удаление и перемещение элементов внутри списка или между несколькими списками не делает недействительными итераторы или ссылки. Итератор становится недействительным только при удалении соответствующего элемента.

Обратной стороной списков является то, что они не обеспечивают произвольный доступ.

...