2011-06-22 136 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