@origingame/create-game 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +15 -7
  2. package/archetypes/README.md +4 -2
  3. package/archetypes/idle/package.json +1 -1
  4. package/archetypes/idle/project.ogt +1 -1
  5. package/archetypes/match3/package.json +1 -1
  6. package/archetypes/match3/project.ogt +1 -1
  7. package/archetypes/rhythm/package.json +1 -1
  8. package/archetypes/rhythm/project.ogt +1 -1
  9. package/archetypes/roguelike/package.json +1 -1
  10. package/archetypes/roguelike/project.ogt +1 -1
  11. package/archetypes/runner/package.json +1 -1
  12. package/archetypes/runner/project.ogt +1 -1
  13. package/archetypes/third-person/package.json +1 -1
  14. package/archetypes/third-person/project.ogt +1 -1
  15. package/archetypes/topdown/package.json +1 -1
  16. package/archetypes/topdown/project.ogt +1 -1
  17. package/archetypes/tower-defense/package.json +1 -1
  18. package/archetypes/tower-defense/project.ogt +1 -1
  19. package/bin/create.ts +71 -14
  20. package/package.json +5 -4
  21. package/template/package.json +1 -1
  22. package/template/project.ogt +1 -1
  23. package/template-2d/.origin/setup +14 -0
  24. package/template-2d/LICENSES.md +14 -0
  25. package/template-2d/README.md +39 -0
  26. package/template-2d/assets/audio/coin.wav +0 -0
  27. package/template-2d/assets/audio/jump.wav +0 -0
  28. package/template-2d/assets/fonts/OFL.txt +93 -0
  29. package/template-2d/assets/fonts/ui.ttf +0 -0
  30. package/template-2d/assets/fonts/ui.ttf.ogt +11 -0
  31. package/template-2d/assets/looks/origin-game-2d.ogt +12 -0
  32. package/template-2d/assets/maps/level.ogt +112 -0
  33. package/template-2d/assets/sprites/coin.ogt +11 -0
  34. package/template-2d/assets/sprites/coin.png +0 -0
  35. package/template-2d/assets/sprites/coin.png.ogt +7 -0
  36. package/template-2d/assets/sprites/courier.ogt +34 -0
  37. package/template-2d/assets/sprites/courier.png +0 -0
  38. package/template-2d/assets/sprites/courier.png.ogt +7 -0
  39. package/template-2d/assets/strings/en.ogt +11 -0
  40. package/template-2d/assets/tiles/city.ogt +17 -0
  41. package/template-2d/assets/tiles/city.png +0 -0
  42. package/template-2d/assets/tiles/city.png.ogt +7 -0
  43. package/template-2d/gitattributes +22 -0
  44. package/template-2d/gitignore +8 -0
  45. package/template-2d/package.json +18 -0
  46. package/template-2d/project.ogt +21 -0
  47. package/template-2d/src/main.ts +305 -0
  48. package/template-2d/tests/smoke.og.ts +60 -0
  49. package/template-2d/tsconfig.json +17 -0
package/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # @origingame/create-game
2
2
 
3
- Scaffolds an Origin Engine game from the project template (`templates/game`
4
- of the engine repository): `project.ogt`, `src/`, `assets/`, `tests/`,
3
+ Scaffolds an Origin Engine game from a project template of the engine
4
+ repository, the 3D template `templates/game` or the 2D starter
5
+ `templates/game-2d`: `project.ogt`, `src/`, `assets/`, `tests/`,
5
6
  `package.json` and `tsconfig.json`, with the game's name and id filled in.
6
7
 
7
8
  ```sh
@@ -9,13 +10,20 @@ bun packages/create/bin/create.ts my-game --name "My Game" # in the engine rep
9
10
  cd my-game && bun install && og cook && og run .
10
11
  ```
11
12
 
