@origingame/create-game 0.2.0 → 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/README.md +2 -2
- package/archetypes/README.md +1 -0
- package/archetypes/arena/.origin/setup +14 -0
- package/archetypes/arena/LICENSES.md +8 -0
- package/archetypes/arena/README.md +67 -0
- package/archetypes/arena/assets/audio/coin.ogt +9 -0
- package/archetypes/arena/assets/audio/dash.ogt +9 -0
- package/archetypes/arena/assets/audio/win.ogt +9 -0
- package/archetypes/arena/assets/fx/coin.ogt +20 -0
- package/archetypes/arena/assets/looks/arena.ogt +10 -0
- package/archetypes/arena/gitattributes +22 -0
- package/archetypes/arena/gitignore +8 -0
- package/archetypes/arena/host.d.ts +46 -0
- package/archetypes/arena/package.json +18 -0
- package/archetypes/arena/project.ogt +14 -0
- package/archetypes/arena/src/game.ts +314 -0
- package/archetypes/arena/src/main.ts +100 -0
- package/archetypes/arena/tests/duel.og.ts +32 -0
- package/archetypes/arena/tests/solo.og.ts +22 -0
- package/archetypes/arena/tsconfig.json +17 -0
- package/archetypes/idle/LICENSES.md +1 -1
- package/archetypes/idle/README.md +3 -3
- package/archetypes/idle/assets/looks/idle.ogt +1 -1
- package/archetypes/idle/assets/{skins → styles}/sparkorb/LICENSES.md +4 -4
- package/archetypes/idle/assets/{skins/sparkorb/skin.ogt → styles/sparkorb/style.ogt} +47 -47
- package/archetypes/idle/package.json +1 -1
- package/archetypes/idle/project.ogt +1 -1
- package/archetypes/idle/references/metal/card.png +0 -0
- package/archetypes/idle/references/metal/orbit.png +0 -0
- package/archetypes/idle/references/metal/title.png +0 -0
- package/archetypes/idle/src/main.ts +2 -2
- package/archetypes/idle/src/ui.ts +11 -11
- package/archetypes/idle/tools/make-assets.py +4 -4
- package/archetypes/match3/package.json +1 -1
- package/archetypes/match3/project.ogt +1 -1
- package/archetypes/rhythm/LICENSES.md +1 -1
- package/archetypes/rhythm/README.md +3 -3
- package/archetypes/rhythm/assets/{skins → styles}/lanebeat/LICENSES.md +4 -4
- package/archetypes/rhythm/assets/{skins/lanebeat/skin.ogt → styles/lanebeat/style.ogt} +45 -45
- package/archetypes/rhythm/package.json +1 -1
- package/archetypes/rhythm/project.ogt +1 -1
- package/archetypes/rhythm/references/metal/results.png +0 -0
- package/archetypes/rhythm/references/metal/title.png +0 -0
- package/archetypes/rhythm/src/main.ts +2 -2
- package/archetypes/rhythm/src/ui.ts +11 -11
- package/archetypes/roguelike/LICENSES.md +1 -1
- package/archetypes/roguelike/README.md +3 -3
- package/archetypes/roguelike/assets/{skins → styles}/lampdive/LICENSES.md +4 -4
- package/archetypes/roguelike/assets/{skins/lampdive/skin.ogt → styles/lampdive/style.ogt} +41 -41
- package/archetypes/roguelike/package.json +1 -1
- package/archetypes/roguelike/project.ogt +1 -1
- package/archetypes/roguelike/references/metal/over.png +0 -0
- package/archetypes/roguelike/references/metal/title.png +0 -0
- package/archetypes/roguelike/src/main.ts +2 -2
- package/archetypes/roguelike/src/ui.ts +7 -7
- package/archetypes/runner/package.json +1 -1
- package/archetypes/runner/project.ogt +1 -1
- package/archetypes/third-person/LICENSES.md +1 -1
- package/archetypes/third-person/README.md +3 -3
- package/archetypes/third-person/assets/{skins → styles}/ember/LICENSES.md +2 -2
- package/archetypes/third-person/assets/{skins/ember/skin.ogt → styles/ember/style.ogt} +40 -41
- package/archetypes/third-person/package.json +1 -1
- package/archetypes/third-person/project.ogt +1 -1
- package/archetypes/third-person/references/metal/beacon.png +0 -0
- package/archetypes/third-person/references/metal/dawn.png +0 -0
- package/archetypes/third-person/references/metal/title.png +0 -0
- package/archetypes/third-person/references/webgl2/beacon.png +0 -0
- package/archetypes/third-person/src/main.ts +2 -2
- package/archetypes/third-person/src/ui.ts +10 -10
- package/archetypes/topdown/package.json +1 -1
- package/archetypes/topdown/project.ogt +1 -1
- package/archetypes/tower-defense/LICENSES.md +1 -1
- package/archetypes/tower-defense/README.md +5 -5
- package/archetypes/tower-defense/assets/{skins → styles}/pathguard/LICENSES.md +4 -4
- package/archetypes/tower-defense/assets/styles/pathguard/atlas.png +0 -0
- package/archetypes/tower-defense/assets/styles/pathguard/style.ogt +111 -0
- package/archetypes/tower-defense/package.json +1 -1
- package/archetypes/tower-defense/project.ogt +1 -1
- package/archetypes/tower-defense/references/metal/end.png +0 -0
- package/archetypes/tower-defense/references/metal/title.png +0 -0
- package/archetypes/tower-defense/references/metal/wave.png +0 -0
- package/archetypes/tower-defense/src/main.ts +2 -2
- package/archetypes/tower-defense/src/ui.ts +19 -17
- package/bin/create.ts +11 -8
- package/looks/catalogue.json +40 -40
- package/package.json +1 -1
- package/template/README.md +2 -1
- package/template/assets/audio/sting.ogt +10 -0
- package/template/assets/timelines/intro.ogt +101 -0
- package/template/assets/timelines/narration.srt +11 -0
- package/template/host.d.ts +46 -0
- package/template/package.json +1 -1
- package/template/project.ogt +1 -1
- package/template/references/metal/intro-4.png +0 -0
- package/template/references/metal/intro-8.png +0 -0
- package/template/src/main.ts +1 -1
- package/template/tests/frames.ts +134 -0
- package/template/tests/intro.og.ts +65 -0
- package/template/tests/smoke.og.ts +30 -36
- package/template/tsconfig.json +1 -1
- package/template-2d/LICENSES.md +1 -0
- package/template-2d/README.md +5 -2
- package/template-2d/assets/rigs/keeper.ogt +292 -0
- package/template-2d/assets/rigs/keeper.png +0 -0
- package/template-2d/assets/rigs/keeper.png.ogt +7 -0
- package/template-2d/package.json +1 -1
- package/template-2d/project.ogt +1 -1
- package/template-2d/src/main.ts +159 -4
- package/template-2d/tests/keeper.og.ts +93 -0
- package/archetypes/tower-defense/assets/skins/pathguard/atlas.png +0 -0
- package/archetypes/tower-defense/assets/skins/pathguard/skin.ogt +0 -111
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/ChakraPetch-BoldItalic.ttf +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/ChakraPetch-BoldItalic.ttf.ogt +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/OFL.txt +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/Orbitron-Medium.ttf +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/Orbitron-Medium.ttf.ogt +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/Rajdhani-Bold.ttf +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/Rajdhani-Bold.ttf.ogt +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/atlas.png +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/atlas.png.ogt +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/icons.png +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/icons.png.ogt +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/ChakraPetch-Medium.ttf +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/ChakraPetch-Medium.ttf.ogt +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/JetBrainsMono-Regular.ttf +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/JetBrainsMono-Regular.ttf.ogt +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/OFL.txt +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/Orbitron-Bold.ttf +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/Orbitron-Bold.ttf.ogt +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/atlas.png +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/atlas.png.ogt +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/icons.png +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/icons.png.ogt +0 -0
- /package/archetypes/roguelike/assets/{skins → styles}/lampdive/DotGothic16-Regular.ttf +0 -0
- /package/archetypes/roguelike/assets/{skins → styles}/lampdive/DotGothic16-Regular.ttf.ogt +0 -0
- /package/archetypes/roguelike/assets/{skins → styles}/lampdive/OFL.txt +0 -0
- /package/archetypes/roguelike/assets/{skins → styles}/lampdive/atlas.png +0 -0
- /package/archetypes/roguelike/assets/{skins → styles}/lampdive/atlas.png.ogt +0 -0
- /package/archetypes/roguelike/assets/{skins → styles}/lampdive/icons.png +0 -0
- /package/archetypes/roguelike/assets/{skins → styles}/lampdive/icons.png.ogt +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/Cinzel-Bold.ttf +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/Cinzel-Bold.ttf.ogt +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/Newsreader-Medium.ttf +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/Newsreader-Medium.ttf.ogt +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/OFL.txt +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/atlas.png +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/atlas.png.ogt +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/icons.png +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/icons.png.ogt +0 -0
- /package/archetypes/tower-defense/assets/{skins → styles}/pathguard/Fredoka-SemiBold.ttf +0 -0
- /package/archetypes/tower-defense/assets/{skins → styles}/pathguard/Fredoka-SemiBold.ttf.ogt +0 -0
- /package/archetypes/tower-defense/assets/{skins → styles}/pathguard/LilitaOne-Regular.ttf +0 -0
- /package/archetypes/tower-defense/assets/{skins → styles}/pathguard/LilitaOne-Regular.ttf.ogt +0 -0
- /package/archetypes/tower-defense/assets/{skins → styles}/pathguard/OFL.txt +0 -0
- /package/archetypes/tower-defense/assets/{skins → styles}/pathguard/atlas.png.ogt +0 -0
- /package/archetypes/tower-defense/assets/{skins → styles}/pathguard/icons.png +0 -0
- /package/archetypes/tower-defense/assets/{skins → styles}/pathguard/icons.png.ogt +0 -0
package/bin/create.ts
CHANGED
|
@@ -47,7 +47,7 @@ export interface CreateOptions {
|
|
|
47
47
|
readonly name?: string;
|
|
48
48
|
readonly id?: string;
|
|
49
49
|
readonly force?: boolean;
|
|
50
|
-
/** Start from an archetype (`runner`, `match3`, `topdown`, `tower-defense`, `roguelike`, `idle`, `rhythm`, `third-person`: templates/archetypes/README.md) instead of the project template. */
|
|
50
|
+
/** Start from an archetype (`runner`, `match3`, `topdown`, `tower-defense`, `roguelike`, `idle`, `rhythm`, `third-person`, `arena`: templates/archetypes/README.md) instead of the project template. */
|
|
51
51
|
readonly archetype?: string;
|
|
52
52
|
/** The template's profile: `2d` writes the 2D starter (templates/game-2d), `3d` the 3D template (templates/game). Unset, a premise that says 2D picks `2d`; else `3d`. Not for an archetype, which has its own. */
|
|
53
53
|
readonly profile?: Profile;
|
|
@@ -102,7 +102,7 @@ export interface Style {
|
|
|
102
102
|
readonly descriptor: string;
|
|
103
103
|
readonly premise: Readonly<Record<string, string>>;
|
|
104
104
|
readonly look: { readonly presetReady: boolean; readonly support: string; readonly missing: readonly string[] };
|
|
105
|
-
readonly
|
|
105
|
+
readonly ui: string;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
/** The style catalogue this copy of the package reads. */
|
|
@@ -215,7 +215,10 @@ export function templateDir(archetype?: string, profile: Profile = "3d"): string
|
|
|
215
215
|
}
|
|
216
216
|
const packed = profile === "2d" ? "template-2d" : "template";
|
|
217
217
|
const source = profile === "2d" ? "game-2d" : "game";
|
|
218
|
-
|
|
218
|
+
// In the engine repository the live template wins: a ./template/ left by an
|
|
219
|
+
// earlier prepack is stale as soon as templates/ changes. A published
|
|
220
|
+
// package has no templates/ beside it, so it scaffolds from its packed copy.
|
|
221
|
+
for (const candidate of [join(here, "..", "..", "..", "templates", source), join(here, "..", packed)]) {
|
|
219
222
|
if (existsSync(join(candidate, "project.ogt"))) return candidate;
|
|
220
223
|
}
|
|
221
224
|
throw new Error(`no ${profile} project template next to ${here}: expected ../${packed} (published package) or ../../../templates/${source} (engine repository)`);
|
|
@@ -281,8 +284,8 @@ function lookText(name: string, style: Style | undefined, slug: string | null, i
|
|
|
281
284
|
head.push(
|
|
282
285
|
`# It extends the style catalogue's ${slug} preset (${style.name}),`,
|
|
283
286
|
style.look.support === "full" ? "# whose primitives all draw today." : `# support ${style.look.support}: ${style.look.missing.join("; ")}.`,
|
|
284
|
-
`# The
|
|
285
|
-
`#
|
|
287
|
+
`# The preset dresses the UI in the built-in ${style.ui} style; a \`ui "<slug>"\``,
|
|
288
|
+
`# line here picks another, or the game's own assets/styles/<name>/style.ogt.`,
|
|
286
289
|
);
|
|
287
290
|
} else if (slug) head.push(`# It extends ${slug}.`);
|
|
288
291
|
else head.push("# It extends no preset yet: the frame is the engine's defaults plus the lines below.");
|
|
@@ -309,11 +312,11 @@ function lookReadme(look: CreatedLook, style: Style | undefined, entry: string,
|
|
|
309
312
|
"after the first scene spawns and before `start` runs, and sets tone",
|
|
310
313
|
"mapping and exposure, the post stack, the stylisation (`Stylise`),",
|
|
311
314
|
"material defaults (`MaterialStyle`: toon, outlines, flat shading), fog,",
|
|
312
|
-
"sky, the environment map and the UI
|
|
315
|
+
"sky, the environment map and the UI style (its `ui` line).",
|
|
313
316
|
"",
|
|
314
317
|
];
|
|
315
318
|
if (look.extends && style) {
|
|
316
|
-
lines.push(`It extends \`${look.extends}\`${how}: "${style.name}" in the style`, `catalogue. ${style.descriptor} Its UI
|
|
319
|
+
lines.push(`It extends \`${look.extends}\`${how}: "${style.name}" in the style`, `catalogue. ${style.descriptor} Its UI style is \`${style.ui}\`.`, "");
|
|
317
320
|
} else if (look.extends) lines.push(`It extends \`${look.extends}\`${how}.`, "");
|
|
318
321
|
else lines.push("It extends no preset yet: the frame is the engine's defaults plus what", "the file sets.", "");
|
|
319
322
|
lines.push(
|
|
@@ -481,7 +484,7 @@ Scaffolds an Origin Engine game into dir (default: ./origin-game).
|
|
|
481
484
|
--name the game's display name (default: from the id or the directory)
|
|
482
485
|
--id the game's id, lowercase-hyphen (default: from the name)
|
|
483
486
|
--profile 2d writes the 2D starter (a platformer: sprites, tilemap, 2D physics), 3d the 3D template (default: 2d for a premise that says 2D, platformer, side-scroller, metroidvania or pixel art without saying 3D; else 3d)
|
|
484
|
-
--archetype start from a complete archetype game (runner, match3, topdown, tower-defense, roguelike, idle, rhythm, third-person) instead of the template; it has its own profile
|
|
487
|
+
--archetype start from a complete archetype game (runner, match3, topdown, tower-defense, roguelike, idle, rhythm, third-person, arena) instead of the template; it has its own profile
|
|
485
488
|
--premise the game in one line (genre, mood, setting, audience): its look extends the style catalogue's best match (asked for on a terminal when neither this nor --look is given)
|
|
486
489
|
--look the style catalogue slug the look extends (og-taste §12), such as anime-cel-3d or 16bit-pixel
|
|
487
490
|
--no-prompt never ask for the premise
|
package/looks/catalogue.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"about": "Origin Engine's style catalogue: 37 art styles in the engine's own words, each with what a critic checks on a rendered frame, the premises it fits, the look preset it maps to (an .ogt of type look; `extends \"<slug>\"` in a game's own look builds on it), the UI
|
|
3
|
+
"about": "Origin Engine's style catalogue: 37 art styles in the engine's own words, each with what a critic checks on a rendered frame, the premises it fits, the look preset it maps to (an .ogt of type look; `extends \"<slug>\"` in a game's own look builds on it), the built-in UI style its look's `ui` line names, palette and asset specs, and an art-bible direction the agent expands per project. `look.support` says how faithfully the engine renders the style today: full (every primitive draws), partial or planned (the primitives in `missing` are still to land), content (the look lives in authored art; the engine frames it). og-taste §12 explains how to use it. The descriptions are original; no game or studio is the reference for a style.",
|
|
4
4
|
"categories": {
|
|
5
5
|
"pixel": "Pixel and retro",
|
|
6
6
|
"paint": "Paint and line",
|
|
7
7
|
"shape": "Shape and material",
|
|
8
8
|
"render": "3D rendering"
|
|
9
9
|
},
|
|
10
|
-
"
|
|
10
|
+
"ui": [
|
|
11
11
|
"pixel",
|
|
12
12
|
"cartoon",
|
|
13
13
|
"fantasy",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"paper",
|
|
16
16
|
"neon"
|
|
17
17
|
],
|
|
18
|
-
"artBibleTemplate": "Art bible for {title}. Premise: {premise}. Camera: {camera}; platform and display size: {platform}. Style: {name} ({descriptor}) Direction: {direction} Palette: {palette}. Asset specs: {assets}. UI: the {
|
|
18
|
+
"artBibleTemplate": "Art bible for {title}. Premise: {premise}. Camera: {camera}; platform and display size: {platform}. Style: {name} ({descriptor}) Direction: {direction} Palette: {palette}. Asset specs: {assets}. UI: the {ui} style the preset names (a `ui` line in the game's look picks another, or the game's own styles/<name>/style.ogt), re-coloured to this palette (og-taste §1). Avoid: {avoid}. Proof: the game's look is assets/looks/{game}.ogt, extending \"{slug}\"; capture the title, play and results screens with og run and check each against: {checks}. Every later asset is made inside this bible; a request for one asset never redesigns the style.",
|
|
19
19
|
"styles": [
|
|
20
20
|
{
|
|
21
21
|
"slug": "expressionist-painting",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"Stylise.paint* for 3D parts to match the painted art"
|
|
48
48
|
]
|
|
49
49
|
},
|
|
50
|
-
"
|
|
50
|
+
"ui": "paper",
|
|
51
51
|
"palette": {
|
|
52
52
|
"size": "free, but 3 to 5 dominant masses per scene",
|
|
53
53
|
"rules": "Complementary clashes in shadows; one dominant temperature per scene; avoid neutral greys."
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
],
|
|
97
97
|
"missing": []
|
|
98
98
|
},
|
|
99
|
-
"
|
|
99
|
+
"ui": "fantasy",
|
|
100
100
|
"palette": {
|
|
101
101
|
"size": "20 to 40 colours",
|
|
102
102
|
"rules": "Deep warm or cool shadow colour shared by all materials; accents in one hue family per faction."
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
],
|
|
146
146
|
"missing": []
|
|
147
147
|
},
|
|
148
|
-
"
|
|
148
|
+
"ui": "paper",
|
|
149
149
|
"palette": {
|
|
150
150
|
"size": "12 to 24 colours",
|
|
151
151
|
"rules": "Light values dominate; two or three pigments mixed into the rest; no pure black."
|
|
@@ -196,7 +196,7 @@
|
|
|
196
196
|
],
|
|
197
197
|
"missing": []
|
|
198
198
|
},
|
|
199
|
-
"
|
|
199
|
+
"ui": "fantasy",
|
|
200
200
|
"palette": {
|
|
201
201
|
"size": "sprites 32 to 64 colours; the set is unconstrained but graded to match",
|
|
202
202
|
"rules": "Grade the 3D set with a LUT towards the sprites' palette so the two read as one world."
|
|
@@ -244,7 +244,7 @@
|
|
|
244
244
|
],
|
|
245
245
|
"missing": []
|
|
246
246
|
},
|
|
247
|
-
"
|
|
247
|
+
"ui": "paper",
|
|
248
248
|
"palette": {
|
|
249
249
|
"size": "16 to 32 colours",
|
|
250
250
|
"rules": "Colour per material, gradients only from lighting and fog."
|
|
@@ -295,7 +295,7 @@
|
|
|
295
295
|
],
|
|
296
296
|
"missing": []
|
|
297
297
|
},
|
|
298
|
-
"
|
|
298
|
+
"ui": "cartoon",
|
|
299
299
|
"palette": {
|
|
300
300
|
"size": "warm, slightly desaturated plasticine colours",
|
|
301
301
|
"rules": "Matte surfaces; saturation from the clay, not the light."
|
|
@@ -344,7 +344,7 @@
|
|
|
344
344
|
],
|
|
345
345
|
"missing": []
|
|
346
346
|
},
|
|
347
|
-
"
|
|
347
|
+
"ui": "pixel",
|
|
348
348
|
"palette": {
|
|
349
349
|
"size": "8 to 16 colours",
|
|
350
350
|
"rules": "Ramps of 3 or 4 steps per material; one shared black; no gradients; background colours darker or desaturated against sprites."
|
|
@@ -393,7 +393,7 @@
|
|
|
393
393
|
],
|
|
394
394
|
"missing": []
|
|
395
395
|
},
|
|
396
|
-
"
|
|
396
|
+
"ui": "pixel",
|
|
397
397
|
"palette": {
|
|
398
398
|
"size": "32 to 64 colours (a voxel palette)",
|
|
399
399
|
"rules": "One palette for the whole world; shade by light, not by palette steps."
|
|
@@ -444,7 +444,7 @@
|
|
|
444
444
|
"Stylise.paintCanvas for the vellum grain"
|
|
445
445
|
]
|
|
446
446
|
},
|
|
447
|
-
"
|
|
447
|
+
"ui": "paper",
|
|
448
448
|
"palette": {
|
|
449
449
|
"size": "10 to 16 colours",
|
|
450
450
|
"rules": "Parchment ground, iron-gall ink, a few mineral pigments (ultramarine, vermilion, verdigris) and gold."
|
|
@@ -495,7 +495,7 @@
|
|
|
495
495
|
"the look is in frame-by-frame animation (flipbooks); the engine supplies the film treatment"
|
|
496
496
|
]
|
|
497
497
|
},
|
|
498
|
-
"
|
|
498
|
+
"ui": "cartoon",
|
|
499
499
|
"palette": {
|
|
500
500
|
"size": "sepia or muted primaries, 12 to 24 colours",
|
|
501
501
|
"rules": "Inked black lines, flat fills, a warm faded grade over everything."
|
|
@@ -544,7 +544,7 @@
|
|
|
544
544
|
],
|
|
545
545
|
"missing": []
|
|
546
546
|
},
|
|
547
|
-
"
|
|
547
|
+
"ui": "paper",
|
|
548
548
|
"palette": {
|
|
549
549
|
"size": "graphite or sepia ramp plus paper, optional single accent",
|
|
550
550
|
"rules": "Value from line density only; the accent marks danger or the goal."
|
|
@@ -596,7 +596,7 @@
|
|
|
596
596
|
"ornament is content; Stylise.depthBands for layered haze"
|
|
597
597
|
]
|
|
598
598
|
},
|
|
599
|
-
"
|
|
599
|
+
"ui": "fantasy",
|
|
600
600
|
"palette": {
|
|
601
601
|
"size": "cool desaturated base with 1 or 2 glowing accents",
|
|
602
602
|
"rules": "Dark blue-grey grounds, pale characters, glows in one hue."
|
|
@@ -647,7 +647,7 @@
|
|
|
647
647
|
"painted backdrops are content; Stylise.paint* for 3D props"
|
|
648
648
|
]
|
|
649
649
|
},
|
|
650
|
-
"
|
|
650
|
+
"ui": "fantasy",
|
|
651
651
|
"palette": {
|
|
652
652
|
"size": "free, organised by warm light and cool shadow",
|
|
653
653
|
"rules": "Saturation highest at the light's edge; value grouping in three planes."
|
|
@@ -697,7 +697,7 @@
|
|
|
697
697
|
"illustration is content; Stylise.ink and paintCanvas"
|
|
698
698
|
]
|
|
699
699
|
},
|
|
700
|
-
"
|
|
700
|
+
"ui": "cartoon",
|
|
701
701
|
"palette": {
|
|
702
702
|
"size": "16 to 32 colours",
|
|
703
703
|
"rules": "Soft saturated hues, coloured line work, patterns from the same palette."
|
|
@@ -747,7 +747,7 @@
|
|
|
747
747
|
"the source paintings and cut-outs are content (public-domain scans or original painting); no engine primitive is missing"
|
|
748
748
|
]
|
|
749
749
|
},
|
|
750
|
-
"
|
|
750
|
+
"ui": "paper",
|
|
751
751
|
"palette": {
|
|
752
752
|
"size": "the source paintings' own",
|
|
753
753
|
"rules": "Grade all sources to a common varnish tone with a LUT."
|
|
@@ -797,7 +797,7 @@
|
|
|
797
797
|
"the drawing is content; Stylise.ink can outline 3D props to match"
|
|
798
798
|
]
|
|
799
799
|
},
|
|
800
|
-
"
|
|
800
|
+
"ui": "paper",
|
|
801
801
|
"palette": {
|
|
802
802
|
"size": "monochrome ink or 4 to 8 light colours",
|
|
803
803
|
"rules": "White or off-white ground; colour never hides line."
|
|
@@ -847,7 +847,7 @@
|
|
|
847
847
|
"silhouettes are content; Stylise.palette locks the colours"
|
|
848
848
|
]
|
|
849
849
|
},
|
|
850
|
-
"
|
|
850
|
+
"ui": "fantasy",
|
|
851
851
|
"palette": {
|
|
852
852
|
"size": "2 to 4 colours",
|
|
853
853
|
"rules": "Ochre ground, black figures, a lighter line colour, optional red-brown."
|
|
@@ -896,7 +896,7 @@
|
|
|
896
896
|
],
|
|
897
897
|
"missing": []
|
|
898
898
|
},
|
|
899
|
-
"
|
|
899
|
+
"ui": "fantasy",
|
|
900
900
|
"palette": {
|
|
901
901
|
"size": "muted 12 to 24 colours plus black",
|
|
902
902
|
"rules": "Desaturated mid-tones, black for every shadow, one blood or fire accent."
|
|
@@ -945,7 +945,7 @@
|
|
|
945
945
|
],
|
|
946
946
|
"missing": []
|
|
947
947
|
},
|
|
948
|
-
"
|
|
948
|
+
"ui": "pixel",
|
|
949
949
|
"palette": {
|
|
950
950
|
"size": "2 colours plus at most 1 accent",
|
|
951
951
|
"rules": "Pick ink and paper first; shading only through dither or pattern; the accent means one thing."
|
|
@@ -994,7 +994,7 @@
|
|
|
994
994
|
],
|
|
995
995
|
"missing": []
|
|
996
996
|
},
|
|
997
|
-
"
|
|
997
|
+
"ui": "pixel",
|
|
998
998
|
"palette": {
|
|
999
999
|
"size": "32 to 64 colours",
|
|
1000
1000
|
"rules": "Ramps of 4 to 6 steps; hue-shifted shadows (cooler) and highlights (warmer); saturated accents on characters, calmer backgrounds."
|
|
@@ -1044,7 +1044,7 @@
|
|
|
1044
1044
|
],
|
|
1045
1045
|
"missing": []
|
|
1046
1046
|
},
|
|
1047
|
-
"
|
|
1047
|
+
"ui": "fantasy",
|
|
1048
1048
|
"palette": {
|
|
1049
1049
|
"size": "48 to 128 colours",
|
|
1050
1050
|
"rules": "Long hue-shifted ramps; a value plan per scene that keeps the play area mid-value and the foreground darkest."
|
|
@@ -1094,7 +1094,7 @@
|
|
|
1094
1094
|
],
|
|
1095
1095
|
"missing": []
|
|
1096
1096
|
},
|
|
1097
|
-
"
|
|
1097
|
+
"ui": "neon",
|
|
1098
1098
|
"palette": {
|
|
1099
1099
|
"size": "24 to 48 colours",
|
|
1100
1100
|
"rules": "A near-black ground with two or three saturated light hues; no mid-grey fills; accents reserved for interactables."
|
|
@@ -1143,7 +1143,7 @@
|
|
|
1143
1143
|
],
|
|
1144
1144
|
"missing": []
|
|
1145
1145
|
},
|
|
1146
|
-
"
|
|
1146
|
+
"ui": "fantasy",
|
|
1147
1147
|
"palette": {
|
|
1148
1148
|
"size": "32 to 64 colours",
|
|
1149
1149
|
"rules": "Floors desaturated and mid-value; walls darker on their faces; characters most saturated."
|
|
@@ -1194,7 +1194,7 @@
|
|
|
1194
1194
|
],
|
|
1195
1195
|
"missing": []
|
|
1196
1196
|
},
|
|
1197
|
-
"
|
|
1197
|
+
"ui": "scifi",
|
|
1198
1198
|
"palette": {
|
|
1199
1199
|
"size": "free, but posterised to 32 levels per channel",
|
|
1200
1200
|
"rules": "Fog colour equals the clear colour; dithered gradients."
|
|
@@ -1242,7 +1242,7 @@
|
|
|
1242
1242
|
],
|
|
1243
1243
|
"missing": []
|
|
1244
1244
|
},
|
|
1245
|
-
"
|
|
1245
|
+
"ui": "pixel",
|
|
1246
1246
|
"palette": {
|
|
1247
1247
|
"size": "6 to 16 colours",
|
|
1248
1248
|
"rules": "Each scene has one dominant mass colour; detail colour only where the eye should go."
|
|
@@ -1293,7 +1293,7 @@
|
|
|
1293
1293
|
],
|
|
1294
1294
|
"missing": []
|
|
1295
1295
|
},
|
|
1296
|
-
"
|
|
1296
|
+
"ui": "neon",
|
|
1297
1297
|
"palette": {
|
|
1298
1298
|
"size": "24 to 48 colours",
|
|
1299
1299
|
"rules": "Two tones per material (lit, shadow) with hue-shifted shadows; highlights as shapes."
|
|
@@ -1344,7 +1344,7 @@
|
|
|
1344
1344
|
],
|
|
1345
1345
|
"missing": []
|
|
1346
1346
|
},
|
|
1347
|
-
"
|
|
1347
|
+
"ui": "scifi",
|
|
1348
1348
|
"palette": {
|
|
1349
1349
|
"size": "free, saturated",
|
|
1350
1350
|
"rules": "Bold local colours, black ink for all shadow edges."
|
|
@@ -1394,7 +1394,7 @@
|
|
|
1394
1394
|
],
|
|
1395
1395
|
"missing": []
|
|
1396
1396
|
},
|
|
1397
|
-
"
|
|
1397
|
+
"ui": "paper",
|
|
1398
1398
|
"palette": {
|
|
1399
1399
|
"size": "8 to 16 colours",
|
|
1400
1400
|
"rules": "Colours of real paper stock: muted, slightly warm; white is off-white."
|
|
@@ -1444,7 +1444,7 @@
|
|
|
1444
1444
|
],
|
|
1445
1445
|
"missing": []
|
|
1446
1446
|
},
|
|
1447
|
-
"
|
|
1447
|
+
"ui": "cartoon",
|
|
1448
1448
|
"palette": {
|
|
1449
1449
|
"size": "soft pastel 24 to 48 colours",
|
|
1450
1450
|
"rules": "Bright but slightly desaturated; warm sunlight, cool shadows."
|
|
@@ -1494,7 +1494,7 @@
|
|
|
1494
1494
|
],
|
|
1495
1495
|
"missing": []
|
|
1496
1496
|
},
|
|
1497
|
-
"
|
|
1497
|
+
"ui": "fantasy",
|
|
1498
1498
|
"palette": {
|
|
1499
1499
|
"size": "free, harmonised by a LUT",
|
|
1500
1500
|
"rules": "Two or three dominant hues per area; graded towards them."
|
|
@@ -1546,7 +1546,7 @@
|
|
|
1546
1546
|
],
|
|
1547
1547
|
"missing": []
|
|
1548
1548
|
},
|
|
1549
|
-
"
|
|
1549
|
+
"ui": "scifi",
|
|
1550
1550
|
"palette": {
|
|
1551
1551
|
"size": "free, graded",
|
|
1552
1552
|
"rules": "One grade per area; avoid oversaturation; skin tones protected."
|
|
@@ -1597,7 +1597,7 @@
|
|
|
1597
1597
|
],
|
|
1598
1598
|
"missing": []
|
|
1599
1599
|
},
|
|
1600
|
-
"
|
|
1600
|
+
"ui": "scifi",
|
|
1601
1601
|
"palette": {
|
|
1602
1602
|
"size": "greys and one accent",
|
|
1603
1603
|
"rules": "Desaturated everything; the accent is red or warm light only where the story points."
|
|
@@ -1646,7 +1646,7 @@
|
|
|
1646
1646
|
],
|
|
1647
1647
|
"missing": []
|
|
1648
1648
|
},
|
|
1649
|
-
"
|
|
1649
|
+
"ui": "neon",
|
|
1650
1650
|
"palette": {
|
|
1651
1651
|
"size": "1 hue in 4 to 6 values, or black plus a gradient sky",
|
|
1652
1652
|
"rules": "Value steps per layer; colour only in the far layers or a single accent."
|
|
@@ -1695,7 +1695,7 @@
|
|
|
1695
1695
|
],
|
|
1696
1696
|
"missing": []
|
|
1697
1697
|
},
|
|
1698
|
-
"
|
|
1698
|
+
"ui": "neon",
|
|
1699
1699
|
"palette": {
|
|
1700
1700
|
"size": "3 to 6 colours",
|
|
1701
1701
|
"rules": "One ground, one figure colour, one accent; contrast by hue and value."
|
|
@@ -1746,7 +1746,7 @@
|
|
|
1746
1746
|
],
|
|
1747
1747
|
"missing": []
|
|
1748
1748
|
},
|
|
1749
|
-
"
|
|
1749
|
+
"ui": "neon",
|
|
1750
1750
|
"palette": {
|
|
1751
1751
|
"size": "black plus 2 to 4 saturated hues",
|
|
1752
1752
|
"rules": "Each hue one meaning (player, enemy, pickup); white only for the hottest centres."
|
|
@@ -1795,7 +1795,7 @@
|
|
|
1795
1795
|
],
|
|
1796
1796
|
"missing": []
|
|
1797
1797
|
},
|
|
1798
|
-
"
|
|
1798
|
+
"ui": "pixel",
|
|
1799
1799
|
"palette": {
|
|
1800
1800
|
"size": "2 to 4 colours",
|
|
1801
1801
|
"rules": "Ink and paper, optionally one mid-tone and one accent."
|
|
@@ -1846,7 +1846,7 @@
|
|
|
1846
1846
|
],
|
|
1847
1847
|
"missing": []
|
|
1848
1848
|
},
|
|
1849
|
-
"
|
|
1849
|
+
"ui": "fantasy",
|
|
1850
1850
|
"palette": {
|
|
1851
1851
|
"size": "dark cool masses plus warm luminous accents",
|
|
1852
1852
|
"rules": "Value structure first: dark foreground, mid play plane, glowing background."
|
package/package.json
CHANGED
package/template/README.md
CHANGED
|
@@ -8,7 +8,7 @@ through the wall, raises the alarm, chases, searches and goes back.
|
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
10
|
og run . # headless with the probe; og dev . reloads on save
|
|
11
|
-
og test . # tests/smoke.og.ts and tests/
|
|
11
|
+
og test . # tests/smoke.og.ts, tests/guard.og.ts and tests/intro.og.ts
|
|
12
12
|
og polish . # the taste and feel scores of those playtests
|
|
13
13
|
og build . # the play page
|
|
14
14
|
```
|
|
@@ -25,6 +25,7 @@ og build . # the play page
|
|
|
25
25
|
| Every word the menu shows from a string table, the base one in the source language | `assets/strings/en.ogt`, `Menu` | og-i18n §1, §2 |
|
|
26
26
|
| A guard as data: a state machine on og.ai, a navmesh cooked from the yard, sight cones against the wall | `assets/ai/guard.ogt`, `assets/nav/yard.ogt` | og-ai §1–§5 |
|
|
27
27
|
| Commands with their usage in `help`, facts for playtests | `commands`, `commandHelp`, `facts` | og-game §3; og-build §1 |
|
|
28
|
+
| A cutscene as data: a camera on a rail, the trickster's clips and walk, narration from an `.srt`, sounds, an event key running `spawn_wave`, fades and markers, played by `timeline:play:intro` | `assets/timelines/intro.ogt`, `narration.srt`, `tests/intro.og.ts` | og-game §9 "Cutscenes" |
|
|
28
29
|
| Playtests that assert on dumps and facts, never on the code | `tests/` | og-build §3, §4 |
|
|
29
30
|
|
|
30
31
|
`og polish .` (2026-10-19): taste 100, feel 87 (tests/evidence/E7/polish/
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
type timeline
|
|
2
|
+
version 1
|
|
3
|
+
---
|
|
4
|
+
name "Intro"
|
|
5
|
+
duration 10
|
|
6
|
+
# The camera's rail: a slow arc in front of the yard, from the left to the right.
|
|
7
|
+
path "flyby" {
|
|
8
|
+
kind catmullRom
|
|
9
|
+
point -5 3.2 9
|
|
10
|
+
point -1.5 2.4 7.5
|
|
11
|
+
point 2 2 7
|
|
12
|
+
point 5 2.8 8.5
|
|
13
|
+
}
|
|
14
|
+
track camera {
|
|
15
|
+
rail "flyby"
|
|
16
|
+
key 0 {
|
|
17
|
+
at 0
|
|
18
|
+
target 0 1 0
|
|
19
|
+
fov 50
|
|
20
|
+
}
|
|
21
|
+
key 9.5 {
|
|
22
|
+
at 1
|
|
23
|
+
target 1.5 1 0
|
|
24
|
+
fov 42
|
|
25
|
+
ease cubicInOut
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
track transform "trickster" {
|
|
29
|
+
key 2 {
|
|
30
|
+
position 2 0 0
|
|
31
|
+
}
|
|
32
|
+
key 5 {
|
|
33
|
+
position 0.5 0 1.5
|
|
34
|
+
ease cubicInOut
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
track animation "trickster" {
|
|
38
|
+
key 0 {
|
|
39
|
+
clip "idle"
|
|
40
|
+
loop true
|
|
41
|
+
}
|
|
42
|
+
key 2 {
|
|
43
|
+
clip "walk"
|
|
44
|
+
loop true
|
|
45
|
+
blendIn 0.3
|
|
46
|
+
}
|
|
47
|
+
key 5 {
|
|
48
|
+
clip "wave"
|
|
49
|
+
blendIn 0.25
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
track caption {
|
|
53
|
+
captions "narration.srt"
|
|
54
|
+
style lg
|
|
55
|
+
anchor bottom
|
|
56
|
+
}
|
|
57
|
+
track audio {
|
|
58
|
+
key 1 {
|
|
59
|
+
sound "audio/blip.wav"
|
|
60
|
+
volume 0.6
|
|
61
|
+
}
|
|
62
|
+
key 5 {
|
|
63
|
+
sound "audio/click.ogt"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
track music {
|
|
67
|
+
key 6 {
|
|
68
|
+
sound "audio/sting.ogt"
|
|
69
|
+
volume 0.7
|
|
70
|
+
fadeIn 0.3
|
|
71
|
+
fadeOut 1
|
|
72
|
+
end 9.5
|
|
73
|
+
loop true
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
track event {
|
|
77
|
+
key 5.5 {
|
|
78
|
+
do "spawn_wave:2"
|
|
79
|
+
retroactive true
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
track transition {
|
|
83
|
+
key 0 {
|
|
84
|
+
kind fade
|
|
85
|
+
mode in
|
|
86
|
+
duration 1
|
|
87
|
+
}
|
|
88
|
+
key 9 {
|
|
89
|
+
kind fade
|
|
90
|
+
mode out
|
|
91
|
+
duration 1
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
track marker {
|
|
95
|
+
key 2 {
|
|
96
|
+
name "walk"
|
|
97
|
+
}
|
|
98
|
+
key 5.5 {
|
|
99
|
+
name "drop"
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// The host this project's playtest helpers (tests/*.ts) touch under bun:
|
|
2
|
+
// `node:` modules, `process`, `Buffer`, `TextEncoder`, `import.meta.url`.
|
|
3
|
+
// Declared here because the project type-checks with `types: []` (no
|
|
4
|
+
// @types/node, no bun-types): `og check` reads them through tsconfig.json's
|
|
5
|
+
// include. Game code (src/) uses none of them.
|
|
6
|
+
|
|
7
|
+
declare module "node:fs" {
|
|
8
|
+
export function existsSync(path: string): boolean;
|
|
9
|
+
export function readFileSync(path: string): Uint8Array;
|
|
10
|
+
export function readFileSync(path: string, encoding: string): string;
|
|
11
|
+
export function writeFileSync(path: string, data: string | Uint8Array): void;
|
|
12
|
+
export function mkdirSync(path: string, options?: { recursive?: boolean }): void;
|
|
13
|
+
export function copyFileSync(from: string, to: string): void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
declare module "node:path" {
|
|
17
|
+
export function dirname(path: string): string;
|
|
18
|
+
export function join(...parts: string[]): string;
|
|
19
|
+
export function resolve(...parts: string[]): string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
declare module "node:url" {
|
|
23
|
+
export function fileURLToPath(url: string | URL): string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
declare module "node:zlib" {
|
|
27
|
+
export function inflateSync(data: Uint8Array): Uint8Array;
|
|
28
|
+
export function deflateSync(data: Uint8Array, options?: { level?: number }): Uint8Array;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
declare const process: {
|
|
32
|
+
readonly env: Record<string, string | undefined>;
|
|
33
|
+
cwd(): string;
|
|
34
|
+
readonly stdout: { write(text: string): boolean };
|
|
35
|
+
};
|
|
36
|
+
declare const Buffer: { concat(chunks: readonly Uint8Array[]): Uint8Array };
|
|
37
|
+
declare class TextEncoder {
|
|
38
|
+
encode(text: string): Uint8Array;
|
|
39
|
+
}
|
|
40
|
+
declare class URL {
|
|
41
|
+
constructor(url: string, base?: string | URL);
|
|
42
|
+
readonly href: string;
|
|
43
|
+
}
|
|
44
|
+
interface ImportMeta {
|
|
45
|
+
readonly url: string;
|
|
46
|
+
}
|
package/template/package.json
CHANGED
package/template/project.ogt
CHANGED
|
Binary file
|
|
Binary file
|
package/template/src/main.ts
CHANGED
|
@@ -66,7 +66,7 @@ export const Menu = defineSystem("Menu", { reads: [Spin, og.Input], writes: [Run
|
|
|
66
66
|
const started = run.value.started;
|
|
67
67
|
og.ui.column("Hud", { padding: { left: 24, top: 24, right: 24, bottom: 24 } }, () => og.ui.panel("Menu", { padding: { left: 20, top: 16, right: 20, bottom: 16 } }, () => {
|
|
68
68
|
og.ui.label("Title", og.i18n.t(world, "menu.title"), { step: "displaySm" });
|
|
69
|
-
og.ui.label("Status", started ? og.i18n.t(world, "menu.spinning", { speed: speed.toFixed(1) }) : og.i18n.t(world, "menu.prompt"), { color: { token: started ? "
|
|
69
|
+
og.ui.label("Status", started ? og.i18n.t(world, "menu.spinning", { speed: speed.toFixed(1) }) : og.i18n.t(world, "menu.prompt"), { color: { token: started ? "highlight" : "inkMuted" } });
|
|
70
70
|
const start = og.ui.button("Start", og.i18n.t(world, started ? "menu.started" : "menu.start"), { variant: "primary", size: "large", disabled: started });
|
|
71
71
|
if (!started && (start.clicked || input.value.pressed("KeyS") || input.value.pressed("Enter"))) run.value.started = true;
|
|
72
72
|
}));
|