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!
Related
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.
Me and a friend of mine are trying to make a tank with cocos2dx.
we are so far that the tank is on the screen and the barrel is attached to the tank
but now we want to try to the rotate the barrel but nothing is happening, the joint is at the center where the barrel start en de dome ends. both the tank and the barrel are dynamic bodies and we are using a friction joint (see code)
// Create sprite and add it to the layer
CCSprite *tank = CCSprite::create();
//tank->initWithFile("../Resources/tanks/001/tank.png");
tank->setPosition(pos);
tank->setTag(1);
this->addChild(tank);
// Create ball body
b2BodyDef tankBodyDef;
tankBodyDef.type = b2_dynamicBody;
tankBodyDef.position = toMeters(&pos);
tankBodyDef.userData = tank;
tankBody = _world->CreateBody(&tankBodyDef);
// Create shape definition and add body
shapeCache->addFixturesToBody(tankBody, "001/tank");
pos = CCPointMake(580, 450);
// Create sprite and add it to the layer
CCSprite *barrel = CCSprite::create();
//barrel->initWithFile("Tanks/001/barrel.png");
barrel->setPosition(pos);
barrel->setTag(2);
this->addChild(barrel);
// Create ball body
b2BodyDef barrelBodyDef;
barrelBodyDef.type = b2_dynamicBody;
barrelBodyDef.position = toMeters(&pos);
barrelBodyDef.userData = barrel;
barrelBody = _world->CreateBody(&barrelBodyDef);
tankBarrelAnchor = CreateRevoluteJoint(tankBody, barrelBody, -85.f, 180.f, 2000000.f, 0.f, true, false);
tankBarrelAnchor->localAnchorA = b2Vec2(0, 0);
tankBarrelAnchor->localAnchorB = b2Vec2(0, 0);
tankBarrelAnchor->referenceAngle = 0;
joint = (b2RevoluteJoint*)_world->CreateJoint(tankBarrelAnchor);
b2RevoluteJointDef* Level::CreateRevoluteJoint(b2Body* A, b2Body* B, float lowerAngle, float upperAngle, float maxMotorTorque, float motorSpeed, boolean enableMotor, boolean collideConnect){
b2RevoluteJointDef *revoluteJointDef = new b2RevoluteJointDef();
revoluteJointDef->bodyA = A;
revoluteJointDef->bodyB = B;
revoluteJointDef->collideConnected = collideConnect;
revoluteJointDef->lowerAngle = CC_DEGREES_TO_RADIANS(lowerAngle);
revoluteJointDef->upperAngle = CC_DEGREES_TO_RADIANS(upperAngle);
revoluteJointDef->enableLimit = true;
revoluteJointDef->enableMotor = enableMotor;
revoluteJointDef->maxMotorTorque = maxMotorTorque;
revoluteJointDef->motorSpeed = CC_DEGREES_TO_RADIANS(motorSpeed); //1 turn per second counter-clockwise
return revoluteJointDef;
}
I think the problem is that your anchor positions are not correct. This setting:
tankBarrelAnchor->localAnchorA = b2Vec2(0, 0);
tankBarrelAnchor->localAnchorB = b2Vec2(0, 0);
... would put the anchors at those two red and green axes you can see in your screenshot, and it will try to pull those two points together. Try turning on the joints display in the debug draw and this should be more obvious.
You need to give the anchors as local coordinates from the point of view of each body. For example from the point of view of the tank body, the swivel point looks like (1,2) and from the point of view of the barrel body, it looks like (-1,0). Of course the dimensions you are using are probably different, but the directions should be somewhat similar.
See the "Local anchors" section here: http://www.iforce2d.net/b2dtut/joints-revolute
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;
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);
Hi
In BOX2d I have a fixture I know its a polygon through:
b2Shape *sh = fixture->GetShape();
NSLog(#"Type %d", sh->GetType());
//this returns 1, means its a polygon.
Now how to get the vertices in order to know exactly what shape it has i.e. rectangle square etc.
If you know it's a polygon, cast it to a b2PolygonShape and call GetVertices().
if(sh->GetType()==1)
{
b2PolygonShape* poly = (b2PolygonShape*)sh;
b2Vec2* verts = poly->GetVertices();
}
Docs: http://www.linuxuser.at/elements/doc/box2d/classb2_polygon_shape.htm#0e8a0b73c98b3e57f26772d14f252e8b