minetest_modding_book/_en/players/hud.md

295 lines
8.0 KiB
Markdown
Raw Permalink Normal View History

2015-01-01 19:36:52 +03:00
---
title: HUD
layout: default
2018-07-15 21:36:35 +03:00
root: ../..
2018-07-15 17:28:10 +03:00
idx: 4.6
2020-07-08 12:37:19 +03:00
description: Learn how to display HUD elements
2018-07-15 21:13:16 +03:00
redirect_from: /en/chapters/hud.html
2015-01-01 19:36:52 +03:00
---
## Introduction <!-- omit in toc -->
2015-01-01 19:36:52 +03:00
Heads Up Display (HUD) elements allow you to show text, images, and other graphical elements.
2018-10-27 05:10:37 +03:00
The HUD doesn't accept user input; for that, you should use a [formspec](formspecs.html).
2015-01-01 19:36:52 +03:00
- [Positioning](#positioning)
2023-05-01 14:22:02 +03:00
- [Position and Offset](#position-and-offset)
- [Alignment](#alignment)
- [Scoreboard](#scoreboard)
- [Text Elements](#text-elements)
2023-05-01 14:22:02 +03:00
- [Parameters](#parameters)
- [Our Example](#our-example)
- [Image Elements](#image-elements)
2023-05-01 14:22:02 +03:00
- [Parameters](#parameters-1)
- [Scale](#scale)
- [Changing an Element](#changing-an-element)
- [Storing IDs](#storing-ids)
- [Other Elements](#other-elements)
2015-01-01 19:36:52 +03:00
2017-12-17 19:01:29 +03:00
## Positioning
2015-01-01 19:36:52 +03:00
2017-12-17 19:01:29 +03:00
### Position and Offset
2015-01-01 19:36:52 +03:00
2017-12-17 19:01:29 +03:00
<figure class="right_image">
<img
width="300"
2018-07-15 21:36:35 +03:00
src="{{ page.root }}//static/hud_diagram_center.svg"
2017-12-17 19:01:29 +03:00
alt="Diagram showing a centered text element">
</figure>
Screens come in a variety of different physical sizes and resolutions, and
the HUD needs to work well on all screen types.
Minetest's solution to this is to specify the location of an element using both
a percentage position and an offset.
The percentage position is relative to the screen size, so to place an element
2018-10-27 05:10:37 +03:00
in the centre of the screen, you would need to provide a percentage position of half
the screen, e.g. (50%, 50%), and an offset of (0, 0).
2017-12-17 19:01:29 +03:00
The offset is then used to move an element relative to the percentage position.
<div style="clear:both;"></div>
### Alignment
Alignment is where the result of position and offset is on the element -
for example, `{x = -1.0, y = 0.0}` will make the result of position and offset point
to the left of the element's bounds. This is particularly useful when you want to
2018-10-27 05:10:37 +03:00
make a text element aligned to the left, centre, or right.
2017-12-17 19:01:29 +03:00
<figure>
<img
width="500"
2018-07-15 21:36:35 +03:00
src="{{ page.root }}//static/hud_diagram_alignment.svg"
2017-12-17 19:01:29 +03:00
alt="Diagram showing alignment">
</figure>
The above diagram shows 3 windows (blue), each with a single HUD element (yellow)
2018-10-27 05:10:37 +03:00
and a different alignment each time. The arrow is the result of the position
2017-12-17 19:01:29 +03:00
and offset calculation.
### Scoreboard
For the purposes of this chapter, you will learn how to position and update a
score panel like so:
<figure>
<img
2018-07-15 21:36:35 +03:00
src="{{ page.root }}//static/hud_final.png"
2017-12-17 19:01:29 +03:00
alt="screenshot of the HUD we're aiming for">
</figure>
2018-10-27 05:10:37 +03:00
In the above screenshot, all the elements have the same percentage position
2017-12-17 19:01:29 +03:00
(100%, 50%) - but different offsets. This allows the whole thing to be anchored
to the right of the window, but to resize without breaking.
## Text Elements
2015-01-01 19:36:52 +03:00
You can create a HUD element once you have a copy of the player object:
2015-01-01 19:36:52 +03:00
```lua
2024-10-23 02:39:22 +03:00
local player = core.get_player_by_name("username")
2015-01-01 19:36:52 +03:00
local idx = player:hud_add({
2017-12-17 19:01:29 +03:00
hud_elem_type = "text",
position = {x = 0.5, y = 0.5},
offset = {x = 0, y = 0},
text = "Hello world!",
alignment = {x = 0, y = 0}, -- center aligned
scale = {x = 100, y = 100}, -- covered later
2015-01-01 19:36:52 +03:00
})
```
2015-01-01 19:36:52 +03:00
2017-12-17 19:01:29 +03:00
The `hud_add` function returns an element ID - this can be used later to modify
or remove a HUD element.
### Parameters
The element's type is given using the `hud_elem_type` property in the definition
table. The meaning of other properties varies based on this type.
2018-10-27 05:10:37 +03:00
`scale` is the maximum bounds of text; text outside these bounds is cropped, e.g.: `{x=100, y=100}`.
2015-01-01 19:36:52 +03:00
2018-10-27 05:10:37 +03:00
`number` is the text's colour, and is in [hexadecimal form](http://www.colorpicker.com/), e.g.: `0xFF0000`.
2017-12-17 19:01:29 +03:00
### Our Example
2018-10-27 05:10:37 +03:00
Let's go ahead and place all the text in our score panel:
2015-01-01 19:36:52 +03:00
```lua
2018-10-27 05:10:37 +03:00
-- Get the dig and place count from storage, or default to 0
local meta = player:get_meta()
local digs_text = "Digs: " .. meta:get_int("score:digs")
local places_text = "Places: " .. meta:get_int("score:places")
2017-12-17 19:01:29 +03:00
player:hud_add({
hud_elem_type = "text",
position = {x = 1, y = 0.5},
offset = {x = -120, y = -25},
text = "Stats",
alignment = 0,
scale = { x = 100, y = 30},
number = 0xFFFFFF,
})
player:hud_add({
hud_elem_type = "text",
position = {x = 1, y = 0.5},
offset = {x = -180, y = 0},
text = digs_text,
alignment = -1,
scale = { x = 50, y = 10},
number = 0xFFFFFF,
})
player:hud_add({
hud_elem_type = "text",
position = {x = 1, y = 0.5},
offset = {x = -70, y = 0},
text = places_text,
alignment = -1,
scale = { x = 50, y = 10},
number = 0xFFFFFF,
})
```
2015-01-01 19:36:52 +03:00
2017-12-17 19:01:29 +03:00
This results in the following:
<figure>
<img
2018-07-15 21:36:35 +03:00
src="{{ page.root }}//static/hud_text.png"
2017-12-17 19:01:29 +03:00
alt="screenshot of the HUD we're aiming for">
</figure>
## Image Elements
Image elements are created in a very similar way to text elements:
2015-01-01 19:36:52 +03:00
```lua
2017-12-17 19:01:29 +03:00
player:hud_add({
hud_elem_type = "image",
position = {x = 1, y = 0.5},
offset = {x = -220, y = 0},
2018-09-24 19:16:00 +03:00
text = "score_background.png",
2017-12-17 19:01:29 +03:00
scale = { x = 1, y = 1},
alignment = { x = 1, y = 0 },
})
```
2015-01-01 19:36:52 +03:00
2017-12-17 19:01:29 +03:00
You will now have this:
2015-01-01 19:36:52 +03:00
2017-12-17 19:01:29 +03:00
<figure>
<img
2018-07-15 21:36:35 +03:00
src="{{ page.root }}//static/hud_background_img.png"
2017-12-17 19:01:29 +03:00
alt="screenshot of the HUD so far">
</figure>
2015-01-01 19:36:52 +03:00
2017-12-17 19:01:29 +03:00
### Parameters
2015-01-01 19:36:52 +03:00
2017-12-17 19:01:29 +03:00
The `text` field is used to provide the image name.
2015-01-01 19:36:52 +03:00
2017-12-17 19:01:29 +03:00
If a co-ordinate is positive, then it is a scale factor with 1 being the
2018-10-27 05:10:37 +03:00
original image size, 2 being double the size, and so on.
However, if a co-ordinate is negative, it is a percentage of the screen size.
2017-12-17 19:01:29 +03:00
For example, `x=-100` is 100% of the width.
2015-01-01 19:36:52 +03:00
2017-12-17 19:01:29 +03:00
### Scale
2015-01-01 19:36:52 +03:00
2017-12-17 19:01:29 +03:00
Let's make the progress bar for our score panel as an example of scale:
```lua
2018-10-27 05:10:37 +03:00
local percent = tonumber(meta:get("score:score") or 0.2)
2017-12-17 19:01:29 +03:00
player:hud_add({
hud_elem_type = "image",
position = {x = 1, y = 0.5},
offset = {x = -215, y = 23},
2018-09-24 19:16:00 +03:00
text = "score_bar_empty.png",
2017-12-17 19:01:29 +03:00
scale = { x = 1, y = 1},
alignment = { x = 1, y = 0 },
})
player:hud_add({
hud_elem_type = "image",
position = {x = 1, y = 0.5},
offset = {x = -215, y = 23},
2018-09-24 19:16:00 +03:00
text = "score_bar_full.png",
2017-12-17 19:01:29 +03:00
scale = { x = percent, y = 1},
alignment = { x = 1, y = 0 },
})
```
2017-12-17 19:01:29 +03:00
We now have a HUD that looks like the one in the first post!
There is one problem however, it won't update when the stats change.
2017-12-17 19:01:29 +03:00
## Changing an Element
2020-07-08 12:37:19 +03:00
You can use the ID returned by the `hud_add` method to update it or remove it later.
2015-01-01 19:36:52 +03:00
```lua
2015-01-01 19:36:52 +03:00
local idx = player:hud_add({
2017-12-17 19:01:29 +03:00
hud_elem_type = "text",
text = "Hello world!",
-- parameters removed for brevity
2015-01-01 19:36:52 +03:00
})
2017-12-17 19:01:29 +03:00
player:hud_change(idx, "text", "New Text")
player:hud_remove(idx)
```
2015-01-01 19:36:52 +03:00
2017-12-17 19:01:29 +03:00
The `hud_change` method takes the element ID, the property to change, and the new
2020-07-08 12:37:19 +03:00
value. The above call changes the `text` property from "Hello World" to "New text".
2015-01-01 19:36:52 +03:00
2017-12-17 19:01:29 +03:00
This means that doing the `hud_change` immediately after the `hud_add` is
functionally equivalent to the following, in a rather inefficient way:
2015-01-01 19:36:52 +03:00
```lua
2015-01-01 19:36:52 +03:00
local idx = player:hud_add({
2017-12-17 19:01:29 +03:00
hud_elem_type = "text",
text = "New Text",
2015-01-01 19:36:52 +03:00
})
```
2015-01-01 19:36:52 +03:00
2017-12-17 19:01:29 +03:00
## Storing IDs
2015-01-01 19:36:52 +03:00
```lua
2018-09-24 19:16:00 +03:00
score = {}
2017-12-17 19:01:29 +03:00
local saved_huds = {}
2018-09-24 19:16:00 +03:00
function score.update_hud(player)
2017-12-17 19:01:29 +03:00
local player_name = player:get_player_name()
2018-10-27 05:10:37 +03:00
-- Get the dig and place count from storage, or default to 0
local meta = player:get_meta()
local digs_text = "Digs: " .. meta:get_int("score:digs")
local places_text = "Places: " .. meta:get_int("score:places")
local percent = tonumber(meta:get("score:score") or 0.2)
2015-01-01 19:36:52 +03:00
2017-12-17 19:01:29 +03:00
local ids = saved_huds[player_name]
if ids then
player:hud_change(ids["places"], "text", places_text)
player:hud_change(ids["digs"], "text", digs_text)
player:hud_change(ids["bar_foreground"],
"scale", { x = percent, y = 1 })
else
ids = {}
saved_huds[player_name] = ids
-- create HUD elements and set ids into `ids`
end
end
2024-10-23 02:39:22 +03:00
core.register_on_joinplayer(score.update_hud)
2017-12-17 19:01:29 +03:00
2024-10-23 02:39:22 +03:00
core.register_on_leaveplayer(function(player)
2017-12-17 19:01:29 +03:00
saved_huds[player:get_player_name()] = nil
end)
```
2015-01-01 19:36:52 +03:00
2015-02-22 13:28:37 +03:00
## Other Elements
2015-01-01 19:36:52 +03:00
2023-05-01 14:22:02 +03:00
Read [lua_api.md](https://minetest.gitlab.io/minetest/hud/) for a complete list of HUD elements.