2017-11-05 5 views
0

나는 소행성이 화면 아래로 떨어지는 C++ 및 sfml이있는 게임에서 플레이어가 레이저를 쏘아서 파괴합니다. 소행성이나 레이저가 화면의 떨어져 갈 때, 그들은 삭제 및 해당 표준 : : 벡터에서 삭제됩니다포인터를 실행할 때의 C++ 액세스 위반

소행성 :

std::vector<Asteroid*>::iterator it; 
for (it = asteroids.begin(); it < asteroids.end();) { 
    (*it)->update(dt); 

    if ((*it)->getPosition().y > Game::window.getSize().y) { 
     delete * it; 
     asteroids.erase(it); 
    } 
    else { 
     it++; 
    } 
} 

레이저 :

for (int i = 0; i < lasers.size(); i++) { 
    lasers.at(i)->update(dt); 

    if (lasers.at(i)->getPosition().y < 0) { 
     delete lasers.at(i); 
     lasers.erase(lasers.begin() + i); 
     i--; 
    } 
} 

문제가 온다 나는 그들 사이의 충돌을 탐지하려고 노력한다. 나는 레이저의 각 인스턴스에서 모든 소행성을 반복하고 부모 클래스 GameObject의 메서드를 사용하여 충돌을 확인합니다. 나는이에 몇 시간을 보냈어요 내가없는 것

bool GameObject::isColliding(GameObject * g) { 

sf::Vector2f gPos = g->getPosition(); 
sf::Vector2f pos = this->getPosition(); // after waiting a few seconds and then testing the collision, I get this error here: Access violation executing location 0x00000000. 



if (gPos.x <= pos.x && pos.x <= gPos.x + g->width 
    || pos.x <= gPos.x && gPos.x <= pos.x + width) { 

    if (gPos.y <= pos.y && pos.y <= gPos.y + g->height 
     || pos.y <= gPos.y && gPos.y <= pos.y + height) { 

     return true; 
    } 
} 
return false; 

}

sf::Vector2f GameObject::getPosition() { 

if (isLoaded) { 
    if (animated) 
     return animatedSprite.getPosition(); 
    else 
     return sprite.getPosition(); // the asteroids are not animated, so this will be called. 

} 

}

:

for (int i = 0; i < Game::spawner->asteroids.size() - 1; i++) { 

    if (isColliding(asteroids.at(0))) { // Access violation executing location 0x071DE528. 
     printf("collided"); 
     //delete asteroids.at(i); 
     //asteroids.erase(asteroids.begin() + i); 
     break; 
    } 
} 

다음은 isColliding와하는 getPosition 방법 무슨 일이 일어나고 있는지 알아 내려고. 나는 포인터와 인덱스를 안전하게 지우고 있다고 생각하기 때문에 거기에서 어디로 가야할지 모르겠습니다. 참고로, isColliding 함수는 두 개의 별개 GameObjects (플레이어와 소행성)에서 작동합니다. 문제가 모든 소행성을 반복하는 것과 관련이있는 것처럼 보입니다.

도움 주셔서 감사합니다.

업데이트] 소행성 삭제 :

int toDelete = -1; 
for (int i = 0; i < asteroids.size(); i++) { 
    asteroids.at(i)->update(dt); 

    if (asteroids.at(i)->getPosition().y > Game::window.getSize().y) { 
     toDelete = i; 
    } 
} 

if (toDelete != -1) { 
    delete asteroids.at(toDelete); 
    asteroids.erase(asteroids.begin() + toDelete); 
} 
+0

그런 벡터를 반복 할 수 없으며 그 위에'erase'를 호출하십시오. –

+0

'asteroids'가 비어 있다면,'i asteroids.size() - 1'는 사실입니다! – aschepler

답변

1

당신은 삭제 후 소행성 통해 이동하는 반복자를 사용하고는, 그러나 문서는 erase를 호출 한 후 반복자가 무효화되는 것을 말한다 :

Erase documentation

모든 반복자, 포인터 및 r을 사용하여 위치 (또는 첫 번째) 이상을 가리키는 반복자, 포인터 및 참조가 무효화됩니다. 위치 (또는 첫 번째) 앞에있는 요소에 대한 참조는 호출 전에 참조 된 것과 동일한 요소를 계속 참조하도록 보장됩니다.

따라서 첫 번째 호출 지우기 후에 포인터가 더 이상 유효하지 않으며 아무 것도 발생할 수 없습니다. 운명의 소행성을 먼저 확인한 다음 별도로 지우는 것과 같은 삭제 전략을 시도해보십시오.

+0

이터레이터 (또는 레이저의 경우 인덱스 된 변수)는 지우기를 고려하여 조정될 수 있습니까? 예를 들어, 항목을 지우지 않을 때만 증가시킵니다. erase()는 벡터의 순서 항목을 변경하지 않습니다. – panner2

+0

아니요, 이터레이터는 지우개를 고려하여 조정할 수 없으며 작동 방식이 다릅니다. 지우기를 호출하면 이터레이터가 무효화되고 이에 대해 할 수있는 일이 없습니다. 당신은 그 주위를 돌아 다니려고 노력할 수 있으며 유효한 위치를 찾을 수도 있습니다. 그러나 사용 방법이 아니기 때문에 이에 대한 보장은 없습니다. – Rodrigo

+0

지금은 루프 외부의 소행성을 삭제하고 있지만 문제는 지속됩니다. 두 가지 오류는 여전히 임의의 시간에 발생합니다. 나는 원래의 질문에 업데이트 된 코드를 포함시켰다. – panner2