[求助]:应用正确的列表迭代程序修复问题。 (如下所示)
我目前有一个程序,如果符合某些条件,列表中的元素将被迭代并删除。由于程序的性质,这可以在视觉上看到。
正在迭代的屏幕上的对象有时会打开和关闭闪烁。这通常发生在它们周围的物体被破坏(即在代码中被擦除)时。起初我以为它是屏幕闪烁,但现在我意识到我认为我的迭代函数的逻辑可能导致问题。
这是两个功能。第一个检测到与块的子弹碰撞。如果子弹击中一个块,该块就会被破坏。
// 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容器。
答案 0 :(得分:1)
在两个循环中,擦除元素时,将erase
的返回值赋给循环迭代器。根据cplusplus.com,list::erase
在删除元素后返回元素。因此,如果我没有弄错的话,当擦除发生时,代码将始终跳过子弹或块。这与它有什么关系吗?
答案 1 :(得分:0)
你不能使用双缓冲技术来处理所有这些操作的后台缓冲区,一旦完成,你将它与当前前一个交换出来,所以所有的更改都会立即完成,这将删除这些当你浏览列表时闪烁。
答案 2 :(得分: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
}
}
}