2011-06-22 140 views
2
"Assertion failed: (m_bodyCount < m_bodyCapacity), function Add, file libs/Box2D/Dynamics/b2Island.h, line 65." 

这就是它在控制台中的崩溃。当我试图摧毁一个b2Body时,游戏崩溃,我该怎么办?

[self removeChild:(CCSprite*)body->GetUserData() cleanup:YES]; 

body->SetTransform(b2Vec2(30, 30), 0); //moving the body out of the scene so it doesnt collide anymore! 

world->DestroyBody(body); 

我想我做了正确的东西..

@property (nonatomic, assign) b2Body *body; 

这是我如何“让”的属性

我不明白为什么它不工作,“身体”是正确的指针,因为我可以从身体的UserData中检索信息,比如设置在身体的肌酸中的标签,所以这不应该是一个问题。有人知道我的代码有什么问题吗?

谢谢。

编辑在:

-(void) tick: (ccTime) dt //Main loop 
{ 

if (ballFired) { 
    Magnet *aMagnet = [magnetArray objectAtIndex:0]; 

    world->DestroyBody(aMagnet.body); //It crashes here! 
} 



int32 velocityIterations = 8; 
int32 positionIterations = 1; 

// Instruct the world to perform a single step of simulation. It is 
// generally best to keep the time step and iterations fixed. 
world->Step(dt, velocityIterations, positionIterations); 


//Iterate over the bodies in the physics world 
for (b = world->GetBodyList(); b; b = b->GetNext()) 
{ 
    if (b->GetUserData() != NULL) { 
     //Synchronize the AtlasSprites position and rotation with the corresponding body 
     CCSprite *myActor = (CCSprite*)b->GetUserData(); 
     myActor.position = CGPointMake(b->GetPosition().x * PTM_RATIO, b>GetPosition().y * PTM_RATIO); 
     myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()); 
    } 
    } 




} 

心不是这个世界外面解决吗?

编辑2:

 ContactListener::ContactListener(){}; 

     void ContactListener::BeginContact(b2Contact* contact) 
     { 
     // Box2d objects that collided 
     b2Fixture* fixtureA = contact->GetFixtureA(); 


     b2Fixture* fixtureB = contact->GetFixtureB(); 
     CCSprite* actorA = (CCSprite*) fixtureA->GetBody()->GetUserData(); 
     CCSprite* actorB = (CCSprite*) fixtureB->GetBody()->GetUserData(); 



     if(actorA == nil || actorB == nil) return; 

    b2WorldManifold* worldManifold = new b2WorldManifold(); 
    contact->GetWorldManifold(worldManifold); 


     Kollisjon *kollisjon = [Kollisjon sharedKollisjon]; 

    if (actorA.tag == 1) { 

    NSLog(@"OK1"); 

    kollisjon.kollidertBody = fixtureB->GetBody(); 

    kollisjon.world->DestroyBody(kollisjon.kollidertBody); //Isnt this ok? 

    } 

    else if (actorB.tag == 1) { 

     NSLog(@"OK2"); 


     kollisjon.kollidertBody = fixtureA->GetBody(); 

     kollisjon.world->DestroyBody(kollisjon.kollidertBody); //Isnt this ok? 

    } 


    } 

这难道不是时间步之外?请帮我在这里...

谢谢

+0

断言正在触发,因为有更多的身体比能力!这就是我对你的所有,因为我对这个API没有经验。 – Joe

+0

你是否正在尝试在时间步或中途做到这一点?使用线程也许?我的猜测是你正在重写引擎内部的东西,看看b2World :: Solve,在开始的时候,岛上的最大人体数量被设置为世界中的身体数量,因为评论说'最糟糕的案件'。在接下来的主循环('构建并模拟所有唤醒的岛屿')的某个地方,循环变量被弄乱是我能看到的唯一的事情。不要在碰撞回调期间改变世界,如果这就是你正在做的事情。 – iforce2d

+0

如果在我检测到与ContactListener发生碰撞后摧毁身体就有资格作为“在回调之后改变世界”,那么是的,我正在这样做。 – JulenissensHjelper

