2D picture UI
Picture UI (UI/game.ui.json)
The data-driven game UI (one layout for menus and the HUD) takes pictures from the project's Assets. The Mac player draws it with Metal and the Deck / Linux / Windows player with OpenGL, from the same command list (UIFrame), so a layout looks the same everywhere. AppKit drawing is kept only for the editor (-appKitUI in the player brings it back).
widget kind | what it is | fields |
|---|---|---|
image | a picture, kept in shape | icon |
panel | a nine-slice frame with text | icon, slice [l, t, r, b] image pixels, border (draw size), text or binding |
imageButton | a button made of a picture (focus ring for controllers) | icon, slice, text, action (as button) |
hearts | a row of hearts: whole, half and empty | icon, iconEmpty, binding or value, maximum |
dialogue | the line, with the speaker and a portrait when given | binding "dialogue.text", portrait, icon/slice frame |
shop | a grid of items with a price; confirm buys | binding (currency item, default "coin"), icon/slice slot art |
inventory | item grid; items with an icon show their picture | items' icon |
ability, compass, styledBar | round ability slots, compass, framed bars (styled HUD) | icon, value, maximum, color |
Items: { "id": "potion", "title": "Potion", "icon": "UI/potion.png", "price": 20 }.
Scripts: game.ui("dialogue", { speaker: "Mira", text: "Hello!", portrait: "UI/mira.png" }); open a screen with game.ui("show", { screen: "shop" }). A buy pays from the player's inventory when it holds the currency and gives the item (scripts hear shop_bought); otherwise scripts get shop_buy { item, price, currency } and decide.
Controller focus moves to the nearest widget in the pressed direction (a vertical menu still wraps round); grids (inventory, shop) move their cursor first and hand focus on at their edges.
A 2D hero in a real 3D world (stage_25d)
Put stage_25d on the camera_2d object. The gameplay stays 2D (body_2d, sprites, tilemaps, 2D particles) on its plane; the world behind it is a real lit 3D scene (meshes, lights, rain, water, fog) seen through a perspective camera that follows the 2D camera. Sprites are cards lit by the scene's point lights and sun (colour, and an edge light from the brightest).
camera_2d { view_height 720 follow "Juno" } stage_25d { units_per_metre 100 plane_z 34 distance 6.5 height 1.1 look_height 0.75 fov 42 ambient 0.45 }
- Build the 3D world in metres; 2D units map to it at
units_per_metrewith the play plane at z =plane_z. - Put 3D behind the play plane; 2D quads draw over the 3D picture (foreground art goes in 2D layers in front).
- 2D backdrops are left out (the 3D world is the background) unless
backdrops true. game.cinematic25d(...)moves the real 3D camera in a stage: a boss intro orbits the 3D world.
Separate layouts for scenes
Pass scene: "Stress2D_Ember_Hollow" to add_ui_screen, bind_hud, set_ui_theme, or ui_report to work on UI/Scenes/Stress2D_Ember_Hollow.ui.json. Omit scene to work on UI/game.ui.json. Creating a scene layout starts from its chosen preset; it does not overwrite another game's HUD. The editor, play_test, and native players choose the current scene's layout, falling back to the project layout. A project containing only scene layouts uses empty HUDs and standard menus for unconfigured scenes. Scene changes reload the layout and clear temporary HUD widgets. An invalid saved layout reports an error. Exports include layouts and their referenced assets for every reachable scene. Share a project's default layout for scenes that need the same UI, or save matching scene layouts when several games share one project.