@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.
- package/bin/og.mjs +1 -1
- package/dist/web/origin-engine.d.ts +219 -5
- package/dist/web/origin-engine.js +1344 -125
- package/dist/web/origin-engine_bg.wasm +0 -0
- package/dist/web/origin-engine_bg.wasm.d.ts +68 -3
- package/dist/web-publish/origin-engine-lanes.js +1007 -22
- package/dist/web-publish/origin-engine-lanes_bg.wasm +0 -0
- package/dist/web-publish/origin-engine.d.ts +162 -5
- package/dist/web-publish/origin-engine.js +1004 -19
- package/dist/web-publish/origin-engine_bg.wasm +0 -0
- package/dist/web-publish/origin-engine_bg.wasm.d.ts +52 -3
- package/dist/web-publish-2d/origin-engine-lanes.js +1007 -22
- package/dist/web-publish-2d/origin-engine-lanes_bg.wasm +0 -0
- package/dist/web-publish-2d/origin-engine.d.ts +162 -5
- package/dist/web-publish-2d/origin-engine.js +1004 -19
- package/dist/web-publish-2d/origin-engine_bg.wasm +0 -0
- package/dist/web-publish-2d/origin-engine_bg.wasm.d.ts +52 -3
- package/knowledge/looks/catalogue.json +40 -40
- package/knowledge/package.json +4 -4
- package/knowledge/scaffold/distribution.json +14 -0
- package/knowledge/scaffold/origin-engine.json +2 -2
- package/knowledge/scaffold/template/README.md +2 -1
- package/knowledge/scaffold/template/assets/audio/sting.ogt +10 -0
- package/knowledge/scaffold/template/assets/timelines/intro.ogt +101 -0
- package/knowledge/scaffold/template/assets/timelines/narration.srt +11 -0
- package/knowledge/scaffold/template/host.d.ts +46 -0
- package/knowledge/scaffold/template/package.json +1 -1
- package/knowledge/scaffold/template/project.ogt +1 -1
- package/knowledge/scaffold/template/src/main.ts +1 -1
- package/knowledge/scaffold/template/tests/frames.ts +134 -0
- package/knowledge/scaffold/template/tests/intro.og.ts +65 -0
- package/knowledge/scaffold/template/tests/smoke.og.ts +30 -36
- package/knowledge/scaffold/template/tsconfig.json +1 -1
- package/knowledge/scripts/mount.ts +2 -1
- package/knowledge/scripts/validate.ts +21 -11
- package/knowledge/skills/og-build/SKILL.md +25 -6
- package/knowledge/skills/og-core/SKILL.md +11 -0
- package/knowledge/skills/og-feel/SKILL.md +8 -1
- package/knowledge/skills/og-game/SKILL.md +994 -21
- package/knowledge/skills/og-i18n/SKILL.md +12 -3
- package/knowledge/skills/og-platform-sdk/SKILL.md +4 -1
- package/knowledge/skills/og-taste/SKILL.md +82 -73
- package/knowledge/skills/og-ui/SKILL.md +82 -54
- package/knowledge/wiki/ai.md +20 -20
- package/knowledge/wiki/anim.md +384 -41
- package/knowledge/wiki/atmosphere.md +36 -13
- package/knowledge/wiki/audio.md +18 -18
- package/knowledge/wiki/camera.md +19 -13
- package/knowledge/wiki/commands.md +19 -13
- package/knowledge/wiki/debug.md +414 -0
- package/knowledge/wiki/game.md +8 -8
- package/knowledge/wiki/i18n.md +7 -7
- package/knowledge/wiki/index.md +265 -7
- package/knowledge/wiki/input.md +47 -47
- package/knowledge/wiki/load.md +236 -68
- package/knowledge/wiki/math.md +2614 -7
- package/knowledge/wiki/nav.md +34 -34
- package/knowledge/wiki/net.md +340 -0
- package/knowledge/wiki/path.md +402 -0
- package/knowledge/wiki/physics.md +124 -106
- package/knowledge/wiki/platform.md +465 -31
- package/knowledge/wiki/probe.md +681 -67
- package/knowledge/wiki/reflect.md +15 -15
- package/knowledge/wiki/render.md +3904 -1897
- package/knowledge/wiki/rng.md +14 -14
- package/knowledge/wiki/stream.md +15 -15
- package/knowledge/wiki/system.md +8 -8
- package/knowledge/wiki/systems.md +2 -2
- package/knowledge/wiki/terrain.md +19 -19
- package/knowledge/wiki/tilemap.md +19 -15
- package/knowledge/wiki/time.md +4 -4
- package/knowledge/wiki/timeline.md +396 -0
- package/knowledge/wiki/transform.md +8 -8
- package/knowledge/wiki/tween.md +17 -17
- package/knowledge/wiki/ui.md +603 -629
- package/knowledge/wiki/video.md +157 -0
- package/knowledge/wiki/world.md +67 -37
- package/package.json +7 -6
- package/schema/api.schema.json +21071 -13964
- package/shell/page.ts +26 -2
- package/shell/platform.ts +46 -0
- package/shell/player.ts +7 -0
- package/src/depth.ts +71 -0
- package/src/e6.ts +32 -1
- package/src/env.d.ts +5 -1
- package/src/generated/abi.ts +189 -3
- package/src/index.ts +26 -4
- package/src/light.ts +18 -0
- package/src/math.ts +622 -0
- package/src/node/index.ts +17 -0
- package/src/node/playtest-run.ts +114 -18
- package/src/node/polish.ts +15 -4
- package/src/node/render.ts +291 -0
- package/src/node/run.ts +91 -6
- package/src/p2.ts +19 -1
- package/src/playtest.ts +57 -4
- package/src/runtime.ts +15 -3
- package/src/targets.ts +28 -0
- package/src/trace.ts +169 -0
- package/src/ui-kit/huds.ts +49 -45
- package/src/ui-kit/menus.ts +12 -12
- package/src/ui-kit/settings.ts +2 -2
- package/src/ui-kit/store.ts +18 -18
- package/src/ui-kit/story.ts +6 -4
- package/src/ui-kit/util.ts +8 -8
- package/src/web/shell.ts +58 -0
- package/src/web/worker.ts +103 -2
- package/types/bindings.json +8945 -6456
- 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
|
|
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
|
|
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
|
|
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,
|
|
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:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
```
|
|
74
|
-
|
|
75
|
-
|
|
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
|
|
79
|
-
to individual calls: copy the
|
|
80
|
-
`assets/
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
|
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
|
|
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 (`
|
|
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 (`
|
|
120
|
-
with a muted ink, **one
|
|
121
|
-
palette; a
|
|
122
|
-
|
|
123
|
-
|
|
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 `
|
|
129
|
-
|
|
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
|
-
|
|
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
|
|
136
|
-
read 1.63:1), on a dark one light (a red under a dark
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
205
|
-
- **One radius scale**: the
|
|
206
|
-
- **One shadow direction**: the
|
|
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
|
|
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
|
|
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
|
|
266
|
-
from a command, or read it in a playtest through
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
459
|
-
`og.render.look(world)?.
|
|
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 |
|
|
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` |
|