-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
create-a-simple-hud #17
base: master
Are you sure you want to change the base?
Changes from all commits
ccc9f19
8397791
6637b2c
6e4c8ef
55afacd
192d596
8cf3c27
0bb2a08
7e8fe2c
a68e50a
d48ed58
bc99314
afd6392
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,140 @@ | ||||||||
# Create a simple HUD | ||||||||
|
||||||||
A HUD (heads-up display) is used to render Graphics used for game information, like a health bar or a toolbar. | ||||||||
LITIENGINE provides a broad kit of Components for this with the [`GuiComponent`](https://litiengine.com/docs/user-interface/guicomponents-an-overview/) framework. | ||||||||
|
||||||||
Lets implement a simple HUD that creates a healthbar for us. | ||||||||
|
||||||||
* ![Healthbar](https://user-images.githubusercontent.com/105820458/173564612-9c57bf97-95b5-4c22-9058-8ed1ed3e28b2.PNG) | ||||||||
|
||||||||
|
||||||||
## 1. our HUD class | ||||||||
|
||||||||
```java | ||||||||
package org.example; | ||||||||
|
||||||||
import de.gurkenlabs.litiengine.Game; | ||||||||
import de.gurkenlabs.litiengine.graphics.ImageRenderer; | ||||||||
import de.gurkenlabs.litiengine.graphics.Spritesheet; | ||||||||
import de.gurkenlabs.litiengine.gui.GuiComponent; | ||||||||
import de.gurkenlabs.litiengine.resources.Resources; | ||||||||
import de.gurkenlabs.litiengine.util.Imaging; | ||||||||
|
||||||||
import javax.tools.Tool; | ||||||||
import java.awt.image.BufferedImage; | ||||||||
|
||||||||
public class HUD extends GuiComponent { | ||||||||
//create variables for our images that we want to render later, and scale them to the desired size | ||||||||
private static final BufferedImage HEART = Imaging.scale(Resources.images().get("src/main/resources/hud/life.png"), 5.0); | ||||||||
private static final BufferedImage HEARTEMPTY = Imaging.scale(Resources.images().get("src/main/resources/hud/herzleer.png"), 5.0); | ||||||||
|
||||||||
//optional / intialize a Padding variable, to change positioning easier later on | ||||||||
private static final int PADDING = 10; | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One could also use values that are relative to the screen resolution in order to make the UI more dynamic. |
||||||||
|
||||||||
//call the super constructor, with the current game Windows Width and Hight to create a new HUD | ||||||||
protected HUD() { | ||||||||
super(0, 0, Game.window().getResolution().getWidth(), Game.window().getResolution().getHeight()); | ||||||||
} | ||||||||
|
||||||||
``` | ||||||||
- It's important to know that the Image files for our `BufferedImage`s can't be received from the [game resource file](https://litiengine.com/docs/resource-management/), so be sure to provide the complete path in the file system. | ||||||||
|
||||||||
## The render methods | ||||||||
|
||||||||
now lets get to the visual part, the render methods of our `HUD` class: | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
```java | ||||||||
@Override | ||||||||
public void render(Graphics2D g) { | ||||||||
super.render(g); | ||||||||
|
||||||||
//if there is no enviroment loaded we dont need to render anything | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
if (Game.world().environment() == null ) { | ||||||||
return; | ||||||||
|
||||||||
} | ||||||||
this.renderHP(g); | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
} | ||||||||
|
||||||||
private void renderHP(Graphics2D g) { | ||||||||
|
||||||||
//define the x and y coordinates of our Healtbar | ||||||||
double y = Game.window().getResolution().getHeight() - Game.window().getResolution().getHeight() + PADDING * 7 - HEART.getHeight(); | ||||||||
double x = Game.window().getResolution().getWidth() - ((Player.instance().getHitPoints().getMax() * (HEART.getWidth() + PADDING) * 1.28) - PADDING); | ||||||||
|
||||||||
//decides weather to render a full or empty heart depending on the players current Hitpoints | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
for (int i = 0; i < Player.instance().getHitPoints().getMax(); i++) { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should explain all custom implementations. |
||||||||
BufferedImage img = i < Player.instance().getHitPoints().get() ? HEART : HEARTEMPTY; | ||||||||
ImageRenderer.render(g, img, x + i * img.getWidth() + PADDING, y); | ||||||||
|
||||||||
} | ||||||||
} | ||||||||
|
||||||||
``` | ||||||||
- the x and y coorinates of this example place the bar in the upper left corner of the screen, but you can adjust these to your liking of course. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
|
||||||||
|
||||||||
### you could also adjust how many Hitpoints a heart should represent by dividing it by 2 for example : | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
```java | ||||||||
private void renderHP(Graphics2D g) { | ||||||||
|
||||||||
//define the x and y coordinates of our Healtbar | ||||||||
double y = Game.window().getResolution().getHeight() - Game.window().getResolution().getHeight() + PADDING * 7 - HEART.getHeight(); | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Explain the magic numbers maybe? |
||||||||
double x = Game.window().getResolution().getWidth() - ((Player.instance().getHitPoints().getMax() * (HEART.getWidth() + PADDING) * 1.28) - PADDING); | ||||||||
|
||||||||
//decides weather to render a full or empty heart depending on the players current Hitpoints | ||||||||
for (int i = 0; i < Player.instance().getHitPoints().getMax() /2; i++) { | ||||||||
BufferedImage img = i < Math.ceil( Player.instance().getHitPoints().get()/2) ? HEART : HEARTEMPTY; | ||||||||
ImageRenderer.render(g, img, x + i * img.getWidth() + PADDING, y); | ||||||||
|
||||||||
} | ||||||||
} | ||||||||
|
||||||||
``` | ||||||||
- now one heart would represent 2 Hitpoints of the Player | ||||||||
- we use the `Math.ceil()` method to get the next bigger int and not a double | ||||||||
|
||||||||
But now we have render methods, so why can't we see our precous health? | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
## initializing a new HUD in the `GameScreen` class | ||||||||
|
||||||||
Now to actually see our HUD, we first need to instantiate it in our `GameScreen` class | ||||||||
|
||||||||
|
||||||||
```java | ||||||||
package org.example; | ||||||||
|
||||||||
import de.gurkenlabs.litiengine.Game; | ||||||||
import de.gurkenlabs.litiengine.gui.screens.GameScreen; | ||||||||
|
||||||||
|
||||||||
public class InGameScreen extends GameScreen { | ||||||||
|
||||||||
private HUD hud; | ||||||||
|
||||||||
public static final String NAME = "INGAME-SCREEN"; | ||||||||
|
||||||||
public InGameScreen() { | ||||||||
super(NAME); | ||||||||
} | ||||||||
@Override | ||||||||
protected void initializeComponents() { | ||||||||
|
||||||||
//initialize a new HUD object, and add it to the GameScreen components | ||||||||
this.hud = new HUD(); | ||||||||
getComponents().add(hud); | ||||||||
|
||||||||
} | ||||||||
@Override | ||||||||
public void render(Graphics2D g) { | ||||||||
super.render(g); | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to override the |
||||||||
|
||||||||
if (Game.world().environment() != null) { | ||||||||
Game.world().environment().render(g); | ||||||||
} | ||||||||
} | ||||||||
} | ||||||||
``` | ||||||||
And there you have it: your own Health bar, customizable as you wish :D |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the resources folder is configured correctly for your project, you only need to specify the file name, not the entire relative path.