- Uređeno
Make Spine character's parts follow box2d Bodies
How do you set a bone to the location of the box2d body?
On this thread (Getting started with Box2D) Nate said "If you want a ragdoll effect, just stop updating their positions and let gravity in the physics simulation take over."
Can anyone elaborate on how they have done that? I can easily let the gravity in the physics take over, and my box2D bodies will fall to the ground. I need now to make the separate images of my character follow them
I am just trying to set the position of the bones directly at this point. This has not been going well.
b2Bodies is an ArrayList of b2D Body class. For background on that if you want: All instances of an enemy subclass using the same skeleton?
it was a separate issue, which Nate addressed.[/i]
public void updateSkeletonToBodies(float deltaTime) {
int i = 0;
for (Slot slot : skeleton.getSlots()) {
Bone bone = slot.getBone();
Body bod = b2bodies.get(i);
float x = bod.getWorldPoint(new Vector2(bod.getPosition().x, bod.getPosition().y)).x;
float y = bod.getWorldPoint(new Vector2(bod.getPosition().x, bod.getPosition().y)).y;
float angle = bod.getAngle() * MathUtils.radiansToDegrees;
bone.setX(x);
bone.setY(y);
bone.setRotation(angle);
i++
}
//skeleton.updateWorldTransform();
}
For x and y in that function I have tried many many things. If I don't use skeleton.updateWorldTransform() then nothing changes at all
I can set the bones all I want, they stay frozen in their last position. If I use updateWorldTransform then of course they are completely wrong. For starters, they are computed with their parent SRTs which (I think) causes them to swing wildly around the screen (though there is probably more than just that going on.) So I don't think updateWorldTransform is correct, but something is missing.
I tried updating the Skeleton and Bone classes to force the Bone not to consider the parent on its updateWorldTransform, which caused them all to fall into a heap, except for the torso of the body which was kinda rotating around the pile like a moon.
I tried subtracting/adding the parent bone SRT from the bone and then also bone.updateWorldTransform for each bone instead of skeleton.updateWorldTransform
no dice.
I tried only changing the x, the y or the rotation, and saw that even if I only change one of these it moves both horizontally and vertically
so now I'm looking at the guts of bone.worldToLocal()
am I going to need to reverse the matrix math SRT calculations?
One last consideration is the registration points of bodies versus bones. The Body center points, which they rotate around, are in the center
yes? Which would not be the same as the bones. So another calculation/translation there?
Any help at all would be greatly appreciated, really. I have been looking at this from all kinds of perspectives, and having trouble even finding a way into it.
Thank you very much,
Richard
Update:
Looking at: Changing bone position in libgdx
I have altered the code somewhat and I'm finding that my if I update only the rotation I can see that it is correct. Positions are mostly very off, although my torso and the thighs are very close to correct; off by a few hundred, perhaps.
public void updateSkeletonToBodies(float deltaTime) {
int i = 0;
for (Slot slot : skeleton.getSlots()) {
Bone bone = slot.getBone();
Body bod = b2bodies.get(i);
if (!(slot.getAttachment() instanceof Box2dAttachment)) continue;
Box2dAttachment attachment = (Box2dAttachment) slot.getAttachment();
float x = bod.getPosition().x - bone.getX() - attachment.getWidth() / 2;
float y = bod.getPosition().y - bone.getY();
Vector2 worldPos = new Vector2(x, y);
Vector2 localPos = bone.getParent().worldToLocal(worldPos);
bone.setX(localPos.x);
bone.setY(localPos.y);
bone.setRotation(bod.getAngle() * MathUtils.radiansToDegrees - bone.getParent().getWorldRotation());
skeleton.updateWorldTransform();
i++;
}
}
Where define the float x and float y, I am not certain that getX() should be the bone calling it. On the post above it was simply 'getX()' with no caller specified. That doesn't work for me. More problematic for the same reasons is the attachment.getWidth()
it must be the attachment there.
In the post I reference Nate says: "You probably want to adjust bones from the root down the hierarchy." Not sure how that is done, but it seems as though that is may well be my problem, since the only pieces of the ragdoll close to accurate are the pieces that are first children of the root.
Thanks again,
Richard
Hi,
Have this semi-figured out now. My mistake was in the lines:
float x = bod.getPosition().x - bone.getX() - attachment.getWidth() / 2;
float y = bod.getPosition().y - bone.getY();
Well, duh: If you take the bone position, and then keep adding to it, and then setting it as the new position, your bones will fly off the screen in the general direction of the edge of the universe. Use the skeleton, not the bone...
float x = bod.getPosition().x - skeleton.getX() - attachment.getWidth() / 12;
float y = bod.getPosition().y - skeleton.getY();
Why 12? That's why it is 'semi' figured out. I have no idea why 12. But things line up pretty well with 12. Hope I'm not back on here in a day or two because of it!
Thanks,
Richard