2013-05-14 2 views
0

В моем коде я хотел бы уничтожить одно из двух контактирующих тел. В beginContact следующий метод в CCPhysicsSprite называется:спасательные контактные тела подлежат уничтожению

-(void)contactMade:(CCPhysicsSprite*)contactedSprite { 
int spriteTag1 = self.tag; 
int spriteTag2 = contactedSprite.tag; 

if (((spriteTag1 == 3) && (spriteTag2 == 4)) || ((spriteTag1 == 4) && (spriteTag2 == 3)) { 

    CCPhysicsSprite* heroSprite = (CCPhysicsSprite*)[self getChildByTag:4]; 
    b2World* world; 

    world->DestroyBody(heroSprite.b2Body); 
    heroSprite.b2Body = NULL; 
    [heroSprite.parent removeChild:heroSprite]; 
} 

Я получаю SIGABRT сигнал, указывающий на

b2Assert(m_bodyCount > 0); 

После поиска по этому вопросу. Я прочитал, что контактное тело должно быть сохранено и уничтожено после отметки времени. Как я могу это сделать, учитывая, что я установил условия контакта в CCPhyscisSprite.

+0

Вам необходимо добавить уничтоженные тела к массиву, предпочтительно в классе, который запускает шаг в box2d. После шага уничтожьте все тела в массиве и опустошите его. Совет. В http://www.koboldtouch.com вы можете уничтожить такие тела непосредственно в методах обратного вызова контакта. – LearnCocos2D

ответ

1

К вашему физическому объекту можно добавить флаг (например: isDead ...), а в событии столкновения просто измените значение этого флага на значение ИСТИНА.

-(void) CollisionBegin:(b2Fixture*)target With:(b2Fixture*) source 
{  
    if (target->GetBody()->GetType() == b2_dynamicBody) 
    { 
     yourCustomClass *temp = (yourCustomClass *)target->GetBody()->GetUserData(); 
     temp->isDead = true ; 
    } 
} 

Затем в функции обновления после шага получить весь физический мир объект и найти, что конкретный объект с помощью флага (здесь: isDead), и уничтожить это.

-(void) update: (ccTime) dt 
{ 

    int32 velocityIterations = 8; 
    int32 positionIterations = 3; 

    world->Step(dt, velocityIterations, positionIterations); 

    // remove your box2d object here , after step function 

    for (b2Body *b = world->GetBodyList(); b;) 
    { 
     b2Body *baba = b->GetNext(); 
     if (b->GetUserData() != NULL && b->GetType() == b2_dynamicBody) 
     { 
      yourCustomClass *t = (yourCustomClass *)b->GetUserData(); 
      if (t->isDead) 
      { 
       world->DestroyBody(b); // remove physical body 
       [self removeChild:t];  // remove node from super layer 
      } 
     } 
     b = baba ; 
    } 
} 
+1

Это может стать немного медленным, если в мире существует большое количество тел, потому что он проверяет каждый временной шаг, и большую часть времени он не найдет никаких тел для уничтожения. Добавление объекта в список (std :: set лучше всего), а затем уничтожение всего, что находится в списке, после того, как временной шаг более эффективен для больших миров. – iforce2d