using sprite for multiple bodies - c++

In my game I have a block sprite. With this sprite I've made a blockbody so that my character can't walk through it.
cocos2d::CCSprite* block = cocos2d::CCSprite::create("Block.png");
block->setPosition(ccp(5,20));
this->addChild(block);
b2BodyDef blockbodydef;
blockbodydef.type = b2_kinematicBody;
blockbodydef.position.Set(5/PTM_RATIO,20/PTM_RATIO);
blockbodydef.userData = block;
b2Body *blockbody = world->CreateBody(&blockbodydef);
b2PolygonShape blockPoly;
blockPoly.SetAsBox(37.5/PTM_RATIO , 37.5 / PTM_RATIO);
b2FixtureDef blockshapedef;
blockshapedef.shape = &blockPoly;
blockshapedef.density = 2.0f;
blockshapedef.friction = 0.2f;
blockshapedef.restitution = 0.8f;
blockbody->CreateFixture(&blockshapedef);
However, I want to have multiple of these blocks. Is there a way to like change the position of the bodydef and sprite without the original sprite disappearing or do I have to create a different sprite for each block?

You have to create another sprite for another block. Textures are cached inside cocos2dx, so it will be loaded from file only once.

Related

How to combine a physics body with tile sprites?

I am working with tile map and box2d with cocos2D in the game for iOS, i want to move the tile with respect to physics bodies, i.e. to combine one or more tiles in a body and on contact if body is moving then tile sprites should also move. Please suggest something to do so.
You could use a CCPhysicsSprite for this.
The following code is from the default Box2D project in Cocos2d v2.
-(void) addNewSpriteAtPosition:(CGPoint)p
{
CCLOG(#"Add sprite %0.2f x %02.f",p.x,p.y);
// Define the dynamic body.
//Set up a 1m squared box in the physics world
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);
b2Body *body = world->CreateBody(&bodyDef);
// Define another box shape for our dynamic body.
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(.5f, .5f);//These are mid points for our 1m box
// Define the dynamic body fixture.
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicBox;
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.3f;
body->CreateFixture(&fixtureDef);
CCNode *parent = [self getChildByTag:kTagParentNode];
//We have a 64x64 sprite sheet with 4 different 32x32 images. The following code is
//just randomly picking one of the images
int idx = (CCRANDOM_0_1() > .5 ? 0:1);
int idy = (CCRANDOM_0_1() > .5 ? 0:1);
CCPhysicsSprite *sprite = [CCPhysicsSprite spriteWithTexture:spriteTexture_ rect:CGRectMake(32 * idx,32 * idy,32,32)];
[parent addChild:sprite];
[sprite setPTMRatio:PTM_RATIO];
[sprite setB2Body:body];
[sprite setPosition: ccp( p.x, p.y)];
}
NOTE The position of the sprite has been set after the body has been created. If you do it the other way around, you may get an exception. See here.

Cocos2d Box2d Scaling Radius Circle Bodies