回答

3

您必须扫描通讯录,所有联系人存储在数组中,再经过所有联系人都被检查,删除你的身体。在你的方法

std::vector<MyContact>::iterator pos; 
for(pos = _contactListener->_contacts.begin(); 
    pos != _contactListener->_contacts.end(); ++pos) 
{ 
    MyContact contact = *pos; 

    b2Body *bodyA = contact.fixtureA->GetBody(); 
    b2Body *bodyB = contact.fixtureB->GetBody(); 

    // Rocket explosion rect 
    if(bodyA->GetUserData() == NULL) 
    { 
     NSLog(@"NULL collision detected. (BODY A)"); 

     hasDoneRocketCollisions = YES; 

     CCSprite *sprite = (CCSprite*) bodyB->GetUserData(); 

     if(sprite.visible == NO) continue; 

     if(sprite.tag >= 200 && sprite.tag < 300) 
     { 
      index = sprite.tag - 200; 
      if([spriteTracker containsObject:sprite]) continue; 
      [spriteTracker addObject:sprite]; 
      bodiesToKill[counter] = bodyB; 
      [enemyChargerIsAlive replaceObjectAtIndex:(int)(sprite.tag-200) withObject:[NSNumber numberWithInt:0]]; 
      [ParticleController spawnExplosion:sprite.position inParent:currentDefaultNode]; 
     } 
     else if(sprite.tag >= 300 && sprite.tag < 400) 
     { 
      index = sprite.tag - 300; 
      if([spriteTracker containsObject:sprite]) continue; 
      [spriteTracker addObject:sprite]; 
      bodiesToKill[counter] = bodyB; 
      [enemyShooterIsAlive replaceObjectAtIndex:(int)(sprite.tag-300) withObject:[NSNumber numberWithInt:0]]; 
      [ParticleController spawnExplosion:sprite.position inParent:currentDefaultNode]; 
      counter++; 
     } 
    } 
} 

后来所有的联系人都被检查后:

检查触点

b2Body *dyingBody; 

for(int i = 0; i < counter; i++) 
{ 
    CCSprite *dyingSprite; 
    dyingSprite = [spriteTracker objectAtIndex:i]; 
    dyingSprite.visible = NO; 

    // Is player projectile 
    if(dyingSprite.tag >= 100 && dyingSprite.tag < 200) 
    { 
     CCParticleSystemQuad *dyingParticle; 
     dyingParticle = [particlesToKill objectAtIndex:particleIndex]; 
     particleIndex++; 
     [dyingParticle stopSystem]; 

     dyingBody = bodiesToKill[i]; 
     dyingBody->SetActive(false); 

     [ParticleController spawnExplosion:dyingSprite.position inParent:currentDefaultNode]; 
     [AudioController playExplosion]; 

     dyingSprite.visible = NO; 

     if([_player currentShotType] == 1) 
     { 
      rocketHitBody->SetTransform(b2Vec2(dyingSprite.position.x/PTM_RATIO, dyingSprite.position.y/PTM_RATIO), 0.0); 
      rocketHitBody->SetActive(true); 
     } 
    } 
} 

注意到,这些代码只是随机块我有复制和粘贴。他们仅仅是一个例子,如果你试图按照确切的说明阅读它们,可能只会让你感到困惑。

这里的要点是:在步骤或联系人侦听器正在访问身体时,无法删除身体。使用联系人侦听器完成,然后删除您的身体。

+0

查看原帖的最新编辑..那里有什么问题? – JulenissensHjelper

+1

问题是整个ContactListener :: BeginContact是从世界的Step例程中调用的。你看过我网站上的图表吗?除此之外,我无法对此加以解释。 Aaron代码的第一部分放在联系人监听器中。第二部分在世界的步骤结束后进入主游戏循环。 – iforce2d

+0

我的问题是,我在任何地方把“DestroyBody”放在主循环内崩溃。如果我用一个按钮调用它,它可以完美地工作并移除球碰撞或与之前相撞的身体。我应该怎么做呢? – JulenissensHjelper