2014-12-19 6 views
0

저는 C++과 SFML로 게임을 만들고 있습니다. 나는 이상한 버그가있다. 화면에 정확히 적 1 개와 총 3 개가 있고 적과 총알이 충돌 할 때마다 게임이 충돌한다. 이해가 오류가 있습니다 : 나는 모든 x 초에 삽입 벡터를SFML 이상한 슈팅 버그

for (int i = 0; i < enemies.size(); i++) 
{ 
    for (int s = 0; s < shots.size(); s++) { 
     if (Collision::PixelPerfectTest(enemies[i].getSprite(), shots[s].getSprite())) { 
      enemies[i].setHealth(enemies[i].getHealth() - player.getDamage()); 
      if (enemies[i].getHealth() <= 0) { 
       enemies.erase(enemies.begin() + i); 
      } 
      shots.erase(shots.begin() + s); 
     } 
    } 
} 

"적"과 "샷"입니다

Expression: vector subscript out of range 

이것은 내가 샷과 적 사이의 충돌을 검사하는 방법이다 메인 루프.

if (enemySpawner.getElapsedTime().asSeconds() >= 1.5f) { 
     enemies.push_back(Enemy(spriteManager.enemySprite)); 
     std::cout << enemies.size() << " enemies" << std::endl; 
     enemySpawner.restart(); 
    } 

    if (shotSpawner.getElapsedTime().asSeconds() >= 0.3f &&  sf::Mouse::isButtonPressed(sf::Mouse::Left)) { 
     shots.push_back(Shot(spriteManager.shotSprite, player.getPosition(), *window)); 
     std::cout << shots.size() << " shots" << std::endl; 
     shotSpawner.restart(); 
    } 

내가 말했듯이, 그렇지 않으면 잘 작동하는 것 같다, 내가 한 적 3 탄이있을 때이 만 발생 : 여기에 대한 코드입니다.

편집 : 이제 첫 번째 적군이 생성되면 게임이 정지됩니다.

//Shot vs enemy 
for (auto eit = enemies.begin(); eit != enemies.end();) 
{ 
    for (auto sit = shots.begin(); sit != shots.end();) { 
     if (Collision::PixelPerfectTest((*eit).getSprite(), (*sit).getSprite())) { 
      (*eit).setHealth((*eit).getHealth() - player.getDamage()); 
      if ((*eit).getHealth() <= 0) { 
       enemies.erase(eit); 
       shots.erase(sit); 
      } 
      shots.erase(sit); 
      eit = eit++; 
      sit = sit++; 
     } 
    } 
} 

답변

0

@ moka의 대답은 코드의 핵심 문제를 설명하고 반복자를 사용하는 코드는 문제를 해결할 것입니다. 그러나 문제를 해결할 수있는 또 다른 방법이 있습니다. 코드를 "계산 패스"와 "배열 수정 패스"로 나누는 것입니다. 코드는 다음과 같을 것입니다 :

for (int i = 0; i < enemies.size(); i++) 
{ 
    for (int s = 0; s < shots.size(); s++) { 
     if (!enemies[i].alive || !shots[s].active) { 
      continue; 
     } 
     if (Collision::PixelPerfectTest(enemies[i].sprite(), shots[s].sprite())) { 
      shots[s].active = false; 
      enemies[i].setHealth(enemies[i].getHealth() - player.getDamage()); 
      if (enemies[i].getHealth() <= 0) { 
       enemies[i].alive = false; 
      } 
     } 
    } 
} 

enemies.erase(std::remove_if(enemies.begin(), enemies.end(), 
    [](Enemy const &e) { return !e.alive; }), enemies.end()); 

shots.erase(std::remove_if(shots.begin(), shots.end(), 
    [](Shot const &s) { return !s.active; }), shots.end()); 

이 스타일은 게임 논리를 구현과 조금 더 분리하기 때문에 좋습니다. 예를 들어 샷이 한 개 이상의 적을 공격 할 수있게하려면 어쨌든 샷 배열에 대해 이와 같은 접근 방식을 사용해야합니다.

Chapter on Double Buffering 우수한 게임 프로그래밍 패턴 책은 더 깊이 들어갑니다.

0

그 이상은 내가에게 벡터의 범위되지 않습니다 값을 얻을 수 있기 때문에 더 이상 일을하는 방법을 반복하는 동안 그냥 벡터에서 물건을 지울 수 없습니다 (후 : 여기에 업데이트 된 코드는 그것의 크기는 지우는 호출에 의해 줄어들었다.) 이것은 더 이상 존재하지 않는 배열 값의 색인을 만드는 것을 근본적으로 시도 할 것이다. 당신이 그 동작을 필요 경우, 반복자를 사용하는 것이 좋습니다 :

auto eit = enemies.begin(); 
for (; eit != enemies.end();) 
{ 
    if((*eit).isDead()) 
    { 
     eit = enemies.erase(eit); 
    } 
    else 
    { 
     eit++; 
    } 
} 

당신이 촬영 배열에 대해 동일한 작업을 수행합니다.

+0

고마워,하지만 지금은 다른 문제가 생겼어. 내 수정 된 게시물보기 – Wahoozel