Appearance
UI
This chapter adds a dedicated UI layer that renders on a separate canvas above the game. We build simple UI elements (panels, text, score) and show how to toggle a pause overlay.
UI architecture (lib, ch07)
The UI system is built around three ideas:
- A second canvas overlaid on top of the game canvas.
- UI layers (
UILayer) that group UI elements. - UI elements derived from
BaseUIElementwith anchor + offset positioning.
Why this matters: once your game camera moves, you need UI that stays fixed to the screen. A separate UI canvas solves that cleanly.
BaseUIElement and anchors
BaseUIElement provides positioning via anchors:
top-left,top-right,bottom-left,bottom-right,center
Each element resolves its anchor to a point in the UI canvas, then applies offsets.
Beginner tip: anchors are just “reference points.” They stop you from doing manual pixel math every time you move a panel.
UILayer
UILayer is a container that can be shown/hidden as a group. It updates and renders all child elements if visible.
UIPanel
UIPanel draws a rectangle (or rounded rect) and then renders child elements within its bounds. It’s used as a layout container for score and lives.
ScoreDisplay and TextDisplay
These render text using a callback, which keeps UI reactive without manual updates:
getScore()for scoregetText()for pause message
That callback pattern means the UI always reflects the latest game data.
Engine integration
The engine now creates a UI canvas automatically when you add the first layer. It keeps the UI canvas aligned with the game canvas sizing and aspect ratio.
This is why UI elements don’t stretch or drift when the window resizes.
Key additions:
addUILayer()to register layers.setUiUpdateInterval(ms)to throttle UI updates.updateAndRenderUI()runs after the main render pass.
HUD and pause UI
The chapter builds two layers:
- HUD layer with score and lives.
- Pause layer with a centered “PAUSED” panel.
The pause overlay is toggled by overriding onPause() and onResume() in the engine subclass:
ts
protected override onPause(): void {
this.pauseLayer.setVisible(true);
}
protected override onResume(): void {
this.pauseLayer.setVisible(false);
}Lives indicator
ShipIndicators is a custom UI element that draws mini ship icons based on remaining lives. It uses the same anchor/offset system as the built‑in UI elements.
Why a custom element? It shows how to extend the UI system without changing the engine.
Library changes
- Added UI module:
UILayer,BaseUIElement,UIPanel,ScoreDisplay,TextDisplay. - Engine now supports UI canvases and throttled UI updates.