Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

libgdx spritebatch not drawing based on a texture's Origin

I'm drawing a collection of sprites here, using a smaller (4x4) texture when zoomed out, and a larger (16x16) texture when zoomed in. When the zoom level reaches a threshold, the swap happens.

However, for this to be a smooth transition, the sprites (located at [x,y]) need to be drawn with their origin being the centre of the sprite. Currently they are being drawn based on their lower left corner. So when the texture swap occurs, the sprite jumps slightly, as the origins don't match.

I've created some variables to debug and make sure that they are correct.

    TextureRegion sprite = null;

    boolean useHighResTexture = (_gameRef.cameraZoom < CAMERA_ZOOM_SWITCH_LO_RES);
    if (useHighResTexture) {
        //Zoomed in, Hi res, Use animation
        sprite = animation.getKeyFrame(animationStateTime, true);

    } else {
        //Zoomed out, lo-res, Use static image
        sprite = Assets.instance.getSmall();
    }


    float spriteWidth = sprite.getRegionWidth();
    float spriteHeight = sprite.getRegionHeight();
    float spriteOriginX = spriteWidth/2;
    float spriteOriginY = spriteHeight/2;

    //Draw(TEXTURE, x, y, originx, originy, 
    //      width, height, scaleX, scaleY, rotation, 
    //      srcX, srcY, 
    //      srcWidth, srcHeight, boolflipX, boolflipY

    //this.setCenter(spriteOriginX, spriteOriginY);

    batch.draw(sprite.getTexture(), this.x, this.y, spriteOriginX, spriteOriginY, 
            spriteWidth, spriteHeight, 1.0f, 1.0f, this.directionFaced, 
            sprite.getRegionX(), sprite.getRegionY(),
            sprite.getRegionWidth(), sprite.getRegionHeight(), false, false);

You can see that I'm using an animation on the zoomed in version (16x16) and a static image on the zoomed out version (4x4) using the AssetsManager.

The variables spriteWidth, spriteHeight are correct both at either 16 or 4 depending on whether zoomed in or out.

The variables spriteOriginX and spriteOriginY are correct (I assume) both at either 8 and 2 depending whether zoomed in or out.

I would have thought with the origins set as above it would draw the sprite based on that origin (as offsets from the lower left corner)

Is my call in the batch.draw() correct?

Many thanks, J

like image 348
Jammo Avatar asked Feb 14 '23 08:02

Jammo


1 Answers

No, it is not correct. The draw() always uses the left, lower corner as position. The origin is used for scaling and rotation only.
So for you this means, that you have to subtract the origin from your position:

batch.draw(sprite.getTexture(), this.x - spriteOriginX, this.y - spriteOriginY,
    spriteOriginX, spriteOriginY, spriteWidth, spriteHeight, 1.0f, 1.0f,
    this.directionFaced, sprite.getRegionX(), sprite.getRegionY(),
    sprite.getRegionWidth(), sprite.getRegionHeight(), false, false
);

By doing this you just "push" the left lower corner (which is the position) to the left and down, by half width and half height, so that your position really defines the center of the sprite.

Again: The origin is only used for rotation and scaling. If you set a rotation in the draw() method it will be rotated arround the origin (in your case the middle).

like image 185
Robert P Avatar answered Mar 03 '23 13:03

Robert P