我正在使用cocos2d和box2d,并且我有多达5个b2bodies需要同时销毁。它们都被添加到设置的std::set<b2Body*>row1RedArray;中,并由row1RedArray.insert(spriteBody);添加,并且我已经通过迭代删除了数组中的所有项目,但是删除它们后,当我触摸屏幕时,我的程序就会崩溃。我是否正确销毁了b2Bodies?

//if that array is empty, then remove all objects from this array (row4)

if ((row4BlueArray.count == 0) && (row4.count >> 0) && (row4Removed == NO)) {
    std::set<b2Body *>::iterator pos04;
    for(pos04 = row4RedArray.begin(); pos04 != row4RedArray.end(); ++pos04) {
        b2Body *rowBody = *pos04;
        if (rowBody->GetUserData() != NULL)
        {
            for (CCSprite* sprite4 in row4) {
                [self removeChild:sprite4 cleanup:YES];
            }
            //Adding the b2Body to the toDelete Set and then removing it from the set of b2Bodies
            toDestroy.insert(rowBody);
            row4RedArray.erase(rowBody);
            row4Removed = YES;
        }
    }
}
std::set<b2Body *>::iterator pos2;
for(pos2 = toDestroy.begin(); pos2 != toDestroy.end(); ++pos2) {
    b2Body *body = *pos2;
    if (body->GetUserData() != NULL)
    {
       //Then removing the b2Body completely (this is all at the end of the tick method)
        _world->DestroyBody(body);
    }
}

最佳答案

您应该通过world-> DestroyBody()销毁尸体,不要以其他任何方式处置它们。没有办法同时删除它们,但是必须在box2d world步骤之外完成对主体的删除。这意味着,如果您遍历列表并销毁您想要的实体,那么下次box2d世界将被更新时,看起来好像这些实体已被同时丢弃。

在C++方面,可能会导致不确定行为的问题很少。其中之一是在对其进行迭代时将其从容器中移除。一旦在任何容器上使用了擦除功能,该容器的迭代器就会失效。这比我建议的代码少得多:

std::vector<b2Body *> toDestroy;
if ((row4BlueArray.count == 0) && (row4.count >> 0) && (row4Removed == NO))
{
    for(std::set<b2Body *>::iterator pos04 = row4RedArray.begin(); pos04 != row4RedArray.end(); ++pos04)
    {
        b2Body *rowBody = *pos04;
        if (rowBody->GetUserData() != NULL)
        {
            toDestroy.push_back(rowBody);
            row4Removed = YES;
        }
    }

    for (CCSprite* sprite4 in row4)
    {
        [self removeChild:sprite4 cleanup:YES];
    }
}

for( std::set<b2Body *>::iterator pos2 = toDestroy.begin(); pos2 != toDestroy.end(); ++pos2)
{
    row4RedArray.erase( (*body) );
    _world->DestroyBody( (*body) );
}
//I have put the toDestroy vector in as a local variable so this is not needed, but if you
//are having it as a member variable etc. you need to clear it before you are going to use
//it in next loop, otherwise it will try to delete the same elements  a second time.
toDestroy.clear();

我不确定为什么您使用std::set来存储b2Body指针。集通常比任何无序容器(例如 vector )慢。我还从第二个for循环中删除了if(rowBody-> GetUserData()!= NULL),因为在将对象添加到toDestroy vector 中时进行了检查,可以假定这些对象已通过删除条件。

您还可以在遍历row4容器时从场景中删除精灵(我从代码中假定它是某种容器),但是您永远不会清除它。删除该容器中的所有元素后,这样做可能是明智的选择,这在我看来是在这里发生。您还尝试多次删除这些精灵,在for循环内使用“for(第4行中的CCSprite * sprite4)”对这些主体进行迭代,因此,如果有一个以上的主体通过了要删除的条件,则您将再次遍历row4以删除精灵。

我不确定为什么要根据“if(rowBody-> GetUserData()!= NULL)条件”删除实体,但这可能是您游戏中需要的东西,从提供的代码中看不出来。

关于c++ - Box2d销毁集合中的所有对象,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18024811/

10-15 22:56