23. Player Health Ui
[[programvideogames]]In this lesson we'll be implementing the player health UI.
There's not much to the code, but a bit to think about as we are using half-hearts.
All code today is in main.odin. Let's get into it.
Setting Up
First, we'll use the core:math package below, so import that.
import "core:math"
Next up we're going to create a new 2D camera that stays at the same location - this way we can scale up our pixel-art UI to the same zoom level as the game.
As an aside, I think pixel size mixing looks really bad. That's when some pixel art assets in the same game have "bigger pixels" than others
Game_State :: struct {
camera: rl.Camera2D,
ui_camera: rl.Camera2D,
// ...
}
Initialise the camera zoom level the same way.
gs.camera = rl.Camera2D {
zoom = ZOOM,
}
gs.ui_camera = rl.Camera2D {
zoom = ZOOM,
}
Here's a zoomed in version of the heart asset we'll be using.
Don't save this one, as I've updated the
tileset.pngto include the hearts.
![[Pasted image 20241019172837.png]]
Drawing the Heart Sprites
// Where rl.DrawFPS used to be
rl.BeginMode2D(gs.ui_camera)
// Player health
{
full_hearts := player.health / 2
has_half_heart := f32(player.health) / 2 > f32(full_hearts)
// Integer division truncates towards zero.
// 5 / 2 = 2
// -5 / 2 = -2
empty_hearts := math.ceil(f32(player.max_health - player.health) / 2)
x := f32(16)
for _ in 0 ..< full_hearts {
rl.DrawTextureRec(gs.tileset_texture, {336, 176, 16, 16}, {x, 16}, rl.WHITE)
x += 16
}
if has_half_heart {
rl.DrawTextureRec(gs.tileset_texture, {336, 144, 16, 16}, {x, 16}, rl.WHITE)
x += 16
}
for _ in 0 ..< empty_hearts {
rl.DrawTextureRec(gs.tileset_texture, {336, 112, 16, 16}, {x, 16}, rl.WHITE)
x += 16
}
}
rl.EndMode2D()
First, we calculate how many full hearts we'll be displaying. One heart is 2 health.
Since integer division truncates towards zero, if we have 5 health right now, 5 / 2 will result in 2, not 2.5 or 3.
That's perfect for the full_hearts.
Next, we use the fact that integer division truncates to see if we should have a half heart.
By converting the value to an f32, we can use decimal division. 5.0 / 2.0 = 2.5 and 2.5 > 2.0.
Finally, we calculate how many empty_hearts.
Then we simply iterate over the full, draw the half if required, and iterate over the empty, while increasing the x position.