1

我有一张网和一些昆虫,我正在投掷网并与昆虫进行碰撞检测并摧毁它们。我使用 bod2d 进行碰撞检测。

世界方法

-(void)createWorld
{

 // Define the gravity vector.
    b2Vec2 b_gravity;
    b_gravity.Set(0.0f, -9.8f);

 // Do we want to let bodies sleep?
 // This will speed up the physics simulation
    bool doSleep = true;

 // Construct a world object, which will hold and simulate the rigid bodies.
    world = new b2World(b_gravity);
    world->SetAllowSleeping(doSleep);

    world->SetContinuousPhysics(true);

}

创建网站

-(void) createWeb
{
    freeBodySprite = [CCSprite spriteWithFile:@"web1.png"];
        [self addChild:freeBodySprite z:2 tag:TAG_WEB];

    CGPoint startPos = CGPointMake(100, 320/1.25);

    bodyDef.type = b2_staticBody;
    bodyDef.position = [self toMeters:startPos];
    bodyDef.userData = freeBodySprite;

    float radiusInMeters = ((freeBodySprite.contentSize.width * freeBodySprite.scale/PTM_RATIO) * 1.0f);
    shape.m_radius = radiusInMeters;

    fixtureDef.shape = &shape;
    fixtureDef.density = 0.01f;
    fixtureDef.friction = 0.1f;
    fixtureDef.restitution = 0.1f;

    circularObstacleBody = world->CreateBody(&bodyDef);
    stoneFixture = circularObstacleBody->CreateFixture(&fixtureDef);
        freeBody = circularObstacleBody;
}

我用 spritesheet 创建了我的昆虫动画,然后为那个 Sprite 创建了 b2body

-(b2Body *) createMovingBoxObstacle
{


    //set this to avoid updating this object in the tick schedule
        _ants.userData = (void *)YES;

    b2BodyDef bodyDef_Ant;
    bodyDef_Ant.type = b2_dynamicBody;
    CGPoint startPos = ccp(520,winSize.height/7.6);
    bodyDef_Ant.position = [self toMeters:startPos];
    bodyDef_Ant.userData = _ants;

    b2PolygonShape dynamicBox;
    float tileWidth = ((_ants.contentSize.width * _ants.scale/PTM_RATIO) * 0.5f);
    float tileHeight = ((_ants.contentSize.height * _ants.scale/PTM_RATIO) * 0.5f);
    dynamicBox.SetAsBox(tileWidth, tileHeight);

    b2FixtureDef fixtureDef_Ant;
    fixtureDef_Ant.shape = &dynamicBox;
    fixtureDef_Ant.friction = 0.7;
    fixtureDef_Ant.density = 0.1f;
    fixtureDef_Ant.restitution = 0.7;


    staticBody = world->CreateBody(&bodyDef_Ant);
    staticBody->CreateFixture(&fixtureDef_Ant);

       VAMovingObstacle* moveableObject = [[VAMovingObstacle alloc] init];
       moveableObject.startPoint = ccp(520,winSize.height/7.6);
       moveableObject.endPoint = ccp(-50,winSize.height/7.6);
       moveableObject.transitionTime = 20.0;
       moveableObject.breakTime = 1.0;

    moveableObject.obstacleSprite = _ants;
    moveableObject.physicalBody = staticBody;
    [moveableObject startMovement];

    if (!movingObstacles) {
        movingObstacles = [[NSMutableArray alloc] init];
    }
    [movingObstacles addObject:moveableObject];
    [moveableObject release];
    return staticBody;
}

VAMovingObstacle 是一个帮助 sprite 与 b2body 一起从左向右移动的类(运行动作)

这是我的联系人列表器 EndContact 方法

void ContactListener::EndContact(b2Contact* contact)
{
    b2Body* bodyA = contact->GetFixtureA()->GetBody();
    b2Body* bodyB = contact->GetFixtureB()->GetBody();

    if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL) {
        CCSprite *spriteA = (CCSprite *) bodyA->GetUserData();
        CCSprite *spriteB = (CCSprite *) bodyB->GetUserData();


        if (spriteA.tag == TAG_WEB && spriteB.tag >= TAG_ANT) {

        }

        else if (spriteA.tag >= TAG_ANT && spriteB.tag == TAG_WEB) {

            [spriteA removeFromParentAndCleanup:YES];
            [[HelloWorldLayer sharedLevel] WebCollisionWithInsect:bodyA];
        }
    }
}

当发生碰撞时 EndContact 方法调用 WebCollisionWithInsect:bodyA

-(void) WebCollisionWithInsect:(b2Body*) bodyT{
            world->DestroyBody(bodyT);
}

在 world->DestroyBody(bodyT) 行它给出一个错误

断言失败:(IsLocked() == false),函数 DestroyBody,文件 /Users/libs/Box2D/Dynamics/b2World.cpp,第 134 行。

任何想法我做错了什么。?

编辑 我在 EndContact 添加了这一行

destroyCollisionDetectionBody = objBody;
didInsectCollideWithWeb = YES;

保持我想破坏的身体的参考。现在我可以在勾选方法中销毁我的身体,如果检查在勾选方法中添加了这些行

if(didInsectCollideWithWeb)
    {
        [self unschedule:@selector(tick:)];
        [freeBodySprite removeFromParentAndCleanup:YES]; // this is my web
        world->DestroyBody(destroyCollisionDetectionBody);
        world->DestroyBody(freeBody);
        [self createWeb];
        [self schedule:@selector(tick:)];
        didInsectCollideWithWeb = NO;

    }

但现在的问题是,当我破坏我的网络时,即 freebody。我无法重新创建它。正如我之前通过调用 [self createWeb] 所做的那样;

4

1 回答 1

1

您正在尝试box2d在模拟阶段(EndContact在该阶段称为)使用对象时销毁它。模拟阶段是调用世界step方法时执行的阶段。

因此,您应该做的是保留对要删除的主体对象的引用,并在 box2d 模拟阶段之后(在step方法返回之后)WebCollisionWithInsect使用所需的主体执行

于 2013-08-27T12:18:44.200 回答