@origingame/engine 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/bin/og.mjs +1 -1
  2. package/dist/web/origin-engine.d.ts +219 -5
  3. package/dist/web/origin-engine.js +1344 -125
  4. package/dist/web/origin-engine_bg.wasm +0 -0
  5. package/dist/web/origin-engine_bg.wasm.d.ts +68 -3
  6. package/dist/web-publish/origin-engine-lanes.js +1007 -22
  7. package/dist/web-publish/origin-engine-lanes_bg.wasm +0 -0
  8. package/dist/web-publish/origin-engine.d.ts +162 -5
  9. package/dist/web-publish/origin-engine.js +1004 -19
  10. package/dist/web-publish/origin-engine_bg.wasm +0 -0
  11. package/dist/web-publish/origin-engine_bg.wasm.d.ts +52 -3
  12. package/dist/web-publish-2d/origin-engine-lanes.js +1007 -22
  13. package/dist/web-publish-2d/origin-engine-lanes_bg.wasm +0 -0
  14. package/dist/web-publish-2d/origin-engine.d.ts +162 -5
  15. package/dist/web-publish-2d/origin-engine.js +1004 -19
  16. package/dist/web-publish-2d/origin-engine_bg.wasm +0 -0
  17. package/dist/web-publish-2d/origin-engine_bg.wasm.d.ts +52 -3
  18. package/knowledge/looks/catalogue.json +40 -40
  19. package/knowledge/package.json +4 -4
  20. package/knowledge/scaffold/distribution.json +14 -0
  21. package/knowledge/scaffold/origin-engine.json +2 -2
  22. package/knowledge/scaffold/template/README.md +2 -1
  23. package/knowledge/scaffold/template/assets/audio/sting.ogt +10 -0
  24. package/knowledge/scaffold/template/assets/timelines/intro.ogt +101 -0
  25. package/knowledge/scaffold/template/assets/timelines/narration.srt +11 -0
  26. package/knowledge/scaffold/template/host.d.ts +46 -0
  27. package/knowledge/scaffold/template/package.json +1 -1
  28. package/knowledge/scaffold/template/project.ogt +1 -1
  29. package/knowledge/scaffold/template/src/main.ts +1 -1
  30. package/knowledge/scaffold/template/tests/frames.ts +134 -0
  31. package/knowledge/scaffold/template/tests/intro.og.ts +65 -0
  32. package/knowledge/scaffold/template/tests/smoke.og.ts +30 -36
  33. package/knowledge/scaffold/template/tsconfig.json +1 -1
  34. package/knowledge/scripts/mount.ts +2 -1
  35. package/knowledge/scripts/validate.ts +21 -11
  36. package/knowledge/skills/og-build/SKILL.md +25 -6
  37. package/knowledge/skills/og-core/SKILL.md +11 -0
  38. package/knowledge/skills/og-feel/SKILL.md +8 -1
  39. package/knowledge/skills/og-game/SKILL.md +994 -21
  40. package/knowledge/skills/og-i18n/SKILL.md +12 -3
  41. package/knowledge/skills/og-platform-sdk/SKILL.md +4 -1
  42. package/knowledge/skills/og-taste/SKILL.md +82 -73
  43. package/knowledge/skills/og-ui/SKILL.md +82 -54
  44. package/knowledge/wiki/ai.md +20 -20
  45. package/knowledge/wiki/anim.md +384 -41
  46. package/knowledge/wiki/atmosphere.md +36 -13
  47. package/knowledge/wiki/audio.md +18 -18
  48. package/knowledge/wiki/camera.md +19 -13
  49. package/knowledge/wiki/commands.md +19 -13
  50. package/knowledge/wiki/debug.md +414 -0
  51. package/knowledge/wiki/game.md +8 -8
  52. package/knowledge/wiki/i18n.md +7 -7
  53. package/knowledge/wiki/index.md +265 -7
  54. package/knowledge/wiki/input.md +47 -47
  55. package/knowledge/wiki/load.md +236 -68
  56. package/knowledge/wiki/math.md +2614 -7
  57. package/knowledge/wiki/nav.md +34 -34
  58. package/knowledge/wiki/net.md +340 -0
  59. package/knowledge/wiki/path.md +402 -0
  60. package/knowledge/wiki/physics.md +124 -106
  61. package/knowledge/wiki/platform.md +465 -31
  62. package/knowledge/wiki/probe.md +681 -67
  63. package/knowledge/wiki/reflect.md +15 -15
  64. package/knowledge/wiki/render.md +3904 -1897
  65. package/knowledge/wiki/rng.md +14 -14
  66. package/knowledge/wiki/stream.md +15 -15
  67. package/knowledge/wiki/system.md +8 -8
  68. package/knowledge/wiki/systems.md +2 -2
  69. package/knowledge/wiki/terrain.md +19 -19
  70. package/knowledge/wiki/tilemap.md +19 -15
  71. package/knowledge/wiki/time.md +4 -4
  72. package/knowledge/wiki/timeline.md +396 -0
  73. package/knowledge/wiki/transform.md +8 -8
  74. package/knowledge/wiki/tween.md +17 -17
  75. package/knowledge/wiki/ui.md +603 -629
  76. package/knowledge/wiki/video.md +157 -0
  77. package/knowledge/wiki/world.md +67 -37
  78. package/package.json +7 -6
  79. package/schema/api.schema.json +21071 -13964
  80. package/shell/page.ts +26 -2
  81. package/shell/platform.ts +46 -0
  82. package/shell/player.ts +7 -0
  83. package/src/depth.ts +71 -0
  84. package/src/e6.ts +32 -1
  85. package/src/env.d.ts +5 -1
  86. package/src/generated/abi.ts +189 -3
  87. package/src/index.ts +26 -4
  88. package/src/light.ts +18 -0
  89. package/src/math.ts +622 -0
  90. package/src/node/index.ts +17 -0
  91. package/src/node/playtest-run.ts +114 -18
  92. package/src/node/polish.ts +15 -4
  93. package/src/node/render.ts +291 -0
  94. package/src/node/run.ts +91 -6
  95. package/src/p2.ts +19 -1
  96. package/src/playtest.ts +57 -4
  97. package/src/runtime.ts +15 -3
  98. package/src/targets.ts +28 -0
  99. package/src/trace.ts +169 -0
  100. package/src/ui-kit/huds.ts +49 -45
  101. package/src/ui-kit/menus.ts +12 -12
  102. package/src/ui-kit/settings.ts +2 -2
  103. package/src/ui-kit/store.ts +18 -18
  104. package/src/ui-kit/story.ts +6 -4
  105. package/src/ui-kit/util.ts +8 -8
  106. package/src/web/shell.ts +58 -0
  107. package/src/web/worker.ts +103 -2
  108. package/types/bindings.json +8945 -6456
  109. package/types/index.d.ts +15507 -11437
