I'm writing a game, and I need to make up a rope. I maked it by b2RopeJoint, but there I have not found an opportunity to make it elastic. Then I looked for b2DistanceJoint, everything is cool with the elasticity, but I can't find an ability to set a limit only to the maximum distance (without minimum one).
How can I do it?
Try this.
-(void) CreateElasticRope {
//=======Params
// Position and size
b2Vec2 lastPos = b2Vec2(4,4); //set position first body
float widthBody = 0.35;
float heightBody = 0.1;
// Body params
float density = 0.05;
float restitution = 0.5;
float friction = 0.5;
// Distance joint
float dampingRatio = 0.0;
float frequencyHz = 0;
// Rope joint
float kMaxWidth = 1.1;
// Bodies
int countBodyInChain = 15;
b2Body* prevBody;
//========Create bodies and joints
for (int k = 0; k < countBodyInChain; k++) {
b2BodyDef bodyDef;
if(k==0 ) bodyDef.type = b2_staticBody; //first body is static
else bodyDef.type = b2_dynamicBody;
bodyDef.position = lastPos;
lastPos += b2Vec2(2*widthBody, 0); //modify b2Vect for next body
bodyDef.fixedRotation = YES;
b2Body* body = world->CreateBody(&bodyDef);
b2PolygonShape distBodyBox;
distBodyBox.SetAsBox(widthBody, heightBody);
b2FixtureDef fixDef;
fixDef.density = density;
fixDef.restitution = restitution;
fixDef.friction = friction;
fixDef.shape = &distBodyBox;
body->CreateFixture(&fixDef);
body->SetHealth(9999999);
body->SetLinearDamping(0.0005f);
if(k>0) {
//Create distance joint
b2DistanceJointDef distJDef;
b2Vec2 anchor1 = prevBody->GetWorldCenter();
b2Vec2 anchor2 = body->GetWorldCenter();
distJDef.Initialize(prevBody, body, anchor1, anchor2);
distJDef.collideConnected = false;
distJDef.dampingRatio = dampingRatio;
distJDef.frequencyHz = frequencyHz;
world->CreateJoint(&distJDef);
//Create rope joint
b2RopeJointDef rDef;
rDef.maxLength = (body->GetPosition() - prevBody->GetPosition()).Length() * kMaxWidth;
rDef.localAnchorA = rDef.localAnchorB = b2Vec2_zero;
rDef.bodyA = prevBody;
rDef.bodyB = body;
world->CreateJoint(&rDef);
} //if k>0
prevBody = body;
} //for
}
There's a 2.2 style ropejoint implementation here: https://github.com/aaronfarr/box2Dweb
You can use both a rope joint and a distance joint together. Make the distance of the rope joint a bit longer than the distance joint.
From the Box2D testbed example, I modified the "Web" example as follows:
#ifndef ELASTICROPE_H
#define ELASTICROPE_H
#define NUM_JOINTS 7
#define NUM_LINKS 8
class ElasticRope : public Test
{
public:
ElasticRope()
{
b2Body* ground = NULL;
{
b2BodyDef bd;
ground = m_world->CreateBody(&bd);
b2EdgeShape shape;
shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
ground->CreateFixture(&shape, 0.0f);
}
{
b2CircleShape shape;
shape.m_radius = 0.8f;
// create bodies
for (int b = 0; b < NUM_LINKS; b++) {
b2BodyDef bd;
bd.type = b2_dynamicBody;
bd.position.Set(5.0f, NUM_LINKS-b);
m_bodies[b] = m_world->CreateBody(&bd);
m_bodies[b]->CreateFixture(&shape, 5.0f);
}
for (int j = 0; j < NUM_JOINTS; j++) {
b2DistanceJointDef jd;
b2Vec2 p1, p2, d;
jd.frequencyHz = 5.0f;
jd.dampingRatio = 1.0f;
jd.bodyA = m_bodies[j];
jd.bodyB = m_bodies[j+1];
m_joints[j] = m_world->CreateJoint(&jd);
}
}
}
void Step(Settings* settings)
{
Test::Step(settings);
m_debugDraw.DrawString(5, m_textLine, "This demonstrates an elastic rope.");
m_textLine += DRAW_STRING_NEW_LINE;
}
void JointDestroyed(b2Joint* joint)
{
for (int32 i = 0; i < 8; ++i)
{
if (m_joints[i] == joint)
{
m_joints[i] = NULL;
break;
}
}
}
static Test* Create()
{
return new ElasticRope;
}
b2Body* m_bodies[NUM_LINKS];
b2Joint* m_joints[NUM_JOINTS];
};
#endif // ELASTICROPE_H
Its far from perfect, but may be a starting point.
来源:https://stackoverflow.com/questions/9171937/box2d-elastic-rope-joint