@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.
- package/README.md +15 -7
- package/archetypes/README.md +4 -2
- package/archetypes/idle/package.json +1 -1
- package/archetypes/idle/project.ogt +1 -1
- package/archetypes/match3/package.json +1 -1
- package/archetypes/match3/project.ogt +1 -1
- package/archetypes/rhythm/package.json +1 -1
- package/archetypes/rhythm/project.ogt +1 -1
- package/archetypes/roguelike/package.json +1 -1
- package/archetypes/roguelike/project.ogt +1 -1
- package/archetypes/runner/package.json +1 -1
- package/archetypes/runner/project.ogt +1 -1
- package/archetypes/third-person/package.json +1 -1
- package/archetypes/third-person/project.ogt +1 -1
- package/archetypes/topdown/package.json +1 -1
- package/archetypes/topdown/project.ogt +1 -1
- package/archetypes/tower-defense/package.json +1 -1
- package/archetypes/tower-defense/project.ogt +1 -1
- package/bin/create.ts +71 -14
- package/package.json +5 -4
- package/template/package.json +1 -1
- package/template/project.ogt +1 -1
- package/template-2d/.origin/setup +14 -0
- package/template-2d/LICENSES.md +14 -0
- package/template-2d/README.md +39 -0
- package/template-2d/assets/audio/coin.wav +0 -0
- package/template-2d/assets/audio/jump.wav +0 -0
- package/template-2d/assets/fonts/OFL.txt +93 -0
- package/template-2d/assets/fonts/ui.ttf +0 -0
- package/template-2d/assets/fonts/ui.ttf.ogt +11 -0
- package/template-2d/assets/looks/origin-game-2d.ogt +12 -0
- package/template-2d/assets/maps/level.ogt +112 -0
- package/template-2d/assets/sprites/coin.ogt +11 -0
- package/template-2d/assets/sprites/coin.png +0 -0
- package/template-2d/assets/sprites/coin.png.ogt +7 -0
- package/template-2d/assets/sprites/courier.ogt +34 -0
- package/template-2d/assets/sprites/courier.png +0 -0
- package/template-2d/assets/sprites/courier.png.ogt +7 -0
- package/template-2d/assets/strings/en.ogt +11 -0
- package/template-2d/assets/tiles/city.ogt +17 -0
- package/template-2d/assets/tiles/city.png +0 -0
- package/template-2d/assets/tiles/city.png.ogt +7 -0
- package/template-2d/gitattributes +22 -0
- package/template-2d/gitignore +8 -0
- package/template-2d/package.json +18 -0
- package/template-2d/project.ogt +21 -0
- package/template-2d/src/main.ts +305 -0
- package/template-2d/tests/smoke.og.ts +60 -0
- 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
|
|
4
|
-
|
|
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
|
|
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
|
|
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
|
package/archetypes/README.md
CHANGED
|
@@ -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/`,
|
|
5
|
-
`tsconfig.json`) that `og run`, `og test` and
|
|
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
|
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/
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
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
|
-
/**
|
|
168
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
--
|
|
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 === "--
|
|
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.
|
|
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/
|
|
8
|
+
"url": "git+https://github.com/originai-game/origin-engine.git",
|
|
9
9
|
"directory": "packages/create"
|
|
10
10
|
},
|
|
11
|
-
"homepage": "https://github.com/
|
|
11
|
+
"homepage": "https://github.com/originai-game/origin-engine#readme",
|
|
12
12
|
"bugs": {
|
|
13
|
-
"url": "https://github.com/
|
|
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"
|
package/template/package.json
CHANGED
package/template/project.ogt
CHANGED
|
@@ -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`.
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
+
}
|