I am trying to re-create this:


So what I did is, made an half-circle image, filled with red, and set a TextureRegion, and used setRegionHeight for given percentage:

public void setDamage(int d) {
    int height = damage.getTexture().getHeight();

    double val = (double) d / 100;
    damage.setRegionHeight((int) Math.round(val * height));

I did the same for the water one

And called after creating:

water.flip(false, true);
bilge.flip(false, true);

I had to flip it aswell y-wise.

And it looks like this:


Doesn't look right, because it fills in a straight line, like I guess it would.

What methods can I use to create that filling look? I know I can use ShapeRenderer but I am not sure how, maybe use the circle equation and use half circle and fill lines at each degree based on the percentage set on damage? I would be happy to get some ideas

  • \$\begingroup\$ I'm not sure how these work, but I assume its just filling bottom from left to right, what you should be doing is finding the midpoint, drawing down and converting your numbers into radians and using sin & cos at angles ? \$\endgroup\$
    – RNewell122
    Aug 27, 2017 at 17:46
  • \$\begingroup\$ @RNewell122 Like a loop from for example 180 degrees is my 0 damage point to my target degree number, and just fill lines per degree? So 180 to 360 is full damage bar, 180 to 270 is half \$\endgroup\$
    – Ben Beri
    Aug 27, 2017 at 17:52

1 Answer 1


You can indeed use the ShapeRenderer to get something that is close to what the first image depicts.

The only part of drawing that that requires any math is the portions of red and blue, which if you use the arc method on ShapeRenderer is fairly simple.

arc takes a start point in degrees, so for the blue part it's trivial at 270 (at the bottom), but since arc does not use from and to but rather from and length for it's arguments the red one needs to start at 90 + 180 * (1 - amountOfRed), where amountOfRed is normalized to lie in the range [0 - 1].

I knocked up an example of this that produces something that looks like this enter image description here

The full code for that is:

package com.bornander.sandbox;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
import com.badlogic.gdx.math.Interpolation;

public class SandboxGame extends ApplicationAdapter {
    private OrthographicCamera camera;
    private ShapeRenderer shapeRenderer;

    private float red = 0;
    private float blue = 0;
    private float elapsed = 0;

    public void create() {
        shapeRenderer = new ShapeRenderer();

        float aspectRatio = (float)Gdx.graphics.getWidth() / (float)Gdx.graphics.getHeight();
        float w = 800;
        float h = w / aspectRatio;

        camera = new OrthographicCamera(w, h);

    public void render () {
        Gdx.gl.glClearColor(0.2f, 0.2f, 0.4f, 1);


        // Create some neat-looking values for red and blue, this part is not important
        elapsed += Gdx.graphics.getDeltaTime();

        float a1 = Math.min(1.0f, elapsed / 4.0f);
        float a2 = Math.min(1.0f, elapsed / 3.0f);

        red = Interpolation.bounceOut.apply(0, 1, a1);
        blue = Interpolation.bounceOut.apply(0, 1, a2);

        // The values for damage and water are hard-coded here, they 
        // should come from your code
        float damage = 250.0f;
        float water = 340.0f;

        float maxDamage = 500.0f; // This is the constant that is the maximum amount of damage in your game
        float maxWater = 400.0f; // This is the constant that is the maximum amount of damage in your game

        // this is the method that does all the work
        // dividing by the max values normalizes the values to the [0-1] range
        drawTheCircleThingy(damage / maxDamage, water / maxWater);

    // redStuff and blueStuff should be normalized to fit into the range [0 - 1]
    private void drawTheCircleThingy(float redStuff, float blueStuff) {

        float x = 0;
        float y = 0;

        float size = 200;
        float borderWidth = 10;

        float redStart = 90.0f + 180.0f * (1.0f - redStuff);
        float redLength = 180.0f * redStuff;

        float blueStart = 270.0f;
        float blueLength = 180.0f * blueStuff;

        float centerBarHeight = (size - borderWidth) * 2;
        float centerBarLeft = x - borderWidth / 2.0f; 
        float centerBarRight = x + borderWidth / 2.0f;
        float centerBarTop = y + centerBarHeight / 2.0f; 
        float centerBarBottom = y - centerBarHeight / 2.0f;

        // Draw the filled bits

        shapeRenderer.circle(x, y, size);

        shapeRenderer.circle(x, y, size - borderWidth);

        shapeRenderer.arc(x, y, size - borderWidth, redStart, redLength);

        shapeRenderer.arc(x, y, size - borderWidth, blueStart, blueLength);

        shapeRenderer.rect(x - borderWidth / 2, y - centerBarHeight / 2, borderWidth, centerBarHeight);


        // Draw the black borders

        shapeRenderer.circle(0, 0, size);
        shapeRenderer.circle(0, 0, size - borderWidth);

        shapeRenderer.line(centerBarLeft, centerBarBottom, centerBarLeft, centerBarTop);
        shapeRenderer.line(centerBarRight, centerBarBottom, centerBarRight, centerBarTop);
  • \$\begingroup\$ Can you show an example without the bouncy stuff? kinda confused with the redStuff part \$\endgroup\$
    – Ben Beri
    Aug 27, 2017 at 21:15
  • \$\begingroup\$ @Jony Sure thing! I've updated the code in the answer to show how your values for damage and water can be normalized and passed to the draw method. \$\endgroup\$
    – bornander
    Aug 27, 2017 at 21:23
  • 1
    \$\begingroup\$ @Jony Not a problem, glad I could help. \$\endgroup\$
    – bornander
    Aug 27, 2017 at 21:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .