2017-12-19 42 views
-3

벡터 std::vector<Bullet*> bullets을 반복하면서 적과 충돌을 찾고 있습니다. 그것은 다음과 같은 경우를 제외하고 모든 경우에 훌륭하게 작동합니다. 마지막으로 발사 된 총알이 두 개 이상 있어야 적과 충돌합니다.마지막 std :: vector 요소를 지울 때 프로그램이 충돌합니다

코드 -

for(std::vector<Bullet*>::iterator it = bullets.begin(); it != bullets.end(); ++it) 
{ 
    if ((*it)->getSprite()->getGlobalBounds().intersects(enemy->getSprite()->getGlobalBounds())) 
    { 
     delete *it; 
     bullets.erase(it); 
     enemy->destroy(); 
     if (bullets.size() == 0) 
      break; 
    } 
} 

은 내가 for 루프에서 특정 요소를 주석하고 bullet.erase(it) 호출이 프로그램을 충돌 사실을 발견했다. 해당 충돌이 발생하면 반환 코드 134 (0x86)가 표시됩니다. 이 코드의 문제점은 무엇입니까?

(*it)->getSprite()Bullet 클래스에서 스프라이트에 대한 포인터를 반환합니다.

+0

['std :: vector :: erase'] (http://en.cppreference.com/w/cpp/container/vector/erase)는 호출 후에 iterator를 무효화하고'++ it'을 만듭니다. '지우기', 정의되지 않은 행동. –

+1

왜 std :: vector :: pop_back()이냐고 –

+0

나는 다음과 같이하려고했습니다 : if (std :: next (it)) == bullets.end() bullets.pop_back(); else bullets.erase (it); 하지만 작동하지 않는 것 같습니다. –

답변

0

및 [마지막 요소]를 bullet.erase (IT) 호출이 어떤 의미에서 프로그램

충돌 사실을 발견, 당신은 아마 중간에 삭제를 수행하고 있습니다.

는 다음과 같은 고려 :

범위, 대상 및 무기 타입의 테스트 매개 변수, 예를 들어, 달성하기 위해 10 %의 적중률을 결합 할 수있는 가능성이있다. 따라서, 1000 발의 콜렉션 (1000 == bullets.size())에서, 목표에 부딪힌 총알이 100 개가 될 것입니다.

코드는 각 요소를 찾고 bullets.erase()를 사용하여 벡터에 100 개의 구멍을 만듭니다. 벡터 데이터가 연속적으로 유지되기 때문에, erase 메서드는 지우개로 작성된 구멍을 채우기 위해 다른 요소도 이동합니다. (구현마다 다른 점이있을 수 있습니다.)

일반적으로 100 번 지울 때마다 매 회 1000 번 이하의 요소가 100 번 반복됩니다.이 한 번에 한 번 접근하면됩니다. 비교적 느린 과정. 코드를 확인하고 모든 표시 될 때까지 현재의 디자인에 대한 대안으로


대신 찾기 및 삭제의 '교차'지우기를 연기.

  • 당신은 아직 삭제하지 마십시오 같은 방법으로 교차 (조회수)하지만, '마크'를 찾을 수 있습니다. 옵션으로 Bullet 클래스에 bool을 추가하거나 일치하는 bool 벡터를 유지하여 각 글 머리표에 대해이 플래그를 유지할 수 있습니다. 0 I1 (제 1 (가장 왼쪽) 벡터 요소)로 초기화

    - - I2 초기화 개의 인덱스

    사용

  • (bullets.size를() - 1) 마지막 (가장 오른쪽) 벡터 요소]

- 스핀 증가 I1은

첫 번째 히트를 찾을 수 - 마지막 미스를 찾기 위해 스핀 감소의 I2를

- 다음 표준 : 스왑 (탄알 [I1, 탄알 [I2]) I1> I2 =까지

반복하기

모든 히트 연속 AND 벡터의 꼬리에 있는지, 100 히트를 한 번만 지우십시오.

이렇게하면 셔플이 제거됩니다.

또한 지우기 요소는 사용하지 않아야합니다 ... 지우기는 프로세스가 끝나기 때문에 발생합니다.

+0

단점은 물론 나머지 '놓친'글 머리 기호가 더 이상 원래 순서대로 존재하지 않는다는 것입니다. –

1

무엇 remove_iferase 콤보를 사용하는 방법에 대한 :

당신의 고려
auto is_hit = [&enemy](Bullet *bullet) 
{ 
    if (bullet->getSprite()->getGlobalBounds().intersects(enemy->getSprite()->getGlobalBounds())) 
    { 
     delete bullet; 
     enemy->destroy(); 
     return true; 
    } 
    return false; 
}; 

bullets.erase(std::remove_if(bullets.begin(), bullets.end(), is_hit), bullets.end()); 
1

: 나는 꼬리에 요소를 추가로 (꼬리에서 보완 조치를 벡터를 청소하는 방법

다음 코드를 보여줍니다 push_back())

while(!gBoard.empty()) 
{ 
    Cell_t* cell = gBoard.back(); // fetch last element (a ptr) 
    gBoard.pop_back();    // remove last element 
    delete cell;     // remove cell from heap - raw pointer 
} 

아마도이 스타일을 깨끗하게 처리하고 여러 벡터를 사용할 수 있습니다. 대안보다 빠를 수도 있습니다.

문제가 발생할 경우 각 글 머리표에 최소한 두 개의 목적지가있는 것으로 보입니다.

while (! Bullets.empty()) // spin through bullet list 
{ 
    Bullet* aBullet = Bullets.back(); // fetch copy of last element 
    Bullets.pop_back();    // remove last element 

    if (*aBullet)-> getSprite()->getGlobalBounds().  
      intersects(enemy->getSprite()->getGlobalBounds())) 
    { 
     // HIT! 
     Hit.push_back(aBullet); // capture the element to Hit bucket 
     enemy->destroy();  // tbd - a decision? or always final? 
     // no delete 
     if (bullets.size() == 0) // no more to compute, redundant to while 
      break; 
    } 
    else 
    { 
     // MISS 
     Missed.push_back(aBullet); // capture element to Missed bucket 
    } 
} // while 

assert(bullets.empty()); // bullets have been consumed 

// clean up spent bullets that intersected 
while (! Hit.empty()) 
{ 
    Bullet* aBullet = Hit.back(); // copy last element from Hit 
    Hit.pop_back();    // remove last element from Hit 
    delete aBullet;    // tbr - delete the dynamic memory 
} 

// clean up spent bullets that missed 
// move the bullet from Missed vec back into Bullets vec 
// for tbd - furthur evaluation ... did the bullet hit any other obj 
// the following also happens to 'undo' the seq reversal 
while (! Missed.empty()) 
{ 
    Bullets.push_back (Missed.back()); // copy last element from Missed 
    Missed.pop_back();     // remove last element from Missed 
    // tbd - also delete the missed bullet? 
    // or do you check for these bullets to collide with other objects 
} 
// possibly a copy can do this last loop, but this is simple and 
// undoes the reversal. 
+0

Hit.size()와 Missed.size()를 계산할 기회를 유의하십시오. –