12
- `create [dir] [--name "Name"] [--id slug] [--archetype name] [--premise "one line"] [--look slug] [--force]`: the
13
+ `create [dir] [--name "Name"] [--id slug] [--profile 2d|3d] [--archetype name] [--premise "one line"] [--look slug] [--force]`: the
13
14
  id defaults to the name in lowercase-hyphen form (or the directory's name);
14
15
  a directory that is not empty is refused unless `--force` is given.
16
+ `--profile 2d` writes the 2D starter (a courier's platformer: sprites,
17
+ flipbooks, a tilemap with one-way ledges, 2D physics, a HUD and a pause
18
+ menu, one playtest), `--profile 3d` the 3D template; without the flag, a
19
+ premise that says 2D, platformer, side-scroller, metroidvania, pixel art,
20
+ sprites or tiles without saying 3D gets the 2D starter, anything else the
21
+ 3D template. The output's `Profile:` line says which and why.
15
22
  `--archetype` starts from a complete game of `templates/archetypes/`
16
- instead of the template: `runner`, `match3`, `topdown`, `tower-defense`,
23
+ instead of either template: `runner`, `match3`, `topdown`, `tower-defense`,
17
24
  `roguelike`, `idle`, `rhythm` or `third-person` (the published package carries them under
18
- `archetypes/`).
25
+ `archetypes/`); an archetype has its own profile, so `--profile` beside it
26
+ is refused.
19
27
 
20
28
  Every game gets its look: `assets/looks/<id>.ogt`, an `.ogt` of `type look`
21
29
  (og-taste §12 of the knowledge package) that `GameDesc.look` in the entry
@@ -42,8 +50,8 @@ is, what it extends and how to change it. For an archetype, a preset moves
42
50
  the frames its `references/` hold; create says so and how to record them
43
51
  again.
44
52
 
45
- The published package carries the template under `template/` and the style
46
- catalogue under `looks/`, copied by the `prepack` script
53
+ The published package carries the 3D template under `template/`, the 2D
54
+ starter under `template-2d/` and the style catalogue under `looks/`, copied by the `prepack` script
47
55
  (`scripts/pack-template.ts`); build output (`cooked/`,
48
56
  `dist/`, `node_modules/`) is never copied. The template's `gitattributes`
49
57
  (media through Git LFS) is written as the project's `.gitattributes`: under
@@ -1,8 +1,10 @@
1
1
  # Archetypes
2
2
 
3
3
  Complete games a Maker starts from, each a project like `templates/game`
4
- (`project.ogt`, `src/`, `assets/`, `tests/`, `package.json`,
5
- `tsconfig.json`) that `og run`, `og test` and `og build` take as is. They
4
+ and the 2D starter `templates/game-2d` (`project.ogt`, `src/`, `assets/`,
5
+ `tests/`, `package.json`, `tsconfig.json`) that `og run`, `og test` and
6
+ `og build` take as is; `npm create @origingame/game --archetype <name>`
7
+ writes one, with its own profile. They
6
8
  rebuild the platform's six Godot Discover prototypes on Origin Engine,
7
9
  keeping each prototype's premise and lessons and none of its code or art,
8
10
  and add a top-down room built for the engine's 2D and game-feel modules
@@ -13,6 +13,6 @@
13
13
  "test": "og test ."
14
14
  },
15
15
  "dependencies": {
16
- "@origingame/engine": "0.1.1"
16
+ "@origingame/engine": "0.2.0"
17
17
  }
18
18
  }
@@ -3,7 +3,7 @@ version 1
3
3
  ---
4
4
  name "Spark Orb"
5
5
  id "idle"
6
- engine "0.1.1"
6
+ engine "0.2.0"
7
7
  entry "src/main.ts"
8
8
  profile "2d"
9
9
  tick 60
@@ -13,6 +13,6 @@
13
13
  "test": "og test ."
14
14
  },
15
15
  "dependencies": {
16
- "@origingame/engine": "0.1.1"
16
+ "@origingame/engine": "0.2.0"
17
17
  }
18
18
  }
@@ -3,7 +3,7 @@ version 1
3
3
  ---
4
4
  name "Tile Swap"
5
5
  id "match3"
6
- engine "0.1.1"
6
+ engine "0.2.0"
7
7
  entry "src/main.ts"
8
8
  profile "2d"
9
9
  tick 60
@@ -13,6 +13,6 @@
13
13
  "test": "og test ."
14
14
  },
15
15
  "dependencies": {
16
- "@origingame/engine": "0.1.1"
16
+ "@origingame/engine": "0.2.0"
17
17
  }
18
18
  }
@@ -3,7 +3,7 @@ version 1
3
3
  ---
4
4
  name "Three-Lane Beat"
5
5
  id "rhythm"
6
- engine "0.1.1"
6
+ engine "0.2.0"
7
7
  entry "src/main.ts"
8
8
  profile "2d"
9
9
  tick 60
@@ -13,6 +13,6 @@
13
13
  "test": "og test ."
14
14
  },
