Уничтожить тело box2d в cocos2d
У меня есть паутина и некоторые насекомые, которых я закидываю паутиной и обнаруживаю столкновение с насекомыми и уничтожаю их. я использовал 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, а затем создал b2body для этого Sprite.
-(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 - это класс, который помогает спрайту вместе с b2body перемещаться слева направо (runaction)
Вот мой метод списка контактов 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;
}
Но теперь проблема в том, что когда я разрушаю свою сеть, т.е. свободную личность. я не могу воссоздать это. как я делал это раньше, вызывая [self createWeb];
1 ответ
Вы пытаетесь уничтожить box2d
объект во время его использования на этапе моделирования (как EndContact
называется на этом этапе). Этап симуляции - это тот, который выполняется, когда вы называете мир step
метод.
Так что вам следует сохранить ссылку на объект body, который вы хотите удалить, и после фазы моделирования box2d (после step
метод возвращает) выполнить WebCollisionWithInsect
с желаемым телом