0
votes

I am having some issues parenting together bodies. It seems to create issues in memory management when I attach more than one fixture to a body. This happens during collisions, so working with XCode I get the following error message:

 *** 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

This does not happens when bodies have a single fixture.

What I am trying to achieve, is for instance if a character picks up an item, the transformations become childed to the parent. So, we would get:

 Parent_R + Child_R
 Parent_P + Child_P

Since I am in the context of a physics engine, I would assume there is a way to create a parent/child relationship between objects. I could simply detach the object (say one that was previously falling) from the the physics world and treat it as a pure sprite game object. This involved quite a bit of back and forth (such as recreating the fixture/body when put back into the physics world). Here is my code:

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;

}

Any helps is greatly appreciated!

1

1 Answers

1
votes

I have not seen any parenting relationships in Box2d other than the body/fixture relationship.

It looks to me like you have obj1 and obj2 referencing the same Box2d-memory-allocated object (the body). When you delete obj1, for example, you probably delete the body attached to it (by doing something like world->DestroyBody(...)). The next box2d update, you are referencing an object that you did not allocate and have told to be destroyed (to the Box2d system). Is this possibly the problem?

I also see that you are sharing a fixture between obj2 and obj1. What happens when obj1 gets reclaimed by the box2d system (i.e. you destroyed obj1's body)? This does not seem correct...the system has no knowledge of your parenting relationships and C++ does not have a reference counting system built into it. This may also be the problem.

If your goal is to have a single GameObject manage multiple bodies (i.e. a swarm of something), then let the single GameObject maintain a list of multiple bodies and manage them all.

However, I believe you want them all to move as if attached. As far as I know, there are only two ways to make two bodies behave as "one".

Option #1: The first is to use a joint between them. I did this in a game where I had a space ship bump into a weapon to pick it up. When the ship did, I created a prismatic joint so that the gun would appear to "mount" in front of the ship. This is the code I used to attach it:

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);
}

You could also use a weld joint.

HOWEVER, per the manual, using weld joints is will not create a "stiff" connection. It has some softness because constraints need to be satisfied during collisions.

FROM THE MANUAL:

The weld joint attempts to constrain all relative motion between two bodies. See the Cantilever.h in the testbed to see how the weld joint behaves. It is tempting to use the weld joint to define breakable structures. However, the Box2D solver is iterative so the joints are a bit soft. So chains of bodies connected by weld joints will flex. Instead it is better to create breakable bodies starting with a single body with multiple fixtures. When the body breaks, you can destroy a fixture and recreate it on a new body. See the Breakable example in the testbed.

I haven't tried to test this, or see how "stiff" other joint types are. When I used a prismatic joint, it seemed pretty solid to me. But it does get "pushed in" occasionally during collisions.

Option #2: Attach it as a fixture directly to the body. I think you will have to create destroy the old body and create a new set of fixtures just for this.

Was this helpful?