1

当我使用绳索时,我正在开发一个游戏,这是我在 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);
    }
}

截图:

普通的:

在此处输入图像描述

拉伸:

在此处输入图像描述

如果您知道如何解决此问题,请帮助我。

谢谢,查理!

4

1 回答 1

1

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

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

下一个最好的办法是用绳索接头将链条的每一部分连接到固定端。那将是 2n 个关节。但是,如果你想拉绳子,那么你还需要一个绳子接头来连接玩家可以挑选和拖动的每一块链条。如果你想让玩家随意选择和拖动,你又回到了 (n^2+n)/2 的情况。

您可能可以部分做到这一点,例如。沿着线均匀地分布一些额外的绳索接头,仅将一些点连接到链的末端。

如果您的绳索不需要在整个长度上具有物理可碰撞的存在,那么我建议使用绳索接头连接两端,并使用 verlet 绳索点在两者之间渲染样条线或其他东西。

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

于 2014-07-18T10:54:06.257 回答