2014-12-19 217 views
0

我正在用C++和SFML製作遊戲。我有一個奇怪的錯誤,只要我在屏幕上有1個敵人和3個鏡頭,並且子彈與敵人碰撞,遊戲就會崩潰。我得到的錯誤是:SFML奇怪的拍攝錯誤

Expression: vector subscript out of range 

我這是怎麼檢查的鏡頭和敵人之間的碰撞:

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); 
     } 
    } 
} 

「敵人」和「槍」是我插入在每x秒載體主循環。下面是該代碼:

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(); 
    } 

正如我所說的,當我有敵1和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

你不能只是載體抹去的東西,而迭代他們你正在做的,因爲它會產生I值,將不會在載體的範圍了的方式(後其大小通過調用擦除而減小),這基本上會導致嘗試索引不再存在的數組值。 如果你需要的行爲,這是一個好主意,使用迭代器:

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

你將用於拍攝陣列做同樣的。

+0

謝謝,但現在我得到了一個不同的問題。看到我編輯的帖子 – Wahoozel