JavaFX - How do I create a health bar?

I tried searching online on how to implement health bar with Java FX in a 2D side-view Java fighting game but I can only find those that goes with 'awt' and 'Swing'.

The health bar I'm picturing are like the two health bars on Street Fighter games. This is a game where two tanks fight each other in side-view.

I have a ViewManager.java that goes as follows:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.*;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundImage;
import javafx.scene.layout.BackgroundPosition;
import javafx.scene.layout.BackgroundRepeat;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.scene.paint.*;
import javafx.scene.canvas.*;

public class ViewManager {

private static final int HEIGHT = 1000;
private static final int WIDTH = 1920;
private AnchorPane mainPane;
private Scene mainScene;
private Stage mainStage;

private final static int GAME_BUTTON_START_X = 120;
private final static int GAME_BUTTON_START_Y = 400;

List<WarstrikeButton> gameButtons;

public ViewManager()
{
//Initialize the game stage
initializeStage();

//Create background
createBackground();

//Draws the tank and bullet
drawTank();
drawBullet();

//Initialize the game buttons
gameButtons = new ArrayList<>();
createButtons();

}//end viewManager

private void initializeStage() {
mainPane = new AnchorPane();
mainScene = new Scene(mainPane, WIDTH, HEIGHT);
mainStage = new Stage();
mainStage.setScene(mainScene);
}

public Stage getMainStage()
{
return mainStage;
}

{
button.setLayoutX(GAME_BUTTON_START_X);
button.setLayoutY(GAME_BUTTON_START_Y + gameButtons.size() * 100);
}

private void createButtons()
{
createMoveButton();
createShootButton();

}//end createButtons method

private void createMoveButton()
{
WarstrikeButton moveButton = new WarstrikeButton("Move");
}

private void createShootButton()
{
WarstrikeButton shootButton = new WarstrikeButton("Shoot");
}

private void createBackground()
{
Image backgroundImage = new Image("src/com/warstrike/graphics/resources/2d-game-background-6.jpg", 1366, 1000, false, true);
BackgroundImage background =  new BackgroundImage(backgroundImage, BackgroundRepeat.REPEAT, BackgroundRepeat.REPEAT, BackgroundPosition.DEFAULT, null);
mainPane.setBackground(new Background(background));
}//end createBackground function

//end class

/*public void drawImageOnScreen(double x, double y, double rotation, String imagePath) throws FileNotFoundException
{
//Creating an image
Image image1 = new Image(new FileInputStream(imagePath));

//Setting the image view
ImageView imageView = new ImageView(image1);

//Setting the position of the image
imageView.setX(x);
imageView.setY(y);
imageView.setRotate(rotation);

//setting the fit height and width of the image view
imageView.setFitHeight(x);
imageView.setFitWidth(y);

//Setting the preserve ratio of the image view
imageView.setPreserveRatio(true);

}//end drawImageOnScreen function */

public void drawTank()
{
// Create the Canvas
Canvas canvas = new Canvas(1920, 1080);

// Get the graphics context of the canvas

GraphicsContext gc = canvas.getGraphicsContext2D();

// Load the Image (Tank 1)
String imagePath = "src/com/warstrike/graphics/resources/tanks_tankNavy3.png";
Image image = new Image(imagePath);

// Draw the Image (150px is x position, 850px is y position, 134px is times 1.4 of the original width of 92px, 96px is times 1.4 of the original height of 69px
gc.drawImage(image, 150, 840, 110, 82); //void drawImage(Image img, double x, double y, double w, double h)

// Load the Image (Tank 2)
String imagePath2 = "src/com/warstrike/graphics/resources/tanks_tankDesert3.png";
Image image2 = new Image(imagePath2);

// Draw the Image (Width parameter is given a negative value to flip the tank horizontally)
gc.drawImage(image2, 1725, 840, -110, 82); //void drawImage(Image img, double x, double y, double w, double h)

//Add the canvas to the mainPane
}

public void drawBullet()
{
// Create the Canvas
Canvas canvas = new Canvas(1920, 1080);

// Get the graphics context of the canvas
GraphicsContext gc = canvas.getGraphicsContext2D();

String imagePath = "src/com/warstrike/graphics/resources/tank_bullet3.png";
Image image = new Image(imagePath);

// Draw Image
gc.drawImage(image, 265, 843, 37.5, 25); //void drawImage(Image img, double x, double y, double w, double h)

}

}


