LibGDX Box2D绳子拉得像个疯子

时间:2014-07-17 22:26:30

标签: android libgdx box2d revolute-joints

我正在使用绳子开发游戏,我使用圆圈和关节在Box2d中创建。当我用较小的力量拖动绳索时,绳索按预期工作,而在其他情况下(当力量更大时)它就像一个疯狂的伸展,我不知道如何修复它并创造更稳定的绳索。我尝试了不同类型的关节(RopeJoint,RevoluteJoint,DistanceJoint等),但它没用。 这是我的代码:

public class RopeItem {

public Body body;
private com.badlogic.gdx.graphics.g2d.Sprite bodySprite;
float width, length;
public CircleShape shape;
public RopeItem(World world, float width, float height, BodyType bodyType, Vector2 position) {
    super();        

    //init body 
    BodyDef bodyDef = new BodyDef();
    bodyDef.type = bodyType;
    bodyDef.position.set(position);
    this.body = world.createBody(bodyDef);
    //init shape
    FixtureDef fixtureDef = new FixtureDef();
    fixtureDef.density = 0.1f;
    fixtureDef.friction = 0.4f; 
    fixtureDef.restitution  = 0.2f;
    shape = new CircleShape();
    shape.setRadius(width / 2);
    fixtureDef.shape = shape;
    fixtureDef.filter.categoryBits = 0x0001;
    fixtureDef.filter.maskBits = 0x0002;

    this.body.createFixture(fixtureDef);
    shape.dispose();

    //create a body sprite
    bodySprite = new com.badlogic.gdx.graphics.g2d.Sprite(new TextureRegion(new Texture("data/rope_circle.png")));
    bodySprite.setSize(width, height);
    bodySprite.setOrigin(width/2, height/2);
    body.setUserData(bodySprite);

}

}

public void createRope(int length) {
    RevoluteJoint[] joints = new RevoluteJoint[length - 1];
    RopeJoint[] ropeJoints = new RopeJoint[length - 1];
    float width = 0.23f, height = 0.23f;
    for(int i=0; i<length; i++) {
        ropeSegmenets.add(new RopeItem(world, width, height, BodyType.DynamicBody, new Vector2(0.3f, 0)));
    }

    RevoluteJointDef jointDef = new RevoluteJointDef();
    jointDef.localAnchorA.x = -height / 2;
    jointDef.localAnchorB.x = height / 2;

    RopeJointDef ropeJointDef = new RopeJointDef();
    ropeJointDef.localAnchorA.set(0, -height / 2);
    ropeJointDef.localAnchorB.set(0, height / 2);
    ropeJointDef.maxLength = length;    

    for(int i = 0; i < length-1; i++) {
        jointDef.bodyA = ropeSegmenets.get(i).body;
        jointDef.bodyB = ropeSegmenets.get(i + 1).body;
        joints[i] = (RevoluteJoint) world.createJoint(jointDef);

        ropeJointDef.bodyA = ropeSegmenets.get(i).body;
        ropeJointDef.bodyB = ropeSegmenets.get(i+1).body;
        ropeJoints[i] = (RopeJoint) world.createJoint(ropeJointDef);
    }
}

截图:

正常:

enter image description here

拉​​伸:

enter image description here

如果你知道如何解决这个问题,请帮助我。

谢谢,查理!

1 个答案:

答案 0 :(得分:1)

之所以发生这种情况,是因为链的每个部分仅在局部解决其位置约束,也就是说,它只查看其两个最接近的邻居。它将这些邻居拉向自己,并将自己移向他们的中心。链条中间的一块不关心你将绳索末端连接到的固定点。

完全修复它的唯一有保证的方法是让链条的每一块都用绳索连接到另一块。因此,如果您有n个身体,则需要(n ^ 2 + n)/ 2个关节。

接下来最好的事情是将每根链条用绳索连接到固定端。这将是2n关节。但是,如果你想拉绳子,那么你还需要一个绳索连接来连接玩家可以拾取和拖动的每一条链条。如果你想让玩家随时随地挑选和拖动,你又会回到(n ^ 2 + n)/ 2的情况。

你可能能够部分地做到这一点,例如。沿着线均匀地扩展一些额外的绳索接头,将一些点连接到链条的末端。

如果您的绳索不需要沿着整个长度存在物理可碰撞的存在,那么我建议使用绳索连接两端,只需使用细节绳点在两者之间渲染样条线。

然而,从截图中看起来,你似乎试图将绳子挂在可碰撞点上并用张力将它拉到它们周围。我真的认为你不会喜欢尝试用Box2D做这个的经验。您需要的是专为绳索物理设计的定制行为。我不知道有任何不错的现有源代码,但您可以从此视频中获得一些好主意:https://www.youtube.com/watch?v=Krlf1XnzZGc