@@ -70,7 +70,9 @@ string "results.time" "タイム {time}"
70
70
  - Numbers, times and prices go through arguments, not string building.
71
71
  - og.ui's templates have words of their own (Retry, Share, "Best 1,200",
72
72
  "New best", Cancel, Settings, Buy, Skip, "1 of 3", a racing HUD's
73
- "lap", "Best 1:36.233", Pause and Boost): each is a field of
73
+ "lap", "Best 1:36.233", Pause and Boost, the other HUDs' Jump, Fire,
74
+ "kills", "moves left", "Target 1,000", "Lv 3" and "+12/s"): each is a
75
+ field of
74
76
  the template's desc with the English default, so a localised game passes
75
77
  its table's: `ResultsDesc.bestLabel`, `newBestLabel`, `shareLabel`,
76
78
  `actions`; `ConfirmDesc.confirmLabel`, `cancelLabel`; `SettingsDesc.title`,
@@ -90,12 +92,19 @@ string "results.time" "タイム {time}"
90
92
  ("Best {best}", the best lap as m:ss.mmm), `pauseLabel` (the pause
91
93
  button's name), `boostLabel`, `brakeLabel`, `leftLabel`, `rightLabel`
92
94
  (the touch pedals and arrows) and `unit`, and its `splits`' labels
93
- (`S1`) are the game's. `bestLabel: og.i18n.t(world, "results.best")`
95
+ (`S1`) are the game's; `PlatformerHudDesc.pauseLabel`, `jumpLabel`
96
+ (the touch Jump); `ShooterHudDesc.killsLabel` (after the count),
97
+ `fireLabel`, `pauseLabel`; `PuzzleHudDesc.movesLabel` (under the moves
98
+ left), `targetLabel` ("Target {target}"), `pauseLabel`;
99
+ `IdleHudDesc.tapLabel`, `levelLabel` ("Lv {level}", a generator's
100
+ badge), `rateLabel` ("+{rate}/s"), `pauseLabel`. Names, levels,
101
+ weapons, currencies and a map's label are the game's data, from its
102
+ table too. `bestLabel: og.i18n.t(world, "results.best")`
94
103
  with `"Best {best}"` / `"最佳 {best}"` in the tables (the template fills
95
104
  `{best}`, formatted); `stepLabel` the same with `"{step} of {count}"` /
96
105
  `"第 {step} 步,共 {count} 步"`. templates/ui-kit passes every one of
97
106
  these words from its five tables (`settings.*`, `shop.*`, `inventory.*`,
98
- `leaderboard.*`, `tutorial.*`, `cutscene.*`).
107
+ `leaderboard.*`, `tutorial.*`, `cutscene.*`, the HUDs' `hud.*`).
99
108
  - Emphasis inside a sentence is rich-text markup in the message itself
100
109
  (`"Your progress in slot [b]{slot}[/b] will be lost."`, shown with
101
110
  `og.ui.richText`): each translation bolds or colours its own words, in
@@ -61,7 +61,9 @@ if (answer.ok && typeof answer.data.value === "number") run.best[i] = Math.max(r
61
61
  - Answers are host input, like key presses: a replay records them, so the
62
62
  same answers give the same world.
63
63
  - Every answer carries `time` (UTC ms): the host's clock when it was
64
- answered. `og.platform.now(world)` is the host's clock at the last
64
+ answered (a `saveSlot` or `loadSlot` answer, the time of the store
65
+ answer that ended it, so a slot's load is as good a clock as a
66
+ `storeGet`). `og.platform.now(world)` is the host's clock at the last
65
67
  answer (or when the platform attached) advanced by the ticks since, so
66
68
  it is the one wall clock a game may read: the time away is a store
67
69
  answer's `time` less the time the save wrote down
@@ -84,6 +86,7 @@ if (answer.ok && typeof answer.data.value === "number") run.best[i] = Math.max(r
84
86
  | Analytics | `telemetry(world, "round.over", { score, coins })` | one-way; a name of 1–64 letters, digits, `.` and `_` (the Player files it as `game.custom.<name>`), at most 16 scalar attributes; never personal data |
85
87
  | Origin Point | `point(world, { reason, amount })` | the platform decides what it grants (today nothing under a Player: `{ granted: 0, balance: null }` until an approved point policy; show nothing that depends on it) |
86
88
  | AI-generated content shown | `aiMark(world, { kind, label })` | disclosure, not permission |
89
+ | Play with others in one room | `roomCreate(world, { name })`, `roomJoin(world, room)`, `roomLeave`, `roomSend(world, data, to?)`, `roomPeers`, `roomInfo`; the answers as `og.RoomJoined`, `og.RoomPeerJoined`, `og.RoomPeerLeft`, `og.RoomMessage` (read one with `roomMessage`) | natively `og relay` with `og run --room ws://127.0.0.1:P/<room>`; on the web the Player's rooms, when its hello lists `room.join` (`roomInfo(world).host` is `none` otherwise and joins are refused). A message is this peer's host input only: for a game both peers simulate, use og.net's lockstep (`og.Lockstep`, `og.PlayerInput`, og-game §20) and send nothing yourself |
87
90
 
88
91
  `og.platform.info(world)` says what answers here (`player`, `local` or
89
92
  `none`) and the methods it answers (`capabilities`): check it rather than
@@ -1,13 +1,14 @@
1
1
  ---
2
2
  name: og-taste
3
- description: Art direction for a game on Origin Engine — choosing a style from the premise (genre, mood, era, audience) out of a 37-style catalogue and binding it as a look (post stack, stylisation, material defaults, skin) with a UI skin, a palette and a type ramp; composition and hierarchy on the play surface, colour, typography, motion, feedback and consistency; atmosphere (fog, sky, time of day, weather, water); the anti-patterns that make a game look like a web form; and the checklist to run (with og run captures and dump_ui) before calling a game done. Use when starting a game's look, building or reviewing any screen or HUD, or when a game "works but looks generic".
3
+ description: Art direction for a game on Origin Engine — choosing a style from the premise (genre, mood, era, audience) out of a 37-style catalogue and binding it as a look (post stack, stylisation, material defaults, the UI style) with a palette and a type ramp; composition and hierarchy on the play surface, colour, typography, motion, feedback and consistency; atmosphere (fog, sky, time of day, weather, water); the anti-patterns that make a game look like a web form; and the checklist to run (with og run captures and dump_ui) before calling a game done. Use when starting a game's look, building or reviewing any screen or HUD, or when a game "works but looks generic".
4
4
  ---
5
5
 
6
6
  A game is judged in its first second, before anyone reads a word. The
7
- engine's UI is correct by default and characterless by default: the platform
8
- tokens are grey glass that suits a settings page. This skill is how to give a
9
- game a look of its own and keep it consistent. The mechanics are og-ui's
10
- (skins, motion and sounds are og-ui §6) and the amounts of game feel
7
+ engine's UI is correct by default and characterless by default: its
8
+ placeholder style, `prototype`, is greys and square corners meant to be
9
+ replaced, and the game's UI never borrows the Origin platform's look. This
10
+ skill is how to give a game a look of its own and keep it consistent. The
11
+ mechanics are og-ui's (styles, motion and sounds are og-ui §6) and the amounts of game feel
11
12
  og-feel's; this is the taste.
12
13
 
13
14
  ## What works
@@ -57,11 +58,16 @@ for a new game and writes the result (`--look <slug>` names it instead):
57
58
  `assets/looks/<game>.ogt` extending the preset, named by `GameDesc.look`,
58
59
  with a README section on changing it. For a game that exists, write the
59
60
  same file by hand (§12) and add `look: "looks/<game>.ogt"` to `og.game`.
60
- The entry also names the palette rules, the asset specs and the skin pack
61
- that matches it. Then pick **one** starting skin. The six packs in the engine's
62
- `templates/ui-kit/assets/skins/` are starting points, not the only looks:
63
-
64
- | Pack | Premises it fits | Signature | Start look (§12) |
61
+ The entry also names the palette rules, the asset specs and the UI style
62
+ its preset carries (the look's `ui` line, §12), so a game that extends a
63
+ preset is dressed by it from the first frame. The game's UI follows the
64
+ game's art, never the Origin platform's: without a style it draws in the
65
+ engine's placeholder `prototype` (greys, near-square corners, a cyan focus
66
+ ring), and `og polish` warns when a game ships in it. The six built-in
67
+ styles in the engine's `templates/styles/` are starting points, not the
68
+ only looks:
69
+
70
+ | Style | Premises it fits | Signature | Start look (§12) |
65
71
  |---|---|---|---|
66
72
  | `pixel` | platformers, roguelikes, retro shooters, jam games | square frames, 2 px bevels, hard shadows, a bitmap face | `16bit-pixel` |
67
73
  | `cartoon` | casual, match-3, party, kids, idle | thick outlines, cream panels, squash on press, pops | `bold-comic-illustration` |
@@ -70,88 +76,90 @@ that matches it. Then pick **one** starting skin. The six packs in the engine's
70
76
  | `paper` | narrative, puzzle, cosy, mystery, word games | off-white sheets, ink outlines, soft shadows, one red | `pencil-hatching` |
71
77
  | `neon` | arcade, rhythm, racing, synthwave | dark glass, glowing tubes, italic display | `neon-vector` |
72
78
 
73
- ```ts
74
- const skin = og.load.skin(world, "skins/fantasy/skin.ogt");
75
- if (skin.ok) og.ui.configure(world, { skin: skin.value });
79
+ ```text
80
+ ui "fantasy" # in the game's look: a built-in style by slug
81
+ ui "styles/harbour/style.ogt" # or the game's own
76
82
  ```
77
83
 
78
- Make it the game's own by changing the skin file, never by passing colours
79
- to individual calls: copy the pack directory into the game's
80
- `assets/skins/<game>/` (`cp -R .../skins/fantasy assets/skins/<game>`) and
81
- load `skins/<game>/skin.ogt`. Nothing in it needs rewriting: the ids in a
82
- skin file are read relative to the file first (`atlas "atlas.png"`, `body
83
- "Newsreader-Medium.ttf"`), then from `assets/` (`skins/fantasy/atlas.png`
84
- still works). The one asset outside the pack is its CJK `fallback`,
85
- `fonts/NotoSansSC-Regular-subset.ttf` (2.5 MB, shared by every pack, so
86
- not copied six times): a project made by `npm create @origingame/game`
87
- has it at that id; otherwise point the line at the game's own CJK font,
88
- or delete it when the game shows no Chinese, Japanese or Korean (the cook
89
- names the line it cannot find). Then change `palette` (start with
90
- `accent`, `bg`, `surface`, `fg`), `ramp` and `fonts` (any OFL font beside
91
- the skin file), and redraw the atlas if the frames should change (`og skin
92
- pack`, og-ui §6). The art in the art direction of the
93
- world (sprites, backgrounds) and the skin must agree: a pixel-art world in a
84
+ Make it the game's own by changing the style file, never by passing colours
85
+ to individual calls: copy the built-in's directory into the game's
86
+ `assets/styles/<game>/` (`cp -R .../templates/styles/fantasy
87
+ assets/styles/<game>`) and name it in the look (`ui
88
+ "styles/<game>/style.ogt"`). Nothing in it needs rewriting: the ids in a
89
+ style file are read relative to the file first (`atlas "atlas.png"`, `body
90
+ "Newsreader-Medium.ttf"`), then from `assets/`. A style is complete: it
91
+ names every palette role and the four radii (`small`, `control`, `bar`,
92
+ `panel`), so nothing of it comes from anywhere else. Then change `palette`
93
+ (start with `primary`, `backdrop`, `panel`, `ink`), `radius`, `ramp` and
94
+ `fonts` (any OFL font beside the style file), and redraw the atlas if the
95
+ frames should change (`og style pack`, og-ui §6). A game that shows Chinese,
96
+ Japanese or Korean adds a `fallback` font to its style (or its string
97
+ table's `fonts` line, og-i18n). For a quick re-colour without a copy,
98
+ `og.ui.configure(world, { primaryColor })` derives the primary's hover,
99
+ pressed and soft tones and the ink on it. The art direction of the world
100
+ (sprites, backgrounds) and the style must agree: a pixel-art world in a
94
101
  neon UI reads as two games.
95
102
 
96
103
  ## 2. Composition and hierarchy
97
104
 
98
105
  - **What the eye reads first**: decide the one thing per screen (the score on
99
106
  results, Play on the title, the health on a HUD) and make it the biggest,
100
- the brightest or the only accent-coloured thing. If two things compete,
107
+ the brightest or the only thing in the primary colour. If two things compete,
101
108
  shrink one.
102
109
  - **The play surface is the hero**: a HUD sits in the corners and edges
103
110
  (anchors `topLeft`, `topRight`, `bottom`), never across the middle. Keep
104
111
  the centre third free during play.
105
- - **HUD weight**: at most three HUD groups visible at once; each is a capsule
106
- with an icon and a number, not a panel with labels. Move rarely needed
112
+ - **HUD weight**: at most three HUD groups visible at once; each is a HUD box
113
+ (`frame: "hud"`) with an icon and a number, not a panel with labels. Move rarely needed
107
114
  information behind pause.
108
115
  - **Safe area**: everything interactive inside `og.ui.frameViewport().safeArea`
109
116
  plus the density gutter; anchors do this for you, absolute positions do not.
110
117
  - **Phone vs desktop**: on `phonePortrait` the thumb zone is the bottom third:
111
118
  primary actions go there, touch controls at least 44 CSS px apart; titles
112
- shrink one step (`displayMd` instead of `displayLg`). On desktop, menus sit
119
+ shrink one step (`xl2` instead of `xl3`). On desktop, menus sit
113
120
  centred or left, never full-width.
114
121
  - **Grouping**: spacing does the grouping. Related things are `space.sm`
115
122
  apart, groups `space.lg` or more. Do not draw a box around everything.
116
123
 
117
124
  ## 3. Colour
118
125
 
119
- - **Limited palette**: a ground (`bg`), one or two surfaces, one ink (`fg`)
120
- with a muted ink, **one accent**, and the status colours. That is the whole
121
- palette; a skin declares exactly these.
122
- - **One accent**, used for the one primary action per screen, earned stars,
123
- the player's own row and focus. If everything is accent, nothing is.
126
+ - **Limited palette**: a ground (`backdrop`), one or two surfaces (`panel`,
127
+ `panelRaised`), one ink (`ink`) with a muted ink (`inkMuted`), **one
128
+ primary**, and the status colours. That is the whole palette; a style
129
+ declares these and the roles derived from them.
130
+ - **One primary**, used for the one primary action per screen, earned stars,
131
+ the player's own row and focus. If everything is primary, nothing is.
124
132
  - **Value before hue**: check the screen in greyscale. Text, the primary
125
133
  button and the player character must separate from their ground by value
126
134
  alone (body text at least 4.5:1; the packs' test enforces it for theirs:
127
135
  every label ink, every button label in every state, a text field's
128
- placeholder, which draws in `fgSubtle` on the field's frame, and an
129
- accent badge, `accentInk` on `accentSoft` over a panel (the results
136
+ placeholder, which draws in `inkFaint` on the field's frame, and a
137
+ primary badge, `highlight` on `primarySoft` over a panel (the results
130
138
  screen's "New best"), and a status badge in each of `success`, `warn`,
131
139
  `danger` and `info` (the tone's own ink on its 16 % tint), so a copied
132
- pack whose `fgSubtle`, `fill`, `accentInk`, `accentSoft` or a status
140
+ style whose `inkFaint`, `control`, `highlight`, `primarySoft` or a status
133
141
  colour moves must keep those pairs at 4.5:1 too. The status colours are
134
142
  also the meters', toasts' and status dots' colours: on a cream panel they
135
- are deep (the cartoon pack's warn is `#7b5102`, not a bright amber that
136
- read 1.63:1), on a dark one light (a red under a dark pack's panel is a
143
+ are deep (the cartoon style's warn is `#7b5102`, not a bright amber that
144
+ read 1.63:1), on a dark one light (a red under a dark style's panel is a
137
145
  salmon such as `#ff8080`). Make them for the panels; a badge placed on
138
- the other side of the scale (a light pack's badge straight on its dark
146
+ the other side of the scale (a light style's badge straight on its dark
139
147
  stage) moves its own ink towards white or black until it reads there,
140
148
  and the neutral badge does the same on its `fill`, so neither needs a
141
- second palette. A game's copied skin is held to the same bars: the
149
+ second palette. A game's own style is held to the same bars: the
142
150
  engine's `pack_contrast.rs` measures the archetypes' and examples'
143
- skins too, and their fixes were value, not hue (pathguard's lantern
151
+ styles too, and their fixes were value, not hue (pathguard's lantern
144
152
  orange deepened under a cream label, sparkorb's gold to a burnished
145
153
  amber under its cream ink, lampdive's plum fill darkened under its
146
154
  placeholder, Lantern Vale's status colours taken back to the fantasy
147
- pack's deep ones);
155
+ style's deep ones);
148
156
  it also reads the primary and secondary labels from a rendered frame,
149
157
  where thin strokes may never reach their colour: a pixel font's one-pixel
150
- strokes fall between pixels and took half their ink, so the pixel pack
158
+ strokes fall between pixels and took half their ink, so the pixel style
151
159
  thickens them with `textWeight body 0.5` and cooks DotGothic16 at
152
- `px_range 8`; a copy of the pack made before that needs both lines).
160
+ `px_range 8`; a copy of the style made before that needs both lines).
153
161
  - Saturated colour on large areas tires the eye: keep saturation for small
154
- things (the accent, icons, effects) and keep grounds calmer.
162
+ things (the primary, icons, effects) and keep grounds calmer.
155
163
  - Status colours mean status: never use `danger` red as decoration.
156
164
 
157
165
  ## 4. Typography
@@ -163,22 +171,22 @@ neon UI reads as two games.
163
171
  - **Numerals**: scores, timers, prices and stats in the numeric role
164
172
  (`font: "mono"`), so digits do not jitter as they count; big scores in the
165
173
  display face. Count them with `og.ui.counter`, never by setting text.
166
- - **A ramp, not sizes**: use the skin's steps (`displayLg`, `xl`, `body`,
174
+ - **A ramp, not sizes**: use the style's steps (`xl3`, `xl`, `body`,
167
175
  `meta`); three or four steps per screen at most. Each step carries its
168
- tracking (display sizes tighten, as the tokens do; a skin's `ramp` line
176
+ tracking (display sizes tighten; a style's `ramp` line
169
177
  takes it as its fourth number after the CJK leading), and it is applied
170
178
  to Latin text only.
171
- - Headings get `heading: true` so the skin's flourish frames them.
179
+ - Headings get `heading: true` so the style's flourish frames them.
172
180
 
173
181
  ## 5. Motion
174
182
 
175
183
  - Every change of state moves; nothing pops in or out without a transition
176
184
  unless reduced motion is on.
177
- - **Durations 120 to 300 ms** for UI (the skin's `durations`), up to 700 ms
185
+ - **Durations 120 to 300 ms** for UI (the style's `durations`), up to 700 ms
178
186
  for a screen transition, longer only for rewards. **Never linear**: ease
179
187
  out on arrival, ease in on exit.
180
188
  - **Anticipation and follow-through**: a press squashes before the action
181
- (`press` in the skin), a reward overshoots and settles (`pop`, `motion.pop`).
189
+ (`press` in the style), a reward overshoots and settles (`pop`, `motion.pop`).
182
190
  - **Stagger**: a panel's controls arrive one after another (`motion.stagger`
183
191
  30–60 ms), not all at once.
184
192
  - **Screens change through a transition** (`og.ui.screenTransition`): fade
@@ -190,22 +198,22 @@ neon UI reads as two games.
190
198
  ## 6. Feedback
191
199
 
192
200
  Every input is answered **on the same tick** (og-feel §1) by a visual and a
193
- sound: hover (the skin's lift or highlight), press (squash, the `press`
201
+ sound: hover (the style's lift or highlight), press (squash, the `press`
194
202
  sound), success (a toast, a burst, `success`), refusal (a disabled button
195
203
  shakes and plays `error` by itself; a wrong answer or a locked door shakes
196
204
  its element with `og.ui.shake` and the `error` sound; never silently ignore
197
205
  a press, and never shake the camera for it). Hand the UI its sounds with
198
206
  `og.ui.configure(world, { sounds: { hover, press, open, close, success, error } })`
199
- or the skin's `sound` lines. Results land with a count-up, stars with a
207
+ or the style's `sound` lines. Results land with a count-up, stars with a
200
208
  `og.ui.burst`, rewards with a pop.
201
209
 
202
210
  ## 7. Consistency
203
211
 
204
- - **One skin per game.** Every screen, dialog and HUD uses it.
205
- - **One radius scale**: the skin's `radius`; never pass radii by hand.
206
- - **One shadow direction**: the skin's shadows all fall the same way (down);
212
+ - **One style per game.** Every screen, dialog and HUD uses it.
213
+ - **One radius scale**: the style's `radius`; never pass radii by hand.
214
+ - **One shadow direction**: the style's shadows all fall the same way (down);
207
215
  in-world shadows should agree.
208
- - **One icon set**: the skin's `icons`; do not mix icon styles.
216
+ - **One icon set**: the style's `icons`; do not mix icon styles.
209
217
  - **One transition kind** for screen changes, one entrance for dialogs.
210
218
 
211
219
  ## 8. Atmosphere
@@ -255,15 +263,16 @@ Each of these is a defect, not a style choice:
255
263
  - the HUD as a toolbar: a full-width bar of labelled boxes across the top;
256
264
  - labels instead of icons on the HUD ("Health: 72/100" instead of a heart
257
265
  and a bar);
258
- - every colour saturated, or every button in the accent;
266
+ - every colour saturated, or every button in the primary colour;
259
267
  - a settings-page layout (left-aligned form rows) for a title screen.
260
268
 
261
269
  ## 10. The checklist before a game is done
262
270
 
263
271
  Run each item; each is checkable from a scripted run.
264
272
 
265
- 1. **A skin is configured**: `og.ui.theme(world).skin` is not empty (log it
266
- from a command, or read it in a playtest through a `facts` field).
273
+ 1. **A style is configured**: `og.ui.theme(world).style` is not empty and
274
+ not `prototype` (log it from a command, or read it in a playtest through
275
+ a `facts` field).
267
276
  2. **Title, pause and results screens captured**: `og run --headless --commands
268
277
  "0.5:show:title;1.5:screenshot:title.png;…"` (with the game's own commands);
269
278
  look at each capture in greyscale: the one thing per screen reads first.
@@ -277,7 +286,7 @@ Run each item; each is checkable from a scripted run.
277
286
  `og run --size 1170x2532`) and check in `dump_ui` that every control is at
278
287
  least 44 × 44 CSS px and nothing leaves the safe area.
279
288
  6. **Text legible**: body text at 13 px or more in `dump_ui` heights (a line
280
- of at least 16 px); the skin passes 4.5:1 (the packs' test, or the same
289
+ of at least 16 px); the style passes 4.5:1 (the built-ins' test, or the same
281
290
  check over your atlas).
282
291
  7. **Motion present**: captures 100 ms apart after `show:` differ (an
283
292
  entrance), and a score `dump_ui` text read twice during the results
@@ -290,7 +299,7 @@ Run each item; each is checkable from a scripted run.
290
299
  10. **Reduced motion**: with `reducedMotion: true` the captures show fades
291
300
  only, and nothing is missing.
292
301
  11. **CJK**: switch the language to Chinese in settings and capture: no
293
- missing-glyph boxes (the skin's fallback font covers it).
302
+ missing-glyph boxes (the style's or the string table's fallback font covers it).
294
303
  12. **None of section 9** is visible in any capture.
295
304
  13. **`og polish .` scores taste 90 or more** where it applies, and every
296
305
  finding left is one you read in the frames and can name a reason for
@@ -303,7 +312,7 @@ occupancy, screen transitions, UI sounds, locale keys) from the frames, the
303
312
  UI trees and the run's audio, with og-feel's measures beside it; og-build §5
304
313
  is the one list of its measures, thresholds and fixes. The numbers cannot
305
314
  judge a style: read the frames before changing anything, and fix the cause
306
- in the skin or the template, never per call.
315
+ in the style or the template, never per call.
307
316
 
308
317
  ## 12. Style catalogue: looks
309
318
 
@@ -311,7 +320,7 @@ A style is chosen once per game and then held by data, not by habit: the
311
320
  **look** (`assets/looks/<game>.ogt`, an `.ogt` of `type look`) binds the
312
321
  frame's whole treatment (tone mapping and exposure, the post stack, the
313
322
  stylisation primitives, material defaults such as toon shading and
314
- outlines, fog and sky, the UI skin and the antialiasing) in one diffable
323
+ outlines, fog and sky, the UI style and the antialiasing) in one diffable
315
324
  file. The engine ships the primitives and the presets; the taste is in
316
325
  which one you pick and how you tune it.
317
326
 
@@ -320,7 +329,7 @@ describes 37 styles in four families (pixel and retro, paint and line,
320
329
  shape and material, 3D rendering). For each: a one-line descriptor, three
321
330
  checks a critic can judge on a captured frame, the premises it fits
322
331
  (genre, mood, era, audience, as §1 asks them), the preset it maps to, the
323
- skin pack, palette constraints, asset specs (logical resolution, sprite
332
+ UI style (`ui`), palette constraints, asset specs (logical resolution, sprite
324
333
  scale, face budget, outline width, texture density) and an art-bible
325
334
  direction. Match the premise's four answers against `premise`, shortlist
326
335
  two, and choose by the checks you can actually hold for the whole game.
@@ -344,7 +353,7 @@ version 1
344
353
  ---
345
354
  name "Harbour at dusk"
346
355
  extends "anime-cel-3d" # the preset's slug (templates/looks/<slug>.ogt)
347
- skin "skins/harbour/skin.ogt" # the game's own copy of the style's skin pack
356
+ ui "styles/harbour/style.ogt" # the game's own UI style (the preset names a built-in)
348
357
  RenderSettings {
349
358
  toneMapping agx
350
359
  exposure 1.1
@@ -455,8 +464,8 @@ middle ground.
455
464
 
456
465
  Name it in the game (`og.game({ look: "looks/harbour.ogt", … })`) and it
457
466
  is applied after the first scene spawns and before `start` runs (so
458
- `start` may still change any field, and reads the look's skin from
459
- `og.render.look(world)?.skin`); switch looks at a tick with
467
+ `start` may still change any field, and reads the look's UI style from
468
+ `og.render.look(world)?.style`); switch looks at a tick with
460
469
  `og.load.look` and `og.render.applyLook` (a flashback, a photo mode, an
461
470
  area's mood). A look's `MaterialStyle` reaches every lit material that
462
471
  leaves the field at its default; a material that must stay as made (a
@@ -492,7 +501,7 @@ in its style step (`docs/platform-asks.md` in the engine repository): the
492
501
  catalogue entry chosen from the premise, the look written, and the
493
502
  entry's three checks handed to the critic that reads the frames.
494
503
 
495
- | Slug | Family | Style | Support | Skin |
504
+ | Slug | Family | Style | Support | UI |
496
505
  |---|---|---|---|---|
497
506
  | `expressionist-painting` | Paint and line | Expressionist paint | content | `paper` |
498
507
  | `bold-comic-illustration` | Paint and line | Bold comic illustration | full | `fantasy` |