I am surely overlooking something, but is there an easy to draw for example only half a sprite in LibGDX? I originally thought I could do this with setBounds() but this distorts the sprite.
3 Answers
It's quite possible to partially draw a sprite using the SpriteBatch.draw(Texture,...) rather than the SpriteBatch.draw(TextureRegion,...). As long as you only intend to draw a rectangular sub-section of that sprite. Note, Sprite is a TextureRegion.
If you have a Sprite that you are already drawing, you can get the Texture itself from the Sprite using the .getTexture() function.
For example, the following code could be used to draw only the left side of a sprite:
spriteBatch.draw(
frame.getTexture(),
x, /* x the x-coordinate in screen space */
y, /* y the y-coordinate in screen space */
width / 2, /* originX the x-coordinate of the scaling and rotation origin relative to the screen space coordinates */
height / 2, /* originY the y-coordinate of the scaling and rotation origin relative to the screen space coordinates */
/* We only want to draw half the width of the sprite */
width / 2, /* width the width in pixels */
height, /* height the height in pixels */
frame.getScaleX(), /* scaleX the scale of the rectangle around originX/originY in x */
frame.getScaleY(), /* scaleY the scale of the rectangle around originX/originY in y */
0 , /* rotation the angle of counter clockwise rotation of the rectangle around originX/originY */
frame.getRegionX(), /* srcX the x-coordinate in texel space */
frame.getRegionY(), /* srcY the y-coordinate in texel space */
/* We only want to use half the source texture region */
frame.getRegionWidth() / 2, /* srcWidth the source with in texels */
frame.getRegionHeight(), /* srcHeight the source height in texels */
false, /* flipX whether to flip the sprite horizontally */
false); /* flipY whether to flip the sprite vertically */
Where spriteBatch is the SpriteBatch and frame is a Sprite; x, y, width and height are the same as you would use in spriteBatch.draw(frame, x, y, width, height);
To only draw the top half of a sprite (as if the sprite was standing in a liquid, for example) you would set the height, the texture region height, and include a slight adjustment to the draw position:
spriteBatch.draw(
frame.getTexture(),
x,
y + (height / 2), /* reposition to draw from half way up from the original sprite position */
width / 2,
height / 2,
width,
height / 2, /* draw the sprite at half height*/
frame.getScaleX(),
frame.getScaleY(),
0,
frame.getRegionX(),
frame.getRegionY(),
frame.getRegionWidth(),
frame.getRegionHeight() / 2, /* only use the texture data from the top of the sprite */
false,
false);
I hope this helps, Good luck.
-
\$\begingroup\$ Note that
textureRegion.getRegionX()
(andy
) are not working correctly with this ifisFlipX()
(ory
) is true. If it's true, you need to useu2
instead ofu
:getRegionX() = Math.round(u2 * texture.getWidth())
(same is true forgetRegionY()
, though you need to usev2
instead ofv
) \$\endgroup\$– JoschuaCommented Mar 16, 2018 at 16:21
If you are working solely with Sprites I do not believe there is a good way of drawing part of a Sprite. If you want to keep working only with Sprites I would recommend splitting the original Texture beforehand and creating a separate Sprite for each piece.
However, if you could work with Textures (i.e. you do not need to rotate the partial Sprite) then you can draw part of the texture using this method. It looks like this:
batch.draw(texture, xPosition, yPosition, xPositionInTexture, yPositionInTexture, widthInTexture, heightInTexture);
After much struggle, I finally found a way to draw texture portions. I really don't know why, but the other answers didn't help me in my case.
So I figured out another solution:
public static void
drawPortionFromButtom(
SpriteBatch batcher, TextureRegion textureRegion,
Vector2 position, float width, float height, float portionToDraw)
{
batcher.draw(textureRegion.getTexture(),
position.x,
position.y + height*(1 - portionToDraw) ,
width,
(height * portionToDraw),
textureRegion.getU() ,
textureRegion.getV2() + (textureRegion.getV() - textureRegion.getV2()) * (1 - portionToDraw),
textureRegion.getU2(),
textureRegion.getV());
}
public static void
drawPortionFromTop(
SpriteBatch batcher, TextureRegion textureRegion,
Vector2 position, float width, float height, float portionToDraw)
{
batcher.draw(textureRegion.getTexture(),
position.x,
position.y,
width,
(height / portionToDraw),
textureRegion.getU() ,
textureRegion.getV(),
textureRegion.getU2(),
textureRegion.getV() / portionToDraw);
}
Hope this helps someone else!