@origingame/create-game 0.2.0 → 0.4.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 +2 -1
- 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 +5 -5
- package/archetypes/idle/assets/looks/idle.ogt +2 -2
- package/archetypes/idle/assets/{skins → styles}/sparkorb/LICENSES.md +6 -6
- 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/components.ts +1 -1
- package/archetypes/idle/src/main.ts +5 -5
- package/archetypes/idle/src/ui.ts +13 -13
- package/archetypes/idle/tools/make-assets.py +5 -5
- 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 +5 -5
- package/archetypes/rhythm/assets/{skins → styles}/lanebeat/LICENSES.md +6 -6
- 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/components.ts +1 -1
- package/archetypes/rhythm/src/main.ts +3 -3
- package/archetypes/rhythm/src/ui.ts +12 -12
- package/archetypes/roguelike/LICENSES.md +1 -1
- package/archetypes/roguelike/README.md +5 -5
- package/archetypes/roguelike/assets/{skins → styles}/lampdive/LICENSES.md +6 -6
- 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/components.ts +1 -1
- package/archetypes/roguelike/src/main.ts +2 -2
- package/archetypes/roguelike/src/ui.ts +8 -8
- 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 +4 -4
- package/archetypes/third-person/assets/{skins → styles}/ember/LICENSES.md +4 -4
- 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/components.ts +1 -1
- package/archetypes/third-person/src/main.ts +3 -3
- package/archetypes/third-person/src/sound.ts +1 -1
- package/archetypes/third-person/src/ui.ts +11 -11
- 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/components.ts +1 -1
- package/archetypes/tower-defense/src/main.ts +2 -2
- package/archetypes/tower-defense/src/ui.ts +20 -18
- package/bin/create.ts +11 -8
- package/looks/catalogue.json +40 -40
- package/package.json +2 -2
- 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 +6 -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 +240 -4
- package/template-2d/tests/keeper.og.ts +178 -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
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -28,7 +28,7 @@ export const Refusal = { None: 0, Poor: 1, Blocked: 2, Taken: 3 } as const;
|
|
|
28
28
|
/** The round: the lantern's light, the purse, the waves and the effects' bookkeeping. */
|
|
29
29
|
export const Game = defineResource("Game", {
|
|
30
30
|
phase: u32(Phase.Title, { doc: "Phase.* of src/components.ts." }),
|
|
31
|
-
leftTitle: bool(false, { doc: "The player has left the title the game opened on: from then on the title enters with the
|
|
31
|
+
leftTitle: bool(false, { doc: "The player has left the title the game opened on: from then on the title enters with the style's entrance (the opening one is built settled, og.ui.mainMenu's instant: the web draws it behind the play gate)." }),
|
|
32
32
|
paused: bool(false, { doc: "The pause menu is open (the garden holds)." }),
|
|
33
33
|
settingsOpen: bool(false, { doc: "The settings dialog is open." }),
|
|
34
34
|
won: bool(false, { doc: "The last round held every wave." }),
|
|
@@ -32,11 +32,11 @@ function must<T>(r: { ok: true; value?: T } | { ok: false; reason: string }): T
|
|
|
32
32
|
|
|
33
33
|
function start(world: World): void {
|
|
34
34
|
for (const l of LANGUAGES) must(og.i18n.load(world, `strings/${l.code}.ogt`));
|
|
35
|
-
const
|
|
35
|
+
const style = must(og.load.style(world, "styles/pathguard/style.ogt"));
|
|
36
36
|
const sound = (path: string) => must(og.load.sound(world, path));
|
|
37
37
|
must(
|
|
38
38
|
og.ui.configure(world, {
|
|
39
|
-
|
|
39
|
+
style,
|
|
40
40
|
sounds: { press: sound("audio/ui-press.ogt"), open: sound("audio/ui-open.ogt"), close: sound("audio/ui-close.ogt"), error: sound("audio/ui-error.ogt"), success: sound("audio/ui-success.ogt") },
|
|
41
41
|
}),
|
|
42
42
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Path Guard's screens on og.ui and the
|
|
1
|
+
// Path Guard's screens on og.ui and the style in assets/styles/pathguard:
|
|
2
2
|
// the title, the HUD (the light and the coins in the top-left corner, the
|
|
3
3
|
// wave and pause in the top-right, the plant tray on the right on a wide
|
|
4
4
|
// screen and along the bottom on a phone), the pause menu, the settings
|
|
@@ -30,8 +30,10 @@ type PrefsV = Value<typeof Prefs>;
|
|
|
30
30
|
* millisecond), so the screens read it from here.
|
|
31
31
|
*/
|
|
32
32
|
const SPACE = { xxs: 2, xs: 4, sm: 8, md: 12, lg: 16, xl: 24 } as const;
|
|
33
|
-
|
|
34
|
-
const
|
|
33
|
+
/** The pathguard style's radius block (assets/styles/pathguard/style.ogt), read from here for the same reason. */
|
|
34
|
+
const RADIUS = { bar: 6, panel: 10 } as const;
|
|
35
|
+
type Theme = { readonly space: typeof SPACE; readonly radius: typeof RADIUS };
|
|
36
|
+
const THEME: Theme = { space: SPACE, radius: RADIUS };
|
|
35
37
|
|
|
36
38
|
/** A string of the active locale (og.i18n). */
|
|
37
39
|
export function say(world: World, key: string, args?: Record<string, string | number>): string {
|
|
@@ -193,10 +195,10 @@ function platform(world: World, g: GameV, p: PrefsV): void {
|
|
|
193
195
|
}
|
|
194
196
|
}
|
|
195
197
|
|
|
196
|
-
/** One HUD
|
|
197
|
-
function
|
|
198
|
-
og.ui.row(id, { gap: t.space.xs, cross: "center", padding: { left: t.space.sm, top: t.space.xs, right: t.space.md, bottom: t.space.xs }, frame: "
|
|
199
|
-
og.ui.icon("Icon", icon, { size: 26, tint: { token: tone
|
|
198
|
+
/** One HUD box: an icon and a number counting to its value. */
|
|
199
|
+
function hudBox(t: Theme, id: string, icon: string, value: number, tone: "gold" | "danger" | "ink"): void {
|
|
200
|
+
og.ui.row(id, { gap: t.space.xs, cross: "center", padding: { left: t.space.sm, top: t.space.xs, right: t.space.md, bottom: t.space.xs }, frame: "hud", background: { token: "panel" }, radius: t.radius.bar }, () => {
|
|
201
|
+
og.ui.icon("Icon", icon, { size: 26, tint: { token: tone } });
|
|
200
202
|
og.ui.counter("Value", value, { step: "xl", font: "display", durationMs: 300, width: px(56), align: "center" });
|
|
201
203
|
});
|
|
202
204
|
}
|
|
@@ -205,14 +207,14 @@ function hud(world: World, theme: Theme, g: GameV, t: TuneV): void {
|
|
|
205
207
|
const small = phone();
|
|
206
208
|
og.ui.setNavigation(false);
|
|
207
209
|
og.ui.anchor("Purse", { anchor: "topLeft", gap: theme.space.sm }, () => {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
+
hudBox(theme, "Light", "heart", g.lives, g.lives <= 3 ? "danger" : "ink");
|
|
211
|
+
hudBox(theme, "Coins", "coin", g.gold, "gold");
|
|
210
212
|
// A refused placement shakes the purse once, with the error sound (og-ui §6).
|
|
211
213
|
if (g.refusedTick === world.tick) og.ui.shake({ sound: true });
|
|
212
214
|
});
|
|
213
215
|
let paused = false;
|
|
214
216
|
og.ui.anchor("Waves", { anchor: "topRight", gap: theme.space.sm, cross: "center" }, () => {
|
|
215
|
-
og.ui.row("Wave", { cross: "center", padding: { left: theme.space.md, top: theme.space.xs, right: theme.space.md, bottom: theme.space.xs }, frame: "
|
|
217
|
+
og.ui.row("Wave", { cross: "center", padding: { left: theme.space.md, top: theme.space.xs, right: theme.space.md, bottom: theme.space.xs }, frame: "hud", background: { token: "panel" }, radius: theme.radius.bar }, () => {
|
|
216
218
|
og.ui.label("Label", say(world, "hud.wave", { n: Math.max(1, g.wave), total: WAVES.length }), { step: "lg", font: "display", nowrap: true });
|
|
217
219
|
});
|
|
218
220
|
if (og.ui.actionButton("Pause", say(world, "hud.pause"), { icon: "pause", size: 48 }).clicked) paused = true;
|
|
@@ -223,11 +225,11 @@ function hud(world: World, theme: Theme, g: GameV, t: TuneV): void {
|
|
|
223
225
|
PLANTS.forEach((name, kind) => {
|
|
224
226
|
const price = cost(t, kind);
|
|
225
227
|
const chosen = g.selected === kind;
|
|
226
|
-
og.ui.column(og.ui.idi("Plant", kind), { cross: "center", gap: theme.space.xxs, padding: { left: theme.space.sm, top: theme.space.xs, right: theme.space.sm, bottom: theme.space.sm }, frame: "card", background: { token: "
|
|
228
|
+
og.ui.column(og.ui.idi("Plant", kind), { cross: "center", gap: theme.space.xxs, padding: { left: theme.space.sm, top: theme.space.xs, right: theme.space.sm, bottom: theme.space.sm }, frame: "card", background: { token: "panel" }, radius: theme.radius.panel }, () => {
|
|
227
229
|
og.ui.row("Top", { cross: "center", gap: theme.space.xs }, () => {
|
|
228
230
|
og.ui.image("Picture", { texture: g.sheet as unknown as never, uv: uvOf(PICTURE[kind]!), width: px(small ? 32 : 44), height: px(small ? 32 : 44) });
|
|
229
231
|
// The price: muted when the purse covers it, in danger's ink when it does not.
|
|
230
|
-
og.ui.label("Price", `${price}`, { step: "lg", font: "display", color: { token: g.gold >= price ? "
|
|
232
|
+
og.ui.label("Price", `${price}`, { step: "lg", font: "display", color: { token: g.gold >= price ? "inkMuted" : "danger" }, nowrap: true, width: px(40), align: "center" });
|
|
231
233
|
});
|
|
232
234
|
if (og.ui.button("Pick", say(world, `tower.${name}`), { variant: chosen ? "primary" : "secondary", size: small ? "medium" : "small", width: px(small ? 86 : 104) }).clicked) g.selected = kind;
|
|
233
235
|
});
|
|
@@ -237,7 +239,7 @@ function hud(world: World, theme: Theme, g: GameV, t: TuneV): void {
|
|
|
237
239
|
// On a phone the call for the next wave sits over the tray, in the thumb's reach.
|
|
238
240
|
if (small) og.ui.anchor("Call", { anchor: "bottom", offsetY: -112 }, () => callButton(world, g, small));
|
|
239
241
|
if (g.wave === 0 && !small) {
|
|
240
|
-
og.ui.anchor("Hint", { anchor: "bottom", padding: { left: theme.space.md, top: theme.space.xs, right: theme.space.md, bottom: theme.space.xs }, frame: "
|
|
242
|
+
og.ui.anchor("Hint", { anchor: "bottom", padding: { left: theme.space.md, top: theme.space.xs, right: theme.space.md, bottom: theme.space.xs }, frame: "hud", background: { token: "panel" }, radius: theme.radius.bar }, () => {
|
|
241
243
|
og.ui.label("Text", say(world, "hud.hint"), { nowrap: true });
|
|
242
244
|
});
|
|
243
245
|
}
|
|
@@ -267,7 +269,7 @@ function settings(world: World, theme: Theme, g: GameV, p: PrefsV): void {
|
|
|
267
269
|
p.master = slider("Master", "settings.master", p.master);
|
|
268
270
|
p.music = slider("Music", "settings.music", p.music);
|
|
269
271
|
p.effects = slider("Effects", "settings.effects", p.effects);
|
|
270
|
-
og.ui.label("LanguageLabel", say(world, "settings.language"), { color: { token: "
|
|
272
|
+
og.ui.label("LanguageLabel", say(world, "settings.language"), { color: { token: "inkMuted" } });
|
|
271
273
|
const r = og.ui.radio("Language", LANGUAGES.map((l) => say(world, l.key)), p.language, { horizontal: true });
|
|
272
274
|
if (r.selected !== p.language) setLanguage(world, p, r.selected);
|
|
273
275
|
p.reducedMotion = og.ui.toggle("Motion", p.reducedMotion, say(world, "settings.motion")).on;
|
|
@@ -293,15 +295,15 @@ function endCard(world: World, theme: Theme, g: GameV, t: TuneV): "retry" | "men
|
|
|
293
295
|
for (let k = 0; k < 3; k++) {
|
|
294
296
|
const lit = k < stars && since >= 20 + k * 12;
|
|
295
297
|
og.ui.transition(og.ui.idi("Star", k), true, { kind: "scale" }, () => {
|
|
296
|
-
og.ui.icon("Mark", "star", { size: 40, tint: { token: lit ? "
|
|
298
|
+
og.ui.icon("Mark", "star", { size: 40, tint: { token: lit ? "primary" : "controlStrong" } });
|
|
297
299
|
});
|
|
298
300
|
if (lit && since === 20 + k * 12) og.ui.burst({ count: 10 });
|
|
299
301
|
}
|
|
300
302
|
});
|
|
301
303
|
og.ui.counter("Score", g.score, { from: 0, durationMs: 900, step: "displayMd", font: "display", align: "center", width: grow });
|
|
302
304
|
og.ui.row("BestRow", { width: grow, align: "center", gap: theme.space.sm, cross: "center" }, () => {
|
|
303
|
-
og.ui.label("Best", say(world, "over.best", { n: g.best }), { color: { token: "
|
|
304
|
-
if (g.newBest) og.ui.transition("NewBest", since > 50, { kind: "pop" }, () => og.ui.badge("Badge", say(world, "over.newBest"), "
|
|
305
|
+
og.ui.label("Best", say(world, "over.best", { n: g.best }), { color: { token: "inkMuted" }, nowrap: true });
|
|
306
|
+
if (g.newBest) og.ui.transition("NewBest", since > 50, { kind: "pop" }, () => og.ui.badge("Badge", say(world, "over.newBest"), "primary"));
|
|
305
307
|
});
|
|
306
308
|
og.ui.column("Stats", { width: grow, gap: 0 }, () => {
|
|
307
309
|
og.ui.keyValue("Waves", say(world, "over.waves"), `${g.won ? g.wave : Math.max(0, g.wave - 1)}/${WAVES.length}`, true);
|
|
@@ -349,7 +351,7 @@ export const Ui = defineSystem("Ui", { reads: [Tuning], writes: [Game, Prefs, og
|
|
|
349
351
|
],
|
|
350
352
|
footer: say(world, "title.footer"),
|
|
351
353
|
// The title the game opens on is built settled: the web draws it behind the play gate, where
|
|
352
|
-
// the
|
|
354
|
+
// the style's entrance would stand part-way until the tap (og-platform-sdk §3). Later titles enter.
|
|
353
355
|
instant: !g.leftTitle,
|
|
354
356
|
});
|
|
355
357
|
if (!g.settingsOpen && r.selected === "play") startRound(world, g, t);
|
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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@origingame/create-game",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Scaffolds an Origin Engine game from the project template: npm create @origingame/game.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -29,6 +29,6 @@
|
|
|
29
29
|
],
|
|
30
30
|
"scripts": {
|
|
31
31
|
"prepack": "bun scripts/pack-template.ts",
|
|
32
|
-
"test": "bun test ${OG_BUN_TEST_TIMEOUT:+--timeout=$OG_BUN_TEST_TIMEOUT} tests/"
|
|
32
|
+
"test": "bun scripts/pack-template.ts && bun test ${OG_BUN_TEST_TIMEOUT:+--timeout=$OG_BUN_TEST_TIMEOUT} tests/"
|
|
33
33
|
}
|
|
34
34
|
}
|
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/
|