Box2d elastic rope joint

扶醉桌前 提交于 2019-12-01 04:42:48

问题


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?


回答1:


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 
}



回答2:


There's a 2.2 style ropejoint implementation here: https://github.com/aaronfarr/box2Dweb




回答3:


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.




回答4:


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!