To have a better idea, here's a picture:

Just incase you'd want to see my Main.java:

    import javafx.application.Application; //import JavaFX libraries
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.shape.Rectangle;
import javafx.scene.Group;
import javafx.scene.Parent;
import javafx.stage.Stage;

public class Main extends Application {
@Override
public void start(Stage primaryStage)
{
try
{
ViewManager manager = new ViewManager();
primaryStage = manager.getMainStage();
//primaryStage.setScene(manager.drawImageOnScreen(50, 50, 0, "src/com/warstrike/graphics/resources/tanks_tankGreen3.png"));
primaryStage.show();
}
catch(Exception e)
{
e.printStackTrace();
}//end catch
}//end start

public static void main(String[] args)
{
launch(args);
}//end main
}//end class


TL;DR:

1) How do I create a health bar using JavaFX? (Obviously: the health bar will be extended to work e.g health bar shrinks when a bullet hits the tank)

2) May I know if my implementation is the correct way to do it? Or should I divide different draw components (e.g. drawTank(), drawBullet()) by classes and how exactly do I do it?

Sorry I'm completely new to game dev. Thank you for your help.

• Don't really know how to used that for gaming, but in pure JavaFX i would use a ProgressBar and skin it with css. I would post this as Answer if this can be done (don't know how to use JavaFX in Games with it's 3D possiblity and etc.) Feb 13 '19 at 15:53

I couldn't find your approach of a health bar, but I would suggest a simple approach for the start, something like this:

1) Add a Rectangle to your scene for each tank and give them both the same size:

Rectangle healtbarTank1 = Rectangle(200.0, 50.0, Color.RED);
Rectangle healtbarTank2 = Rectangle(200.0, 50.0, Color.BLUE);


2) Create a DoubleProperty for each healthbar and create a binding with the healthbars widthProperty():

DoubleProperty healthPercentage1 = SimpleDoubleProperty(1.0);
DoubleProperty healthPercentage2 = SimpleDoubleProperty(1.0);

DoubleBinding b1 = healthbarTank1.widthProperty().multiply(healthPercentage1);
DoubleBinding b2 = healthbarTank2.widthProperty().multiply(healthPercentage2);
healthbarTank1.widthProperty().bind(b1);
healthbarTank2.widthProperty().bind(b2);


Then you just have to set the percentage properties and the rectangles will change their size according to your bindings (width * percentage). Calculating the percentage of the health is up to you though. You can exchange the rectangles later for nearly any other Node JavaFX has to offer.

To create a health bar, you want to have a value representing the percentage of health you have. This value can be calculated as such:

float percentage = (currentHealth / maxHealth);


This will give you a value between 0.0 and 1.0. Next, you have the max width of the health bars on either side. You would presumably draw a container that the health bar goes in and then draw the health bar itself. You can draw the actual bar anywhere you want, but to calculate the width of the bar based on the player's current health:

float width = (percentage * maxWidth);


If you wanted to justify the health bar itself to the right of the container instead of the left, you could do something like:

float percentage = (currentHealth / maxHealth);
float width = (percentage * maxWidth);
float x = (originX + ((1.0f - percentage) * maxWidth));


And that would move the health bar over so that it is positioned on the right side of the health container. You can also use these percentage values to draw only a portion of an image if you want to use an image for the health bar instead.

It has been a while since I've used JavaFX specifically, so I can't really help you on the specifics of the drawing portion, but if you know how to draw basic shapes on the canvas, you should be able to figure the rest out on your own.