2009-11-01 33 views
0

[求助]:應用適當的列表迭代程序修復問題。 (如下所示)迭代列表的邏輯。元素「閃爍」

我現在有在其中一個列表的要素通過迭代和擦除,如果符合特定條件的節目。由於該計劃的性質,這可以直觀地看到。正在通過有時迭代屏幕上

對象閃爍開啓和關閉。當它們周圍的物體被破壞時(即在代碼中被擦除)時,通常會發生這種情況。起初我以爲是屏幕閃爍,但現在我意識到我認爲我的迭代函數的邏輯可能會導致問題。

這裏有兩種功能。第一個檢測與塊的子彈碰撞。如果子彈擊中一個塊,該塊將被銷燬。

// Edit: WRONG WAY TO ITERATE THROUGH LIST 
void DetectBulletCollisions() 
{ 
    std::list<Bullet>::iterator bullet = game::player_bullets.begin(); 
    for (; bullet != game::player_bullets.end(); ++bullet) 
    { 
     if (bullet->IsOnScreen()) 
     { 
      bullet->DetectBlockCollision(game::blocks); 
     } 
     else // Remove bullet from list 
     { 
      bullet = --game::player_bullets.erase(bullet); 
     } 
    } 
} 

該函數移動閃爍的塊。

// Edit: RIGHT WAY TO ITERATE THROUGH LIST 
void MoveBlocks(const int delta_ticks) 
{ 
    // Blocks on screen 
    std::list<Block>::iterator block = game::blocks.begin(); 

    while (block != game::blocks.end()) // Loop through blocks 
    { 
     block->Show(); // Show block 
     if (!block->IsDestroyed()) // If block hasn't been destroyed 
     { 
      block->Move(delta_ticks); // Move block 
      ++block; // Increment iterator 
     } 
     else // Block has been destroyed, remove it from list. 
     { 
      block = game::blocks.erase(block); 
     } 
    } 
} 

這些循環的邏輯有什麼問題嗎?值得注意的是第二個?看起來,當一個塊被破壞時,其周圍的其他人閃爍開關(它不一致,但可能只是幀速率)。我不確定在每次擦除後重新排列元素的列表是否會成爲問題。每個塊都有座標,所以它們在列表中的位置並不重要。

如果需要更多的信息,我很樂意給它。我只是想知道在編寫這些循環時我的邏輯是錯誤的,還是我應該採取不同的方法。我選擇列表是因爲它們是用於刪除元素的最有效的STL容器。

回答

1

在這兩個循環,當你刪除一個元素,你的erase的返回值分配給循環迭代。根據cplusplus.com,list::erase返回元素被擦除的元素。因此,如果我沒有弄錯,擦除發生時代碼將總是跳過子彈或塊。這有什麼關係嗎?

+0

我會考慮這個了。 – trikker 2009-11-01 02:40:09

+0

是的,這是確切的問題。我刪除了元素,並將其賦值給迭代器。非常感謝! – trikker 2009-11-01 02:43:06

+0

太棒了! :)你也可以將增量移動到循環體中,這樣你就不會被迫做稍微多毛的遞減。 – henle 2009-11-01 02:48:52

0

無法使用,你在後臺緩存工作,所有這些操作,一旦它完成你換出來與當前的前一個,這樣所有的變化都在這一次做將消除雙緩衝技術這些閃爍,而你通過列表​​。

+0

這就是我總是這樣做的。我將所有內容都應用到緩衝區,然後一旦循環結束,我用該緩衝區更新屏幕,如果這就是你的意思。那麼顯然我清除緩衝區並重做這個過程。 – trikker 2009-11-01 02:38:52

0

您的解決方案仍然是錯誤的。如果你抹掉第一個項目會怎麼樣?您不允許將迭代器遞減到容器的開始處。

一個典型的「擦除,而迭代」循環如下所示:

void DetectBulletCollisions() 
{ 
    std::list<Bullet>::iterator bullet = game::player_bullets.begin(); 
    while (bullet != game::player_bullets.end()) //NB! No incrementing here 
    { 
     if (bullet->IsOnScreen()) 
     { 
      bullet->DetectBlockCollision(game::blocks); 
      ++bullet; //Only increment if not erased 
     } 
     else // Remove bullet from list 
     { 
      bullet = game::player_bullets.erase(bullet); //iterator "incremented" by erase 
     } 
    } 
} 
+0

非常有幫助,謝謝。出於某種原因,我陷入了循環的思維模式。 – trikker 2009-11-01 16:18:09