Skip to content

Canvas and HUD Overlays

The Canvas module draws 2D graphics composited on top of the rendered 3D viewport — ideal for HUDs, debug readouts, and simple screen-space UI. For interactive editor-style panels use Debugging (ImGui section) or ImGui.

Canvas vs ImGui

Canvas HTML5-style 2D drawing (shapes, text, images). Good for in-game HUDs and lightweight overlays.
ImGui Immediate-mode debug UI (buttons, sliders, windows). | Best for development tools and inspectors.

When to draw

Canvas commands can be issued from any lifecycle hook, but for dynamic HUDs prefer ``render()`` so drawing happens once per frame in a predictable order:

local Canvas = require 'engine/canvas'

function MyBehaviour:render()
    Canvas.setFillColor(255, 255, 255, 1)
    Canvas.setFont("24px Arial")
    Canvas.fillText("Score: " .. self.score, 20, 40)
end

Avoid heavy Canvas work in update(); use render() instead.

Persistence and clearing

Drawn content persists across frames until cleared. Either clear manually or enable auto-clear. Using auto-clear is preferred because clearing manually in a script might clear anything that another script might have already drawn. Auto clearing will clear exactly once at the beginning of a new frame.

Canvas.setAutoClear(true)   -- clears once before each render pass

-- Or explicit clear inside render:
Canvas.clear()
Canvas.fillRect(0, 0, 800, 600)  -- background bar

Command buffering

Canvas batches draw calls and commits them at the end of the frame. You rarely need to call Canvas.commit() yourself unless you are building advanced multi-pass 2D logic. See Canvas for details.

Basic drawing

local Canvas = require 'engine/canvas'

function MyBehaviour:render()
    -- Filled rectangle (HUD bar)
    Canvas.setFillColor(0, 0, 0, 0.5)
    Canvas.fillRect(10, 10, 200, 30)

    -- Text
    Canvas.setFillColor(255, 255, 255, 1)
    Canvas.setFont("18px Arial")
    Canvas.fillText("Health: " .. self.health, 20, 32)

    -- Stroke
    Canvas.setStrokeColor(255, 0, 0, 1)
    Canvas.setLineWidth(2)
    Canvas.strokeRect(10, 50, 100, 100)
end

Fonts

Load project fonts with Asset Loading or load them in the canvas fonts section of your project in the inspector then reference them by item name:

function MyBehaviour:init()
    await(Loader.loadFont("/resources/fonts/arcade"))
end

function MyBehaviour:render()
    Canvas.setFont("20px arcade")
    Canvas.fillText("GAME OVER", 100, 200)
end

Images and textures

Draw loaded texture items on the HUD (use flipY = false when loading images for Canvas):

local icon = await(Loader.loadImage("/resources/textures/icon", { flipY = false }))
Canvas.drawImage(icon, 10, 10, 64, 64)

Coordinate system

Canvas uses screen pixels with the origin at the top-left of the render viewport. Sizes follow the current viewport resolution.

Variable sets on Canvas

Variable sets pair well with Canvas debug overlays — see Variable Sets for reading global state and drawing it each frame in render().

Further reading