【问题标题】:Collision of two sprites in separate lists单独列表中两个精灵的碰撞
【发布时间】:2023-03-21 07:38:01
【问题描述】:

我现在尝试在 SFML 中编写一个自上而下的射击游戏,但遇到了问题。我对 C++ 和一般编程很陌生,所以请原谅凌乱的代码和/或过于复杂的解决方案。

我有两个std::lists,一个包含随机生成的敌人,另一个包含我发射的子弹。当子弹击中敌人时,他们都应该被清除,但它不起作用。

这是我的代码的问题部分:

for(MonsterIt = MonsterList.begin(); MonsterIt != MonsterList.end(); MonsterIt++)
{

    //Here would be Monster-Movement

    //Collision Monster-Player (MonsterIt = iterator of MonsterList)
    if ((MonsterIt -> getPosition().x + 25) >= PlayerX - 25 && 
        (MonsterIt -> getPosition().x - 25) <= PlayerX + 25 &&
        (MonsterIt -> getPosition().y + 25) >= PlayerY - 25 && 
        (MonsterIt -> getPosition().y - 25) <= PlayerY + 25   )
    {
        MonsterList.erase(MonsterIt);
        break;              
    }


        window.draw(*MonsterIt);
}

这就是我在怪物和玩家之间进行碰撞的方式。效果很好,所以我对 Monsters 和 Lasers 进行了同样的尝试:

for(LaserIt = LaserList.begin(); LaserIt != LaserList.end(); LaserIt++)
{

    //Here would be "Laser-Movement"

    //Collision-Laser                               // Doesn't work
    if ((MonsterIt -> getPosition().x + 25) >=      //
        (LaserIt   -> getPosition().x - 7) &&       //
        (MonsterIt -> getPosition().x - 25) <=      //
        (LaserIt   -> getPosition().x + 7) &&       //
        (MonsterIt -> getPosition().y + 25) >=      //
        (LaserIt   -> getPosition().y - 7) &&       //
        (MonsterIt -> getPosition().y - 25) <=      //
        (LaserIt   -> getPosition().x + 7))         //
    {                                               //
        MonsterList.erase(MonsterIt);               //
                                                    //
        LaserList.erase(LaserIt);                   //
                                                    //
        break;                                      //
    }                                               //  

    window.draw(*LaserIt);
}

当我输入我标记的代码部分(右侧带有 //)时,我在拍摄时立即调试时收到“列表迭代器不可取消引用”错误。当我删掉所说的代码时,它运行良好(我可以射击,走进怪物并且它们消失等等)。因此,我猜我的其余代码都可以正常工作。

那么,不同列表的迭代器之间是否可能发生冲突? 如果是这样,我该怎么做?

如果您需要更多信息或代码,请询问。很高兴得到您的帮助...

【问题讨论】:

  • 你怎么知道MonsterIt 是第二个片段中的有效迭代器?
  • 这是我的问题。我想它是无效的,这就是它不起作用的原因。但是我怎样才能在作为 MonsterList 一部分的 Monster 和作为 LaserList 一部分的 Laser-Shot 之间进行碰撞?就像我说的,我对 C++ 很陌生。据我了解,这里的迭代器 MonsterIt 是列表中一个成员的“名称”。这是真的吗?
  • 并非如此。 MonsterIt 是“指向”怪物的变量的名称(MonsterIt 是迭代器,而不是怪物)。
  • MonsterIt 是指向 Monster 的 Memory-adress 还是指向该地址的内容?
  • 如果您需要找到 all 怪物和 all 激光射击之间的碰撞,您可能需要嵌套循环,例如for (MonsterIt = ...) { for (LaserIt = ...) { ... } }。你有这个或类似的结构吗?如果是,问题就出在这里:你擦除MonsterIt,然后继续外循环,即增加擦除的迭代器。您需要重新设计外循环以避免这种情况。首先移动到下一个元素,然后擦除需要的元素。更好的是,学习和使用std::remove_if

标签: c++ collision-detection sfml


【解决方案1】:

您使用的迭代器无效。

您的问题有多种解决方案。第一个:

for(MonsterIt = MonsterList.begin(); MonsterIt != MonsterList.end(); MonsterIt++)
{
    //Here would be Monster-Movement

    //Collision Monster-Player (MonsterIt = iterator of MonsterList)

    // Collision with laser, inside the loop for monsters
    for(LaserIt = LaserList.begin(); LaserIt != LaserList.end(); LaserIt++)
    {
    }

    window.draw(*MonsterIt);
}

这个解决方案并不是真正的 C++ 语言。使用 OOP,您可以拥有更清晰的代码:

class Player
{
    public:
        int X, Y; // for code simplicity on SO.
};
// ...

Player player;
for(MonsterIt = MonsterList.begin(); MonsterIt != MonsterList.end(); MonsterIt++)
{
    MonsterIt->update(player,LaserList);
    if(!MonsterIt->isAlive())
    {
        // Remove monster from list *without* break
    }
}

那么,Monster 是一个类似下面的类: 类怪物 { 布尔活着; 民众: bool isAlive() const { 活着返回; }

        bool collideWithPlayer(Player p) const
        {
            // Returns whether it collide with player
            // ...
        }

        bool collideWithLaser(Laser l) const
        {
            // Returns whether it collide with one laser
            // ...
        }

        bool collideWithLasers(LaserList l) const
        {
            for(LaserIt = LaserList.begin(); LaserIt != LaserList.end(); LaserIt++)
                if(collideWithLaser(*LaserIt))
                    return true;
            return false;
        }


        void update(Player p, LaserList l)
        {
            if(collideWithPlayer(p) || collideWithLasers(l))
                alive = false;
            else
                window.draw(this);
        }
};

【讨论】:

  • 太好了,我会试试的。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多