15
15
  "dependencies": {
16
- "@origingame/engine": "0.1.1"
16
+ "@origingame/engine": "0.2.0"
17
17
  }
18
18
  }
@@ -3,7 +3,7 @@ version 1
3
3
  ---
4
4
  name "Lamp Dive"
5
5
  id "roguelike"
6
- engine "0.1.1"
6
+ engine "0.2.0"
7
7
  entry "src/main.ts"
8
8
  profile "2d"
9
9
  tick 60
@@ -13,6 +13,6 @@
13
13
  "test": "og test ."
14
14
  },
15
15
  "dependencies": {
16
- "@origingame/engine": "0.1.1"
16
+ "@origingame/engine": "0.2.0"
17
17
  }
18
18
  }
@@ -3,7 +3,7 @@ version 1
3
3
  ---
4
4
  name "Runner"
5
5
  id "runner"
6
- engine "0.1.1"
6
+ engine "0.2.0"
7
7
  entry "src/main.ts"
8
8
  profile "2d"
9
9
  tick 60
@@ -13,6 +13,6 @@
13
13
  "test": "og test ."
14
14
  },
15
15
  "dependencies": {
16
- "@origingame/engine": "0.1.1"
16
+ "@origingame/engine": "0.2.0"
17
17
  }
18
18
  }
@@ -3,7 +3,7 @@ version 1
3
3
  ---
4
4
  name "Ember Vale"
5
5
  id "third-person"
6
- engine "0.1.1"
6
+ engine "0.2.0"
7
7
  entry "src/main.ts"
8
8
  profile "3d"
9
9
  tick 60
@@ -13,6 +13,6 @@
13
13
  "test": "og test ."
14
14
  },
15
15
  "dependencies": {
16
- "@origingame/engine": "0.1.1"
16
+ "@origingame/engine": "0.2.0"
17
17
  }
18
18
  }
@@ -3,7 +3,7 @@ version 1
3
3
  ---
4
4
  name "Tomb Room"
5
5
  id "topdown"
6
- engine "0.1.1"
6
+ engine "0.2.0"
7
7
  entry "src/main.ts"
8
8
  profile "2d"
9
9
  tick 60
@@ -13,6 +13,6 @@
13
13
  "test": "og test ."
14
14
  },
15
15
  "dependencies": {
16
- "@origingame/engine": "0.1.1"
16
+ "@origingame/engine": "0.2.0"
17
17
  }
18
18
  }
@@ -3,7 +3,7 @@ version 1
3
3
  ---
4
4
  name "Path Guard"
5
5
  id "tower-defense"
6
- engine "0.1.1"
6
+ engine "0.2.0"
7
7
  entry "src/main.ts"
8
8
  profile "2d"
9
9
  tick 60
package/bin/create.ts CHANGED
@@ -2,13 +2,16 @@
2
2
  // `npm create @origingame/game` (and `bun create`): scaffolds the Origin
3
3
  // Engine project template (templates/game) into a directory, naming the game.
4
4
  //
5
- // create [dir] [--name "Name"] [--id slug] [--archetype runner|match3|...]
5
+ // create [dir] [--name "Name"] [--id slug] [--profile 2d|3d] [--archetype runner|match3|...]
6
6
  // [--premise "one line"] [--look <slug>] [--force]
7
7
  //
8
- // The template comes from ./template/ in the published package (prepack:
9
- // scripts/pack-template.ts) or ../../templates/game in the engine repository;
10
- // an archetype (a complete small game to start from) from ./archetypes/<name>/
11
- // or ../../templates/archetypes/<name>/.
8
+ // The template comes from ./template/ (the 3D template, templates/game) or
9
+ // ./template-2d/ (the 2D starter, templates/game-2d) in the published
10
+ // package (prepack: scripts/pack-template.ts), or from ../../templates/ in
11
+ // the engine repository; an archetype (a complete small game to start from)
12
+ // from ./archetypes/<name>/ or ../../templates/archetypes/<name>/. The 2D
13
+ // starter is written for --profile 2d, or for a premise that says 2D
14
+ // (platformer, side-scroller, metroidvania, pixel art) without saying 3D.
12
15
  //
13
16
  // Every game gets its look, `assets/looks/<id>.ogt`, named by GameDesc.look
14
17
  // in the entry: it extends the style catalogue's preset given by --look, or
