2013-12-10 2 views
0

У меня возникли некоторые проблемы, связанные с воссоединением тел. Кажется, что создает проблемы в управлении памятью, когда я прикрепляю к одному телу несколько приборов. Это происходит во время столкновений, поэтому работа с XCode я получаю следующее сообщение об ошибке:Корпуса для родительских ящиков2D

*** error for object 0xf572ef0: incorrect checksum for freed object - object was probably modified after being freed. 
*** set a breakpoint in malloc_error_break to debug 

Это не происходит, когда тела имеют один прибор.

То, что я пытаюсь достичь, это, например, если персонаж поднимает элемент, преобразования становятся дочерними для родителя. Таким образом, мы получим:

Parent_R + Child_R 
Parent_P + Child_P 

Поскольку я нахожусь в контексте физического движка, я бы предположить, что есть способ, чтобы создать родительские/дочерние отношения между объектами. Я мог бы просто отделить объект (скажем, тот, который ранее падал) от мира физики, и рассматривать его как объект игры с чистым спрайтом. Это включало в себя довольно много назад и вперед (например, воссоздание светильника/тела при возвращении в мир физики). Вот мой код:

void GameObject::AttatchToBody(GameObject& obj1, GameObject& obj2, b2World& world) 
{ 
    b2PolygonShape boxShape; 
    boxShape.SetAsBox(obj2.width, obj2.height); 

    b2FixtureDef boxFixtureDef; 
    boxFixtureDef.restitution = 0.2f; 
    boxFixtureDef.friction = 0.3f; 
    boxFixtureDef.shape = &boxShape; 
    boxFixtureDef.density = 1/(obj2.width + obj2.height); 

    obj2.fixture = obj1.body->CreateFixture(&boxFixtureDef); 
    obj2.body = obj1.body; 

} 

Любая помощь очень ценится!

ответ

0

Я не видел отношений с родителями в Box2d, кроме отношений body/fixture.

Мне кажется, что у вас есть obj1 и obj2, ссылающиеся на тот же объект с выделенной памятью Box2d (тело). Например, если вы удаляете obj1, вы, вероятно, удаляете прикрепленное к нему тело (делая что-то вроде world-> DestroyBody (...)). В следующем обновлении box2d вы ссылаетесь на объект, который вы не выделили, и сказали, что он уничтожен (в систему Box2d). Возможно, это проблема?

Я также вижу, что вы делитесь креплением между объектами obj2 и obj1. Что произойдет, когда obj1 будет восстановлен системой box2d (т. Е. Вы уничтожили тело obj1)? Это не кажется правильным ... система не знает о ваших родительских отношениях, а C++ не имеет встроенной в нее системы подсчета ссылок. Это также может быть проблемой.

Если ваша цель состоит в том, чтобы один объект GameObject управлял несколькими телами (т. Е. Рой чего-то), то пусть единственный GameObject поддерживает список нескольких тел и управляет ими всеми.

Однако, я считаю, вы хотите, чтобы все они двигались так, как если бы они были прикреплены. Насколько я знаю, существует всего два способа заставить два тела вести себя как «один».

Вариант № 1: Первый - использовать соединение между ними. Я сделал это в игре, в которой у меня был космический корабль, который врезался в оружие, чтобы забрать его. Когда корабль сделал это, я создал призматический сустав, чтобы ружье показалось «встать» перед кораблем. Это код, который я использовал для его подключения:

void BulletLauncherEntity::CreateJointConnection() 
{ 
    Entity* owner = GetOwner(); 
    Body& ownerBody = owner->GetBody(); 

    // We put the position of this at the tip of the 
    // owner. 
    float32 launcherDist = 0.5*(owner->GetScale())*Constants::SCALE_TO_METERS_RATIO(); 
    float32 launcherSize = 0.5*GetScale()*Constants::SCALE_TO_METERS_RATIO(); 
    // Joint along axis of entity 
    b2PrismaticJointDef jointDef; 
    // Note that the "Initialize" function in the 
    // jointDef did not really give us what we wanted. 
    jointDef.bodyA = &ownerBody; 
    jointDef.bodyB = &GetBody(); 
    jointDef.localAnchorA = Vec2(launcherDist-launcherSize,0); 
    jointDef.localAnchorB = Vec2::Zero(); 
    jointDef.localAxisA = Vec2(1,0); 
    jointDef.referenceAngle = 0; 

    jointDef.lowerTranslation = -launcherDist; 
    jointDef.upperTranslation = 0.5*GetScale()*Constants::SCALE_TO_METERS_RATIO(); 
    jointDef.enableLimit = true; 
    jointDef.maxMotorForce = 2.0; 
    jointDef.motorSpeed = 0.25; 
    jointDef.enableMotor = true; 
    jointDef.collideConnected = false; 
    ownerBody.GetWorld()->CreateJoint(&jointDef); 
} 

Вы также можете использовать сварное соединение.

HOWEVER, согласно руководству, используя сварные швы, не создает «жесткое» соединение. Он имеет некоторую мягкость, потому что при столкновении необходимо соблюдать ограничения.

из руководства:

сварного соединения попытки ограничить все относительное движение между двумя телами. См. Cantilever.h в испытательном стенде, чтобы увидеть, как ведет себя сварной шов . Заманчиво использовать сварное соединение для определения разрушаемых конструкций . Тем не менее, решатель Box2D является итеративным, поэтому суставы представляют собой бит . Поэтому цепи тел, соединенные сварными швами, будут изгибаться. Вместо этого лучше создать обрывающие тела, начиная с одного тела с несколькими светильниками. Когда тело ломается, вы можете уничтожить светильник и воссоздать его на новом корпусе. См. Пример Breakable в тестовом стенде .

Я не пробовал проверить это или посмотреть, как «жесткие» другие типы соединений. Когда я использовал призматический сустав, мне показалось, что он довольно твердый. Но во время столкновений он иногда «толкается».

Вариант № 2: Прикрепите его как приспособление непосредственно к корпусу. Я думаю, вам нужно будет уничтожить старое тело и создать для него новый набор светильников.

Было ли это полезно?

Смежные вопросы