spine 2d coordinate system libgdx

646 Views Asked by At

i don't know what im doing wrong...i think im having brain freeze. I am really struggling with converting my spine objects pixel coordinates to world coordinates. I have recently converted all my code to work with Ashley ecs and i cant seem to get my spine object to display in the correct position. i have a system which handles the rendering and positioning of my spine object but i cant seem to get it displaying in the correct position. I'm hoping someone can point me in the correct direction!

i have included my code for the spine rendering system...hope you can help! i want to place the spine object at the same position as my box 2d object which is using world coordinates. but spine is using pixel coordinates. i have also included an image to show you what is happening. (the grey square near the middle right of the screen is where i want my spine object to be!)

Amarino

in game image

    public class SpineRenderSystem extends IteratingSystem {
    private static final String TAG = com.chaingang.freshstart.systems.SpineRenderSystem.class.getName();

    private PolygonSpriteBatch pBatch;
    SkeletonMeshRenderer skeletonMeshRenderer;
    private boolean process = true;

    BodyComponent bodyComp;
    Spine2DComponent spineComp;

    public SpineRenderSystem(PolygonSpriteBatch pBatch){
        super(Family.all(RenderableComponent.class, Spine2DComponent.class, PositionComponent.class).get());
        this.pBatch = pBatch;
        skeletonMeshRenderer = new SkeletonMeshRenderer();
        skeletonMeshRenderer.setPremultipliedAlpha(true);

    }


    @Override
    protected void processEntity(Entity entity, float deltaTime) {

        bodyComp = Mappers.body.get(entity);
        spineComp = Mappers.spine2D.get(entity);

        float offsetX = 100.00f/Gdx.graphics.getWidth(); //100 equal world width
        float offsetY = 50.00f/Gdx.graphics.getHeight(); //50 equals world height

        pBatch.begin();
            spineComp.skeleton.setX((bodyComp.body.getPosition().x / offsetX) );
            spineComp.skeleton.setY((bodyComp.body.getPosition().y) / offsetY);

            skeletonMeshRenderer.draw(pBatch,spineComp.skeleton);
            //spineComp.get(entity).skeleton.setFlipX(player.dir == -1);
            spineComp.animationState.apply(spineComp.skeleton);
            spineComp.skeleton.updateWorldTransform();
        pBatch.end();


    }
}
2

There are 2 best solutions below

0
On BEST ANSWER

What I do for my spine renders is look at the bounding box size in pixels in spine. This is usually in the order of 100s of pixels. But if you are working with box2d scales, it is recommended that you think of 1 as 1 meter.

With this in mind I will scale a human spine animation with a hip y coordinate of 200 pixels by dividing it by 200, or there about.

Once you have this ratio, then when you build your Spine Skeleton you can do this (sorry, I do all my libgdx stuff in Kotlin now):

val atlasLoader = AtlasAttachmentLoader(atlas)
val skeletonJson = SkeletonJson(atlasLoader)
skeletonJson.scale = 1/200f

Then you might also want to handle an offset for rendering your spine object, as I see you are trying to do, because possibly your root bone is in the center of your spine object (a hip for example). However, you are doing a division operation, which I guess is exploratory as offsets should be an addition or subtraction. Here is how I do it using the spine pixel coordinates (again, sorry for the Kotlin, but I like it):

//In some object or global state we have this stuff
var skeleton: Skeleton
var skeletonRenderer = SkeletonRenderer<PolygonSpriteBatch>()


//Then in the rendering code
val offset = Vector2(0f,-200f)
val position = physicsRoot.position().add(offset)
skeleton.setPosition(position.x, position.y)
skeleton.updateWorldTransform()
skeletonRenderer.draw(batch, skeleton)

That should get your spine stuff working as you expect.

9
On

Have you heard of a method called camera.project(world coordinates); it might do what you are looking for. It takes the world coordinates and turns them into screen coordinates. For the opposite you can do camera.unproject(screen coordinates);