Criei uma boneca de pano usando corpos dinâmicos (retângulos) e juntas de revolução simples (com ângulos inferiores e superiores). Quando minha boneca de pano atinge o chão (que é um corpo estático), os corpos parecem se mexer e as articulações se separam.
Parece que os corpos estão grudados no chão e o momento da boneca de pano separa a junta (veja a captura de tela abaixo).
Não tenho certeza se está relacionado, mas estou usando o wrapper Java Badlogic GDX para Box2D. Aqui estão alguns trechos do que eu acho que é o código mais relevante:
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;
}
Eu pulei o método para criar a cabeça, pois é praticamente o mesmo que o método retângulo (apenas usando uma forma de cricle).
Esses métodos são usados assim:
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);
Respostas:
O Box2D usa um solucionador de forma iterativo , em vez de fechado . Isso significa que todas as restrições são um pouco suaves. O Box2D se esforçará muito para fazer o que você diz, mas ocorrem imprecisões.
Para minimizar isso, há várias coisas que você pode fazer, em ordem de importância:
Step
). Isso torna o solucionador mais estável - é mais provável que suas imprecisões se cancelem ou se comportem pelo mesmo sempre.Step
). Você deve tentar obter pelo menos 10 de cada. Mais iterações de solucionador significam mais chances a cada passo de encontrar estabilidade e satisfazer corretamente as restrições - aproximadamente, menos chance de imprecisão. No entanto, um timestep menor e mais estável é melhor que mais iterações. Dadas as restrições suficientemente complicadas, você nunca poderá resolvê-las 100% corretamente, portanto, tente reduzir o tempo máximo antes de aumentar as iterações.fonte