Ich habe eine Stoffpuppe aus dynamischen Körpern (Rechtecken) und einfachen Drehgelenken (mit unteren und oberen Winkeln) erstellt. Wenn meine Stoffpuppe auf den Boden trifft (was ein statischer Körper ist), scheinen die Körper zu zappeln und die Gelenke trennen sich.
Es sieht so aus, als ob die Körper am Boden kleben und der Schwung der Stoffpuppe das Gelenk auseinander zieht (siehe Abbildung unten).
Ich bin nicht sicher, ob es verwandt ist, aber ich verwende den Badlogic GDX Java-Wrapper für Box2D. Hier sind einige Ausschnitte aus dem meiner Meinung nach relevantesten Code:
private RevoluteJoint joinBodyParts(
Body a, Body b, Vector2 anchor,
float lowerAngle, float upperAngle) {
RevoluteJointDef jointDef = new RevoluteJointDef();
jointDef.initialize(a, b, a.getWorldPoint(anchor));
jointDef.enableLimit = true;
jointDef.lowerAngle = lowerAngle;
jointDef.upperAngle = upperAngle;
return (RevoluteJoint)world.createJoint(jointDef);
}
private Body createRectangleBodyPart(
float x, float y, float width, float height) {
PolygonShape shape = new PolygonShape();
shape.setAsBox(width, height);
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.y = y;
bodyDef.position.x = x;
Body body = world.createBody(bodyDef);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = 10;
fixtureDef.filter.groupIndex = -1;
fixtureDef.filter.categoryBits = FILTER_BOY;
fixtureDef.filter.maskBits = FILTER_STUFF | FILTER_WALL;
body.createFixture(fixtureDef);
shape.dispose();
return body;
}
Ich habe die Methode zum Erstellen des Kopfes übersprungen, da sie der Rechteckmethode ziemlich ähnlich ist (nur mit einer Krikelform).
Diese Methoden werden wie folgt verwendet:
torso = createRectangleBodyPart(x, y + 5, 0.25f, 1.5f);
Body head = createRoundBodyPart(x, y + 7.4f, 1);
Body leftLegTop = createRectangleBodyPart(x, y + 2.7f, 0.25f, 1);
Body rightLegTop = createRectangleBodyPart(x, y + 2.7f, 0.25f, 1);
Body leftLegBottom = createRectangleBodyPart(x, y + 1, 0.25f, 1);
Body rightLegBottom = createRectangleBodyPart(x, y + 1, 0.25f, 1);
Body leftArm = createRectangleBodyPart(x, y + 5, 0.25f, 1.2f);
Body rightArm = createRectangleBodyPart(x, y + 5, 0.25f, 1.2f);
joinBodyParts(torso, head, new Vector2(0, 1.6f), headAngle);
leftLegTopJoint = joinBodyParts(torso, leftLegTop, new Vector2(0, -1.2f), 0.1f, legAngle);
rightLegTopJoint = joinBodyParts(torso, rightLegTop, new Vector2(0, -1.2f), 0.1f, legAngle);
leftLegBottomJoint = joinBodyParts(leftLegTop, leftLegBottom, new Vector2(0, -1), -legAngle * 1.5f, 0);
rightLegBottomJoint = joinBodyParts(rightLegTop, rightLegBottom, new Vector2(0, -1), -legAngle * 1.5f, 0);
leftArmJoint = joinBodyParts(torso, leftArm, new Vector2(0, 1), -armAngle * 0.7f, armAngle);
rightArmJoint = joinBodyParts(torso, rightArm, new Vector2(0, 1), -armAngle * 0.7f, armAngle);
Antworten:
Box2D verwendet einen iterativen und keinen geschlossenen Löser. Dies bedeutet, dass alle Einschränkungen etwas weich sind. Box2D wird sich sehr bemühen, das zu tun, was Sie sagen, aber es treten Ungenauigkeiten auf.
Um dies zu minimieren, können Sie verschiedene Dinge in der Reihenfolge ihrer Wichtigkeit tun:
Step
). Dies macht den Solver stabiler - Ihre Ungenauigkeiten heben sich mit größerer Wahrscheinlichkeit gegenseitig auf oder verhalten sich jedes Mal zumindest gleich.Step
). Sie sollten versuchen, mindestens 10 von jedem zu bekommen. Mehr Solver-Iterationen bedeuten mehr Chancen bei jedem Zeitschritt, Stabilität zu finden und Einschränkungen korrekt zu erfüllen - ungefähr weniger Ungenauigkeiten. Ein kleinerer, stabilerer Zeitschritt ist jedoch besser als mehr Iterationen. Bei ausreichend komplizierten Einschränkungen können Sie diese möglicherweise nie zu 100% korrekt lösen. Reduzieren Sie daher den Zeitschritt, bevor Sie die Iterationen erhöhen.quelle