@@ -46,6 +49,8 @@ export interface CreateOptions {
46
49
  readonly force?: boolean;
47
50
  /** Start from an archetype (`runner`, `match3`, `topdown`, `tower-defense`, `roguelike`, `idle`, `rhythm`, `third-person`: templates/archetypes/README.md) instead of the project template. */
48
51
  readonly archetype?: string;
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
+ readonly profile?: Profile;
49
54
  /** The template directory; found next to this file when omitted. */
50
55
  readonly template?: string;
51
56
  /** A style catalogue slug the game's look extends (og-taste §12). */
@@ -68,11 +73,22 @@ export interface CreatedLook {
68
73
  readonly chosen: "flag" | "premise" | "template" | "none";
69
74
  }
70
75
 
76
+ /** A project's profile (`project.ogt`'s `profile` line): 2D or 3D. */
77
+ export type Profile = "2d" | "3d";
78
+
79
+ /** The profile the game was written in, and how it was chosen. */
80
+ export interface CreatedProfile {
81
+ readonly value: Profile;
82
+ /** `flag` for --profile, `premise` for a premise that says 2D, `archetype` for an archetype's own, `template` for the 3D template by default. */
83
+ readonly chosen: "flag" | "premise" | "archetype" | "template";
84
+ }
85
+
71
86
  export interface Created {
72
87
  readonly dir: string;
73
88
  readonly name: string;
74
89
  readonly id: string;
75
90
  readonly files: readonly string[];
91
+ readonly profile: CreatedProfile;
76
92
  readonly look: CreatedLook;
77
93
  /** What the game's author should know, such as reference frames a look will move. */
78
94
  readonly notes: readonly string[];
@@ -164,8 +180,30 @@ function title(id: string): string {
164
180
  .join(" ");
165
181
  }
166
182
 
167
- /** The template this copy of the package scaffolds. */
168
- export function templateDir(archetype?: string): string {
183
+ /** Words of a premise that say the game is 2D (platformer, side-scroller, metroidvania, pixel art, sprites, tiles). */
184
+ const TWO_D = new Set(["platformer", "platforming", "side-scroller", "side-scrolling", "sidescroller", "sidescrolling", "scroller", "metroidvania", "pixel", "pixel-art", "pixelart", "sprite", "tilemap", "tile", "8bit", "16bit", "1bit"]);
185
+ const THREE_D = new Set(["third-person", "first-person", "fps", "voxel", "lowpoly", "low-poly"]);
186
+
187
+ /**
188
+ * The profile a premise asks for: `2d` when it uses a 2D word (TWO_D, or
189
+ * `2D` itself) and no 3D word (THREE_D, or `3D`), else null: the template's
190
+ * own, 3D, applies.
191
+ */
192
+ export function premiseProfile(premise: string): Profile | null {
193
+ const asked = new Set(words(premise));
194
+ const says = (w: string) => new RegExp(`(^|[^a-z0-9])${w}($|[^a-z0-9])`, "i").test(premise);
195
+ if (says("3d") || [...THREE_D].some((w) => asked.has(w))) return null;
196
+ return says("2d") || [...TWO_D].some((w) => asked.has(w)) ? "2d" : null;
197
+ }
198
+
199
+ /** The `profile "2d"` line of a project manifest; `3d` when it has none. */
200
+ function profileOf(dir: string): Profile {
201
+ const m = /^profile[ \t]+"(2d|3d)"/m.exec(readFileSync(join(dir, "project.ogt"), "utf8"));
202
+ return m?.[1] === "2d" ? "2d" : "3d";
203
+ }
204
+
205
+ /** The template this copy of the package scaffolds: the archetype's, or the project template of a profile (3D unless `2d`). */
206
+ export function templateDir(archetype?: string, profile: Profile = "3d"): string {
169
207
  const here = dirname(fileURLToPath(import.meta.url));
170
208
  if (archetype !== undefined) {
171
209
  const roots = [join(here, "..", "archetypes"), join(here, "..", "..", "..", "templates", "archetypes")];
@@ -175,10 +213,12 @@ export function templateDir(archetype?: string): string {
175
213
  const known = roots.filter(existsSync).flatMap((r) => readdirSync(r).filter((d) => existsSync(join(r, d, "project.ogt"))));
176
214
  throw new Error(`no archetype '${archetype}': choose one of ${[...new Set(known)].sort().join(", ") || "(none shipped)"}`);
177
215
  }
178
- for (const candidate of [join(here, "..", "template"), join(here, "..", "..", "..", "templates", "game")]) {
216
+ const packed = profile === "2d" ? "template-2d" : "template";
217
+ const source = profile === "2d" ? "game-2d" : "game";
218
+ for (const candidate of [join(here, "..", packed), join(here, "..", "..", "..", "templates", source)]) {
179
219
  if (existsSync(join(candidate, "project.ogt"))) return candidate;
180
220
  }
181
- throw new Error(`no project template next to ${here}: expected ../template (published package) or ../../../templates/game (engine repository)`);
221
+ throw new Error(`no ${profile} project template next to ${here}: expected ../${packed} (published package) or ../../../templates/${source} (engine repository)`);
182
222
  }
183
223
 
184
224
  function ogtString(value: string): string {
@@ -322,8 +362,16 @@ export function create(options: CreateOptions): Created {
322
362
  throw new Error(`${dir} is not empty; pick an empty directory, or pass --force to write the template over it`);
323
363
  }
324
364
  }
365
+ if (options.profile !== undefined && options.archetype !== undefined) {
366
+ throw new Error(`--profile and --archetype together: an archetype has its own profile (${options.archetype}); drop one`);
367
+ }
325
368
  const choice = chooseStyle(options);
326
- const template = options.template ?? templateDir(options.archetype);
369
+ const asked = options.profile ?? (options.premise !== undefined ? premiseProfile(options.premise) : null);
370
+ const template = options.template ?? templateDir(options.archetype, asked ?? "3d");
371
+ const profile: CreatedProfile = {
372
+ value: profileOf(template),
373
+ chosen: options.archetype !== undefined ? "archetype" : options.profile !== undefined ? "flag" : asked !== null ? "premise" : "template",
374
+ };
327
375
  const list = files(template);
328
376
  const written: string[] = [];
329
377
  mkdirSync(dir, { recursive: true });
@@ -342,7 +390,7 @@ export function create(options: CreateOptions): Created {
342
390
  writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
343
391
  }
344
392
  const { look, notes } = writeLook(dir, name, id, choice, written);
345
- return { dir, name, id, files: written, look, notes };
393
+ return { dir, name, id, files: written, profile, look, notes };
346
394
  }
347
395
 
348
396
  /**
@@ -427,12 +475,13 @@ function writeLook(dir: string, name: string, id: string, choice: ReturnType<typ
427
475
  return { look, notes };
428
476
  }
429
477
 
430
- const USAGE = `usage: create [dir] [--name "Name"] [--id slug] [--archetype name] [--premise "one line"] [--look slug] [--force]
478
+ const USAGE = `usage: create [dir] [--name "Name"] [--id slug] [--profile 2d|3d] [--archetype name] [--premise "one line"] [--look slug] [--force]
431
479
 
432
480
  Scaffolds an Origin Engine game into dir (default: ./origin-game).
433
481
  --name the game's display name (default: from the id or the directory)
434
482
  --id the game's id, lowercase-hyphen (default: from the name)
435
- --archetype start from a complete archetype game (runner, match3, topdown, tower-defense, roguelike, idle, rhythm, third-person) instead of the template
483
+ --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
436
485
  --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)
437
486
  --look the style catalogue slug the look extends (og-taste §12), such as anime-cel-3d or 16bit-pixel
438
487
  --no-prompt never ask for the premise
@@ -444,6 +493,7 @@ function main(argv: string[]): number {
444
493
  let id: string | undefined;
445
494
  let force = false;
446
495
  let archetype: string | undefined;
496
+ let profile: Profile | undefined;
447
497
  let premise: string | undefined;
448
498
  let look: string | undefined;
449
499
  let ask = true;
@@ -458,7 +508,11 @@ function main(argv: string[]): number {
458
508
  else if (a === "--id") id = value();
459
509
  else if (a === "--force") force = true;
460
510
  else if (a === "--archetype") archetype = value();
461
- else if (a === "--premise") premise = value();
511
+ else if (a === "--profile") {
512
+ const v = value();
513
+ if (v !== "2d" && v !== "3d") throw new Error(`--profile ${v}: use 2d or 3d. ${USAGE}`);
514
+ profile = v;
515
+ } else if (a === "--premise") premise = value();
462
516
  else if (a === "--look") look = value();
463
517
  else if (a === "--no-prompt") ask = false;
464
518
  else if (a === "-h" || a === "--help") {
@@ -476,13 +530,16 @@ function main(argv: string[]): number {
476
530
  ...(name ? { name } : {}),
477
531
  ...(id ? { id } : {}),
478
532
  ...(archetype ? { archetype } : {}),
533
+ ...(profile ? { profile } : {}),
479
534
  ...(premise ? { premise } : {}),
480
535
  ...(look ? { look } : {}),
481
536
  force,
482
537
  });
483
538
  const shown = relative(process.cwd(), made.dir) || ".";
484
539
  const style = made.look.extends ? `extends ${made.look.extends}${made.look.chosen === "premise" ? " (from the premise)" : made.look.chosen === "flag" ? " (--look)" : ""}` : "extends no preset";
540
+ const how = { flag: " (--profile)", premise: " (from the premise)", archetype: ` (the ${archetype} archetype's)`, template: "" }[made.profile.chosen];
485
541
  console.log(`Created ${made.name} (${made.id}) in ${shown}: ${made.files.length} files.
542
+ Profile: ${made.profile.value}${how}.
486
543
  Look: ${made.look.file}, ${style}; README.md says how to change it.${made.notes.map((n) => `\nNote: ${n}`).join("")}
487
544
 
488
545
  Next:
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@origingame/create-game",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Scaffolds an Origin Engine game from the project template: npm create @origingame/game.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "git+https://github.com/fran0220/origin-engine.git",
8
+ "url": "git+https://github.com/originai-game/origin-engine.git",
9
9
  "directory": "packages/create"
10
10
  },
11
- "homepage": "https://github.com/fran0220/origin-engine#readme",
11
+ "homepage": "https://github.com/originai-game/origin-engine#readme",
12
12
  "bugs": {
13
- "url": "https://github.com/fran0220/origin-engine/issues"
13
+ "url": "https://github.com/originai-game/origin-engine/issues"
14
14
  },
15
15
  "publishConfig": {
16
16
  "access": "public"
@@ -22,6 +22,7 @@
22
22
  "files": [
23
23
  "bin",
24
24
  "template",
25
+ "template-2d",
25
26
  "archetypes",
26
27
  "looks",
27
28
  "README.md"
@@ -13,6 +13,6 @@
13
13
  "test": "og test ."
14
14
  },
15
15
  "dependencies": {
16
- "@origingame/engine": "0.1.1"
16
+ "@origingame/engine": "0.2.0"
17
17
  }
18
18
  }
@@ -7,7 +7,7 @@ version 1
7
7
  name "Origin Game"
8
8
  id "origin-game"
9
9
  # The engine this game is written against (design §9: upgrades are explicit).
10
- engine "0.1.1"
10
+ engine "0.2.0"
11
11
  entry "src/main.ts"
12
12
  # 2d (orthographic camera, sprites, 2D physics) or 3d.
13
13
  profile "3d"
@@ -0,0 +1,14 @@
1
+ #!/bin/sh
2
+ # Prepares this Game's cloud sandbox snapshot: Origin runs it once per
3
+ # snapshot build, in the checkout, without a terminal, for at most 20 minutes,
4
+ # and saves the result for new sandboxes of the Game. Keep it idempotent; it
5
+ # never receives credentials. Only ignored output is kept: node_modules/ and
6
+ # cooked/ (og cook is incremental, so a new sandbox starts cooked).
7
+ set -eu
8
+ if [ -f bun.lock ]; then bun install --frozen-lockfile; else bun install; fi
9
+ og="${ORIGIN_OG_BIN:-og}"
10
+ if ! command -v "$og" >/dev/null 2>&1; then
11
+ echo "no og on this executor class; the first og run cooks instead"
12
+ exit 0
13
+ fi
14
+ "$og" cook .
@@ -0,0 +1,14 @@
1
+ # Asset licences
2
+
3
+ Nothing in this project is downloaded: the art and sounds are the engine's
4
+ runner archetype's (`templates/archetypes/runner`, drawn and synthesised by
5
+ its `tools/make-assets.py`), and the rest is written by hand.
6
+
7
+ | File | Licence | Origin |
8
+ |---|---|---|
9
+ | `assets/sprites/courier.png`, `assets/sprites/coin.png` and their `.ogt` | CC0 1.0 | self-made: the runner archetype's courier and coin |
10
+ | `assets/tiles/city.png` | CC0 1.0 | self-made: the runner archetype's city tileset |
11
+ | `assets/tiles/city.ogt`, `assets/maps/level.ogt` | CC0 1.0 | self-made, written by hand |
12
+ | `assets/audio/jump.wav`, `assets/audio/coin.wav` | CC0 1.0 | self-made: the runner archetype's synthesised tones |
13
+ | `assets/fonts/ui.ttf` | SIL Open Font License 1.1 (`assets/fonts/OFL.txt`) | Noto Sans SC Regular, subset to Latin-1 by the runner archetype from the project template's `assets/fonts/NotoSansSC-Regular-subset.ttf` |
14
+ | `assets/looks/*.ogt`, `assets/strings/*.ogt`, every other `.ogt` | CC0 1.0 | self-made, written by hand |
@@ -0,0 +1,39 @@
1
+ # The 2D starter
2
+
3
+ What `npm create @origingame/game` writes for a 2D game (`--profile 2d`, or
4
+ a premise that says 2D, platformer, side-scroller, metroidvania or pixel
5
+ art): the smallest whole 2D Origin Engine project. A courier runs and jumps
6
+ the rooftops of one level, takes coins, jumps up through one-way ledges and
7
+ lands on them, loses a life in the pit and clears the level at the far
8
+ wall; Escape (or the HUD's Pause) opens the pause menu.
9
+
10
+ ```sh
11
+ og run . # headless with the probe; og dev . reloads on save
12
+ og test . # tests/smoke.og.ts
13
+ og build . # the play page
14
+ ```
15
+
16
+ ## What it demonstrates, and the skills it exercises
17
+
18
+ | Part | Where | Skill |
19
+ |---|---|---|
20
+ | The project in the 2D profile: an orthographic camera, sprites, 2D physics | `project.ogt`, `start` in `src/main.ts` | og-game §2, §8 |
21
+ | A hand-written tilemap over a tileset: a parallax skyline, roofs that collide, ledges on their own collider layer (`colliderLayers 2`) that the controller makes one-way | `assets/maps/level.ogt`, `assets/tiles/city.ogt` | og-game §8 (the grammar) |
22
+ | A flipbook sheet, its clips numbered in file order and checked against the code | `assets/sprites/courier.ogt`, `CLIP`, `checkClips` | og-game §8 |
23
+ | og.PlatformerController: run, jump (held for the full height), coyote time, the jump buffer, one-way ledges, Down to drop | `Control`, the hero in `start` | og-game §13; og-feel §12 |
24
+ | The map's objects: the spawn, the coins, the goal | `start`, `Pickups` | og-game §8 |
25
+ | Input on the press's tick: keys, a pad, the HUD's touch controls on a phone | `Control`, `Hud` | og-feel §1; og-ui §5 |
26
+ | The UI kit's platformer HUD and pause menu, every word from the string table | `Hud`, `assets/strings/en.ogt` | og-ui §1, §6; og-i18n §1 |
27
+ | A camera that follows with a dead zone and look-ahead | og.Follow2D on the hero | og-feel §8 |
28
+ | The frame's art direction as data: a look extending the 16bit-pixel preset | `assets/looks/origin-game-2d.ogt` (a created game's is `<id>.ogt`) | og-taste §1, §12 |
29
+ | A playtest that asserts on dumps, never on the code | `tests/smoke.og.ts` | og-build §3, §4 |
30
+
31
+ What a game made from it changes first: the art (the courier and the city
32
+ are the runner archetype's, `templates/archetypes/runner/tools/make-assets.py`
33
+ draws them), the level (`assets/maps/level.ogt`, or a Tiled `.tmj` beside
34
+ it, og-game §8), the controller's tunables (og-feel §12) and what the map's
35
+ objects mean. The 2D archetypes (`templates/archetypes/`) are whole games
36
+ to start from instead: a runner, a top-down room, match-3, a roguelike,
37
+ tower defence, an idle game and a rhythm game.
38
+
39
+ Asset licences: `LICENSES.md`.
@@ -0,0 +1,93 @@
1
+ Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ https://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
Binary file
@@ -0,0 +1,11 @@
1
+ type import
2
+ version 1
3
+ ---
4
+ # The HUD's font: Noto Sans SC Regular subset to Latin-1 (the runner
5
+ # archetype's assets/fonts/ui.ttf). A language with other characters needs
6
+ # a font that holds them (og-i18n §2).
7
+ font {
8
+ charset latin
9
+ em_px 48
10
+ px_range 6
11
+ }