Работаю над игрой астероидов для моего портфолио. В игре обнаружена ошибка со следующим блоком кода. Ошибка просто в том, что итератор не подлежит исправлению, но я сузил ошибку. Я поговорю об этом после того, как покажу код:
void Game::Update()
{
if (elapsedTime > REFRESH_RATE)
{
player->Update(elapsedTime);
std::vector<Asteroid*>::iterator iterator= bigAsteroids.begin();
std::vector<Bullet*>::iterator iter = bullets.begin();
// *********************** //
while (iterator!= bigAsteroids.end())
{
if (*iterator != nullptr) // Checks to see if player is colliding with an asteroid and updates the asteroid
{
player->CheckCollisionsAsteroid( *iterator );
// *********************** // Checks to see if bullet is colliding with asteroid
while (iter != bullets.end())
{
if (*iter != nullptr)
{
if ((*iter)->CheckCollisionsAsteroid( **iterator ))
{
size_t i = iterator - bigAsteroids.begin();
iter = bullets.erase(iter);
iterator = bigAsteroids.erase(iterator);
printf("\nAsteroid destroyed at position %i", i);
}
else
{
++iter;
}
}
}
iter = bullets.begin(); // Reset the bullet iterator else we'd only get to check 1 asteroid
// *********************** //
if (*iterator != nullptr && iterator != bigAsteroids.end()) { (*iterator)->Update(elapsedTime); }
}
if (*iterator != nullptr && (iterator!= bigAsteroids.end()))
{++iterator;}
}
// *********************** //
Clock.Reset();
}
}
Если все выглядит немного грязно, вот краткое объяснение:
Когда итератор проходит через каждый из астероидов, я проверяю, сталкивается ли игрок с каждым из астероидов. В настоящее время это ничего не делает
Затем я перебираю свой вектор пуль, сверяя каждую пулю с текущим астероидом. если происходит столкновение, я уничтожаю и стираю и пулю, и астероид, и распечатываю, какую позицию занимал разрушенный астероид в векторе.
Как только я закончу с этим, я переустановил маркер пули для следующего астероида.
Моя главная проблема в настоящее время — это вызов Update (* iterator) <- астероид
Проблема возникает только тогда, когда я стираю последний объект в векторе астероидов. Я знаю, что erase возвращает итератор к следующему объекту — если следующий объект не существует, будет выдана ошибка (так как итератор затем указывает на nullptr, верно?). Я делаю проверки для nullptr безрезультатно ..
У кого-нибудь есть совет или помощь, которую они могут предложить? Буду очень признателен, чесал мою голову в течение нескольких часов!
Проблема в том, что когда вы уничтожаете последний астероид, iterator
будет установлен в bigAsteroids.end()
(будучи назначенным на результат erase()
). Затем после внутреннего while
цикл завершается разыменованием iterator
, Итератор конца-конца не может быть разыменован.
Вам придется изменить порядок чеков:
if (iterator != bigAsteroids.end() && *iterator != nullptr)
Других решений пока нет …