2
votes

During game play, I would like to be able to change the ground edges in a Box2D world. I have created a ground body and then I am adding a ground fixture to the body. For example, the following code will create a flat ground 20 pixels above the bottom of the screen in my Box2D world:

b2BodyDef groundBodyDef;
groundBodyDef.type = b2_staticBody;
groundBodyDef.position.Set(0, 0);
groundBody = world->CreateBody(&groundBodyDef);

b2PolygonShape groundShape;
b2FixtureDef groundFixtureDef;
groundFixtureDef.shape = &groundShape;
groundFixtureDef.density = 0.0;

CGSize screenSize = [CCDirector sharedDirector].winSize;
int num = 2;
b2Vec2 verts[] = {
    b2Vec2(-screenSize.width / 100.0, 20.0 / 100.0),   
    b2Vec2(screenSize.width / 100.0, 20.0 / 100.0)
};

for(int i = 0; i < num - 1; ++i) {
    b2Vec2 offset = b2Vec2(screenSize.width/2/PTM_RATIO,
                           20.0/2/PTM_RATIO);
    b2Vec2 left = verts[i] + offset;
    b2Vec2 right = verts[i+1] + offset;

    groundShape.SetAsEdge(left, right);
    groundBody->CreateFixture(&groundFixtureDef);
}

Suppose I need change the verts array to have a different ground fixture definition? For example, is it possible to dynamically raise the ground by 50 pixels between moves of a player? Do I need to delete the entire ground body and recreate the ground body and fixture, or can I just delete or modify the existing ground fixture?

2

2 Answers

1
votes

I found that it worked to destroy the current groundBody followed by the creation of a new groundBody and ground fixture works fine. I don't know if this is best for performance, but it works like I wanted it to.

So basically, at the appropriate time during my game, I do the following:

    world->DestroyBody(groundBody);

Then I re-execute the code I showed in the problem statement above, substituting the 20.0 pixel value with the 50.0 pixel value in the verts array as follows:

b2Vec2 verts[] = {
    b2Vec2(-screenSize.width / 100.0, 50.0 / 100.0),   
    b2Vec2(screenSize.width / 100.0, 50.0 / 100.0)
}
0
votes

Change b2PolygonShape to b2EdgeShape.

CGSize s = [[CCDirector sharedDirector] winSize];
b2EdgeShape groundBox;

// bottom
groundBox.Set(b2Vec2(0.0f,0.0f), b2Vec2(s.width/PTM_RATIO,0.0f));
groundBody->CreateFixture(&groundBox,0);

You can't change fixture definition at runtime. So use different fixture and switch that body at run time.