2009-11-01 50 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