5

I have a arbitrarily deep tree structure of bodies in box2d. When a parent body collides with anything, it should move its children along. On the other hand, if the child is moved due to a collision, the parent should not be touched. One body can be a parent to one body and a child to another at the same time.

Is there a way to implement this in Box2D? None of the joints seem to be able to represent this, since they're all symmetrical.

Thomas Zoechling
  • 34,177
  • 3
  • 81
  • 112
anlumo
  • 143
  • 2
  • 7
  • Please consider accepting my answer if it answers your question or leave a comment explaining what seems still unanswered. Thank you! – Louis Langholtz Sep 30 '17 at 02:39
  • I'm sorry, but during those 9 months I implemented a different solution that wasn't based on box2d at all any more, so I can't verify whether your solution works, although it sounds promising. – anlumo Oct 12 '17 at 03:21
  • @anlumo what solution did you end up using? – Marc J. Schmidt Aug 18 '22 at 18:57

1 Answers1

2

Yes. Algorithmically speaking, use conceptually nested worlds.

Here's some pseudo code for this. You'll need to fill in details like setting the bodies to be dynamic and what there densities should be. But hopefully the code shows a way to get this done:

extern void render(b2World& world, b2Vec2 position);

b2World world(b2Vec2(0, 0));
b2World subWorld(b2Vec2(0, 0));

b2BodyDef bodyDef;

// Create body outside of "parent".
bodyDef.position = b2Vec2(-15, 14);
b2Body* otherBody = world.CreateBody(&bodyDef);

// Setup "parent" body.
b2Body* parentBody = world.CreateBody(&bodyDef);
b2Vec2 vertices[] = { b2Vec2(10, 10), b2Vec2(-10, 10), b2Vec2(-10, -10), b2Vec2(10, -10) };
b2PolygonShape parentShape;
parentShape.Set(vertices, 4);
b2FixtureDef parentFixtureDef;
parentFixtureDef.shape = &parentShape;
parentBody->CreateFixture(&parentFixtureDef);

// Setup container for bodies "within" parent body...
b2BodyDef childBodyDef;
// set childWorldBody to being static body (all others dynamic)
b2Body* childWorldBody = subWorld.CreateBody(&childBodyDef);
b2ChainShape containerShape;
containerShape.CreateLoop(vertices, 4);
b2FixtureDef childContainerFixture;
childContainerFixture.shape = &containerShape;
childWorldBody->CreateFixture(&childContainerFixture);

// First example of creating child body "within" the parent body...
childBodyDef.position = b2Vec2(0, 0); // Inside child world and with childContainerShape.
b2Body* bodyInChild = subWorld.CreateBody(&childBodyDef);
// Call subWorld.CreateBody for all the bodies in the child world.
// Always create those child bodies within the bounds of vertices.

for (;;)
{
    world.Step(0.1, 8, 3);
    subWorld.Step(0.1, 8, 3);

    render(world, b2Vec2(0, 0));
    render(subWorld, parentBody->GetPosition());
}
Louis Langholtz
  • 2,913
  • 3
  • 17
  • 40