Making games
Game UI
A game’s interface (a HUD, a pause menu, a health bar) is a UI document, a
.ogui file, shown on screen by a Canvas component.
Making a document
In the Assets panel, choose New UI Document, then double-click it. It opens in a tab of its own beside Scene, and while that tab is in front:
- the middle of the window is the document’s design surface,
- the left dock lists the document’s Elements instead of the Hierarchy,
- the Inspector shows the selected element’s properties.
Click Scene to go back to the scene; the document stays open in its tab.
Add at the top of the Elements list puts in a new element:
| Element | What it is |
|---|---|
| panel | A box that holds other elements, with a background. |
| row, column | Lay their children out side by side, or one above another. |
| label | Text. |
| image | A picture. |
| button | Something to click. |
| progress | A bar that fills: health, loading. |
| slider | A value the player drags. |
| text_input | A field the player types into. |
| widget | Another UI document, placed inside this one. Make a health bar once and use it in every HUD. |
Every element has a name. Names matter: scripts reach elements by them.
Showing it in the game
Add a Canvas to an object (Scene → Canvas makes one) and pick the document in its Document field. The canvas draws over the whole screen, whatever its transform says, and draws in the scene view while the game runs.
| Property | What it does |
|---|---|
| Visible | Drawn at all. |
| Order | Which canvas is on top when two overlap: higher draws later. |
| Scaling | ConstantPixels keeps everything the same size in pixels on every screen. ScaleWithScreen scales the document as if it were made for Reference size, so it fills the same share of any screen. |
| Screen match | With ScaleWithScreen, for a screen of a different shape: 0 follows its width, 1 its height, in between blends. |
From a script
Scene.canvas("HUD") finds the canvas on the object named HUD. An element
is named by its path: its name, with the names of the elements it’s inside
in front, like "menu/start". Inside a widget, the path goes through it:
"hud/health/fill".
var score = 120
var has_save = Save.exists("progress")
var hud = Scene.canvas("HUD")
hud.set_text("score", "Score: {score}")
hud.set_visible("pause_menu", true)
hud.set_enabled("menu/continue", has_save)
hud.set("health/fill", "value", 0.75)
var name = hud.get("name_field", "text")
When the player uses the UI, the scripts on the canvas’s own object get:
on_ui_click(path) runs when a button is clicked, on_ui_change(path, value)
when a slider is moved or a text input typed in (value is the new value or
text), and on_ui_submit(path, text) when Enter is pressed in a text input. The
reference lists them with the other hooks.
fn on_ui_click(path) {
if path == "menu/start" {
Scene.load("assets://scenes/level1.otsn")
} else if path == "menu/quit" {
Engine.quit()
}
}
A tidy way to organize this: one script on the canvas’s object owns the UI,
and everything else sends it what to show. The Escape example’s hud.cog
works that way.