#c #sfml
#c #sfml
Вопрос:
Я создаю игру на C и SFML, и у меня возникла проблема при рендеринге различных элементов с помощью массива. Когда я пытаюсь нарисовать массив спрайтов, отладка проходит нормально, предупреждений и ошибок нет, но моя игровая программа работает всего 20 секунд, затем она останавливается и сообщает: «Необработанное исключение в 0x7C50CF2E (sfml-graphics-d-2.dll ), ECOVID-19 SFML.exe ): 0xC0000005: местоположение чтения с нарушением доступа 0xCCCCCCD0.’ Я сделал все, что мог, но я не знаю, почему возникает это исключение. Вот мои коды, которые, как я подозреваю, являются причиной ошибки. Спасибо за чтение, несмотря на мой плохой английский.
#include <SFML/Graphics.hpp>
...
using namespace std;
using namespace sf;
...
int main () {
...
//item Sprites
Texture bombTex;
bombTex.loadFromFile("images/bomb.png");
Sprite bomb;
...
Texture bomb2Tex;
bomb2Tex.loadFromFile("images/bomb_2.png");
Sprite bomb_2;
...
Texture cakeTex;
cakeTex.loadFromFile("images/cake.png");
Sprite cake;
...
Texture coffeeTex;
coffeeTex.loadFromFile("images/coffee.png");
Sprite coffee;
...
Texture chickenTex;
chickenTex.loadFromFile("images/chicken.png");
Sprite chicken;
...
Texture pizzaTex;
pizzaTex.loadFromFile("images/pizza.png");
Sprite pizza;
//item array (I made an item array to display amp; render various items in the game screen.)
Sprite item[10]; //Although I change the array size to 4 or 5, the same exception occurs.
item[0] = bomb;
item[1] = coffee;
item[2] = bomb_2;
item[3] = chicken;
item[4] = pizza;
std::vector<Sprite> items;
items.push_back(Sprite(item[4]));
...
while (window.isOpen())
{ ...
...
for (size_t i = 0; i < items.size(); i )
{
if (humanArr[index].getGlobalBounds().intersects(item[i].getGlobalBounds()))
//humanArr[index] is a player Sprite.
{
...
items.erase(items.begin() i);
}
}
...
window.clear();
...
for (size_t i = 0; i < items.size(); i )
{
window.draw(item[i]); // <- the exception error occurs here.
}
...
window.display();
}
return 0;
}
Комментарии:
1.
std::vector<Sprite> items;
—Sprite
Имеет правильную семантику копирования? Если нет, то наличиеvector
ofSprite
не будет работать слишком хорошо.2. Увеличивается ли вектор
items
со временем? Если это так, то в цикле вы говорите, что.intersects(item[i].getGlobalBounds())
еслиitems
размер большеitem
, то вы получаете доступ из диапазона3. Пропущено много кода, поэтому трудно сказать. Все ли
Texture
s все еще находятся в области видимости, когда выdraw
создаете спрайты?4. Кажется возможным, что причиной является некоторое несоответствие между
items
иitem
. Ваш цикл рисования предполагает, что онitem
по крайней мере такой же большой, какitems
но, возможно, это не так. Просто иметь две параллельные структуры данных, подобные этой, немного сомнительно.
Ответ №1:
Что может происходить, так это то, что при копировании Sprite item[10];
в std::vector<Sprite> items;
класс Sprite создает неглубокую копию. Это означает, что если класс Sprite выделяет какую-либо память с помощью new
оператора и сохраняет ее в указателе на член, то поверхностная копия скопирует только адрес, на который указывает указатель. При выполнении вызова items.erase(items.begin() i);
будет вызван деструктор спрайта, и в деструкторе это может быть вызов delete в этом указателе на некоторый ресурс.
При вызове window.draw(item[i]);
библиотека попытается использовать этот ресурс и обнаружит недопустимый адрес.
Я предлагаю, чтобы вы не использовали Sprite item[10];
и только std::vector<Sprite> items;
, вот так:
std::vector<Sprite> items;
items.push_back(bomb);
items.push_back(coffee);
...
window.draw(items[i]);
Вам не нужно использовать промежуточный массив, просто std::vector<Sprite>
;