Currently, in cocos2d, I have a an app that does the following:
Initiate with a Blank Screen.
When I tap the screen, I get a circle to pop-up. As I hold the circle, the circle will continue to grow at a constant rate. However, despite the fact that the sprite is growing, the box2d physical body isn't, which means that the sprite will not collide with other bodies. I been trying to figure out a way to change the radius that scales with the sprite but no such question exist here for cocos2d. I have noticed other box2d for things other than cocos2d but I am having a hard time translating them over.
//smile.position = ccp(touchLocation.x, touchLocation.y);
smile.scale = .05;
[self addChild:smile];
// b2BodyDef smileBodyDef;
smileBodyDef.type = b2_dynamicBody;
smileBodyDef.position.Set(touchLocation.x/PTM_RATIO, touchLocation.y/PTM_RATIO);
smileBodyDef.userData = smile;
smileBody = world->CreateBody(&smileBodyDef);
//Radius
b2CircleShape smileCircleShape;
int radius = 80;
//Fixture
smileFixtureDef.shape = &smileCircleShape;
smileFixtureDef.density = 0.00f;
smileFixtureDef.friction = .2f;
smileBody->CreateFixture(&smileFixtureDef);
if (CGRectContainsPoint(smileRect, touchLocation)) {
growForever = [CCRepeatForever actionWithAction: [CCScaleBy actionWithDuration: .5 scale: 1.2]];
[growForever setTag:1];
[smile runAction:growForever];
Each time you want to change your radius, grab the shape object associated with the b2Fixture that you created for your body, and then set the new value accordingly:
fixture->GetShape()->m_radius = new_radius/PTM_RATIO;

Cocos2D+Box2D: Stack bodies that doesn´t fall?

EDIT 2: Problem solved! I can´t promise it will work with different settings, but by putting my block´s body density to 0, the stack of blocks did not fall when new blocks are added.
I´m sorry about the poor title of the question, I´ll explain my problem closer here:
So, I´ve used Box2D and cocos2D to setup a simple project where two boxes stacks on top of each other (I´m planning to expand to 8-10 boxes). Right now, using a friction of 10.0f on each box, the box at the top still moves around a little. If I would add more boxes, the "tower" would fall and I don´t want that.
I want the boxes to use the gravity to move down, but I never ever want them to change there start x-value.
So, how could I prevent my tower of boxes to fall over or prevent my boxes from moving in x-direction?
EDIT: Posting some code
This code creates on of the boxes, the other one just have a different sprite file.
CCSprite *block = [CCSprite spriteWithFile:#"red.png"];
block.position = ccp(200,380);
[self addChild:block];
//Body definition
b2BodyDef blockDef;
blockDef.type = b2_dynamicBody;
blockDef.position.Set(200/PTM_RATIO, 200/PTM_RATIO);
blockDef.userData = block;
b2Body *blockBody = _world->CreateBody(&blockDef);
//Create the shape
b2PolygonShape blockShape;
blockShape.SetAsBox(block.contentSize.width/PTM_RATIO/2, block.contentSize.height/PTM_RATIO/2);
//Fixture defintion
b2FixtureDef blockFixtureDef;
blockFixtureDef.shape = &blockShape;
blockFixtureDef.restitution = 0.0f;
blockFixtureDef.density = 10.0f;
blockFixtureDef.friction = 10.0f;
_redBlockFixture = blockBody->CreateFixture(&blockFixtureDef);
Nothing fancy.
Regards.
You could setup a 2 (1 pixel wide) walls in box2D to the left and right of the block. Here's some sample code for the left wall. To create the right wall, just copy and past the code and change the variable names and the position of the BodyDef.
// Constant you'll need to define
float wallHeight;
// Create wall body
b2BodyDef wallBodyDef;
wallBodyDef.type = b2_dynamicBody;
wallBodyDef.position.Set(200 - block.contentSize.width/PTM_RATIO/2, 0);
b2Body *wallBody = _world->CreateBody(&wallBodyDef);
// Create wall shape
b2PolygonShape wallShape;
wallShape.SetAsBox(1, wallHeight);
// Create shape definition and add to body
b2FixtureDef wallShapeDef;
wallShapeDef.shape = &wallShape;
wallShapeDef.density = 100.0f;
wallShapeDef.friction = 0.0f;
wallShapeDef.restitution = 0.0f;
b2Fixture *wallFixture = wallBody->CreateFixture(&wallShapeDef);
I solved this problem by adjusting the restitution (bounce) of the static surface upon which the blocks are stacked. For example, if the floor has a restitution of .2, a stack of five blocks will look like they are compressing into each other, and eventually topple:
Set the restitution of the floor to 0, and the blocks stay stacked the way you would expect:

Changing the polygon vertices in a dynamic polygon in cocos2d

I am new to cocos2d and first I learned how to make a circle then a square and now I learned how to create a polygon with an amount of vertices that I pick with a "b2polygonshape polygon" and here is my code for that
-(void) createDynamicPoly:(CGPoint)p;
{
b2BodyDef bodyDefPoly;
bodyDefPoly.type = b2_dynamicBody;
bodyDefPoly.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);
b2Body *polyBody = world->CreateBody(&bodyDefPoly);
int count = 8;
b2Vec2 vertices[8];
vertices[0].Set(10.0f/PTM_RATIO,0.0/PTM_RATIO);
vertices[1].Set(20.0f/PTM_RATIO,0.0f/PTM_RATIO);
vertices[2].Set(30.0f/PTM_RATIO,10.0f/PTM_RATIO);
vertices[3].Set(30.0f/PTM_RATIO,20.0f/PTM_RATIO);
vertices[4].Set(20.0f/PTM_RATIO,30.0f/PTM_RATIO);
vertices[5].Set(10.0f/PTM_RATIO,30.0f/PTM_RATIO);
vertices[6].Set(00.0f/PTM_RATIO,20.0f/PTM_RATIO);
vertices[7].Set(0.0f/PTM_RATIO,10.0f/PTM_RATIO);
b2PolygonShape polygon;
polygon.Set(vertices, count);
b2FixtureDef fixtureDefPoly;
fixtureDefPoly.shape = &polygon;
fixtureDefPoly.density = 1.0f;
fixtureDefPoly.friction = 0.3f;
polyBody->CreateFixture(&fixtureDefPoly);
}
My question is how can I actively change the vertices of this polygon and it change the shape on my screen, without drawing a new shape. My over all goal is to create a free flowing blob.
Thankyou
Modify your last statement to return a pointer to the resulting b2Fixture object. This can be kept as a class variable (ie. b2Fixture* fixture in your class interface).
fixture = polyBody->CreateFixture(&fixtureDefPoly);
Then, wherever you want to change the vertices of the polygon shape, grab a pointer to the shape object associated with your fixture:
b2PolygonShape* shape = (b2PolygonShape*) fixture->GetShape();
And modify the vertices as appropriate:
shape->m_vertices[0].Set(new_x0/PTM_RATIO,new_y0/PTM_RATIO);
shape->m_vertices[1].Set(new_x1/PTM_RATIO,new_y1/PTM_RATIO);
shape->m_vertices[2].Set(new_x2/PTM_RATIO,new_y2/PTM_RATIO);
...
shape->m_vertices[7].Set(new_x7/PTM_RATIO,new_y7/PTM_RATIO);
Good luck!

Cocos2d Box2d multiple b2circle shape fixture for one body with positioning

Anybody knows how to add 2 circle fixture to one b2body with desired positioning?
I know how to add two polygon fixture to one body by using m_centroid. But how can I do it for circle fixtures.
Any answer will be appreciated. I want to stick some object together. I tried joints but they all are elastic. I want distance static.
Thanks everyone!
You should create two fixtures for your body and the shapes of those fixtures should be b2CircleShape
//Create a body. You'll need a b2BodyDef, but I've assumed you know how to use these since you say you've created bodies successfully before.
b2Body* body = world->CreateBody(&bodyDef);
//Create the first circle shape. It's offset from the center of the body by -2, 0.
b2CircleShape circleShape1;
circleShape1.m_radius = 0.5f;
circleShape1.m_p.Set(-2.0f, 0.0f);
b2FixtureDef circle1FixtureDef;
circle1FixtureDef.shape = &circleShape1;
circle1FixtureDef.density = 1.0f;
//Create the second circle shape. It's offset from the center of the body by 2, 0.
b2CircleShape circleShape2;
circleShape2.m_radius = 0.5f;
circleShape2.m_p.Set(2.0f, 0.0f);
b2FixtureDef circle2FixtureDef;
circle2FixtureDef.shape = &circleShape2;
circle2FixtureDef.density = 1.0f;
//Attach both of these fixtures to the body.
body->CreateFixture(&circle1FixtureDef);
body->CreateFixture(&circle2FixtureDef);