迭代列表的逻辑。元素“闪烁”

时间:2009-11-01 01:49:15

标签: c++ list

[求助]:应用正确的列表迭代程序修复问题。 (如下所示)

我目前有一个程序,如果符合某些条件,列表中的元素将被迭代并删除。由于程序的性质,这可以在视觉上看到。

正在迭代的屏幕上的对象有时会打开和关闭闪烁。这通常发生在它们周围的物体被破坏(即在代码中被擦除)时。起初我以为它是屏幕闪烁,但现在我意识到我认为我的迭代函数的逻辑可能导致问题。

这是两个功能。第一个检测到与块的子弹碰撞。如果子弹击中一个块,该块就会被破坏。

// 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容器。

3 个答案:

答案 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
        }
    }
}