HudHandle
Since 0.6Changed in 0.7
HUD overlay.
Text values are keys into meta.strings; a missing key renders as [[key]].
Reached in a behaviour as ctx.hud.
Signature
export interface HudHandle {
/**
* Set one field. With no `meta.hud` spec a field reads as a label and the value ("Lap 2"); `options`
* give it a label, a unit and fixed decimals: `ctx.hud.set("speed", 92, { unit: "km/h" })` reads
* "Speed 92 km/h". An unknown option, or decimals that are not a whole number 0..6, throws.
*/
set(field: HudField, value: string | number | null, options?: HudFieldOptions): void
objective(textKey: string): void
/** A contextual prompt ("Press E"); null hides it. */
prompt(textKey: string | null): void
/** Countdown in seconds, shown as a clock with tenths (`0:02.0`, `1:23.3`) unless `meta.hud` styles it; null hides it. */
timer(seconds: number | null): void
score(value: number): void
/**
* Let one HUD row answer the hit-test and take focus.
*
* The HUD is click-through, so nothing on it can be clicked or tabbed to and it can never
* quietly eat a gameplay click. This is the opt-in, and it grants both halves at the node:
* the row is hit-testable *and* focusable, because §2.9 states the two together.
*
* In practice that is the pointer half. Tab, Enter and Space go to the topmost screen that
* is not click-through, and the HUD is click-through so Escape still reaches the game over
* a bare one — so an opted-in row is clickable rather than tabbable. A HUD node that has to
* take the keyboard belongs on a screen that takes input.
*
* The field need not have a row yet — the opt-in is remembered and applies the moment `set`
* writes one. It is not a {@link UiProp}: a binding cannot change what a node is, so this
* re-registers the stock screen, once per opt-in rather than once per frame.
*/
hittable(field: HudField | string, on?: boolean): void
}
Import: import type { HudHandle } from "@argus/api"
Members
| Member | Signature | Description |
|---|---|---|
set | set(field: HudField, value: string | number | null, options?: HudFieldOptions): void | Set one field. With no meta.hud spec a field reads as a label and the value ("Lap 2"); options give it a label, a unit and fixed decimals: ctx.hud.set("speed", 92, { unit: "km/h" }) reads "Speed 92 km/h". An unknown option, or decimals that are not a whole number 0..6, throws. |
objective | objective(textKey: string): void | |
prompt | prompt(textKey: string | null): void | A contextual prompt ("Press E"); null hides it. |
timer | timer(seconds: number | null): void | Countdown in seconds, shown as a clock with tenths (0:02.0, 1:23.3) unless meta.hud styles it; null hides it. |
score | score(value: number): void | |
hittable | hittable(field: HudField | string, on?: boolean): void | Let one HUD row answer the hit-test and take focus. The HUD is click-through, so nothing on it can be clicked or tabbed to and it can never quietly eat a gameplay click. This is the opt-in, and it grants both halves at the node: the row is hit-testable and focusable, because §2.9 states the two together. In practice that is the pointer half. Tab, Enter and Space go to the topmost screen that is not click-through, and the HUD is click-through so Escape still reaches the game over a bare one — so an opted-in row is clickable rather than tabbable. A HUD node that has to take the keyboard belongs on a screen that takes input. The field need not have a row yet — the opt-in is remembered and applies the moment set writes one. It is not a {@link UiProp}: a binding cannot change what a node is, so this re-registers the stock screen, once per opt-in rather than once per frame. |
Example
The tested fixture fixtures/recipes/jump-pad-and-elevator/scenes/behaviors/camera-zone.ts.
import type { Behavior } from "@argus/api"
/**
* A trigger volume that retunes the camera while the player is inside it.
*
* The engine has no camera-zone concept and needs none: a volume, a `trigger` component and this.
* Here the player's behaviour owns the camera (it re-sends its params when the view is turned), so
* the zone tells it what to change rather than calling `ctx.camera.set` itself. In a scene where
* nothing else writes the camera, the zone can call `ctx.camera.set(kind, params)` directly.
*/
interface Props {
/** `ctx.camera.set` params to merge in on the way in, and on the way out. */
inside?: Record<string, unknown>
outside?: Record<string, unknown>
}
export default {
onTrigger(ctx, trigger) {
const params = trigger.entering ? ctx.props.inside : ctx.props.outside
if (params) ctx.events.emit("camera-zone", { target: trigger.other.id, params })
},
} satisfies Behavior<Record<string, never>, Props>