Starting a game
From yarn new-game to the first thing of its own playing.
This page covers a new game from yarn new-game to its first kind of its own playing in one tab and against its server.
Making the folder
- From the repo's root, run
yarn new-game <name>. It writesgames/<name>/with one scene,main(playfor a game namedmain), 960 by 540 pixels, on its own port. The name is a lower-case letter followed by lower-case letters, digits and underscores, and may not bestart,player,body, a plugin's or addon's name, or an existing game. It refuses any other name and writes nothing. - Name the game after the game, never after a kind it will have:
<game>.sim.tsis the manager's file, so a kind with the game's name would collide with it.
| File | What it is |
|---|---|
<game>.scene.json | The manager scene: the game's scenes, the entry scene every connection enters, the port, and the step dt. Its world and prefabs sit under every scene's own, so a value every scene uses is written once here. |
<game>.sim.ts | The manager's code, which only lists scenemanager. |
main.scene.json, main.sim.ts | The scene on loader, scenemanager, player and render2d, and the list of every kind it makes rows of. |
start.sim.ts | Where a seat starts. No rule and no drawing. |
player.sim.ts, player.client.ts | The row a seat plays as, and its arrow keys. |
body.sim.ts, body.client.ts | A square on a row of its own, which the next step folds into the player row. |
assets/<game>.json | The definitions: each kind's fixed numbers. |
index.html, client.html, <game>.server.ts | The game in one tab; one seat over a socket; the server on node. |
Folding the body into the player row
The thing a seat plays as is its own player row (Designing a seat), so the template's separate body row is moved onto it first.
- In
main.scene.json, give theplayerprefab"seat": 0, "placed": false, "pos": [0, 0], "move": [0, 0]and delete thebodyprefab. Addworld.predict:{ "epsilon": 0.000001, "cutoff": 60, "halflife": 100, "snap": 5, "below": 0.001 }. See predict. - In
assets/<game>.json, rename thebodyentry toplayer, keeping itsspeed,sizeandcolour. - Move the body's rule into
player.sim.ts:beforestands the row on thestartof its slot once and setsplaced;tickruns it at its definition'sspeedalongmove; themoveact stores the direction, at most one unit long. Use math'shypot, notMath.hypot. - Move the body's drawing into
player.client.ts, drawn for every seat's row, and bind the arrow keys only for the row markedmine. - Delete
body.sim.tsandbody.client.tsand removebodyfrommain.sim.ts. - Rewrite
client.htmlso its link is wrapped inpredict, callingpage.input()thenawait page.frame(now)each frame.
Where the first numbers go
Every number is in the scene file or a data file it names, as Where things go sets out. A rule that rolls w.die() needs a world.seed in its scene. The canvas size is the width and height of the scene's engine prefab. Every file the game reads is an entry of world.loader.assets, with its path from the repo's root.
The first kind of its own
For a coin that jumps somewhere new when a seat's square reaches it:
- Its prefab, the fields that change:
prefabs.coin: { "pos": [0, 0], "taken": 0 }. - Its
actorsentry:{ "is": "coin", "pos": [640, 270] }. - Its definition in
assets/<game>.json:{ "reach": 24, "size": 16, "colour": "#5ad1e8", "bounds": [[16, 16], [944, 524]] }. - Its rule,
coin.sim.ts, and its drawing,coin.client.ts, both reading fixed numbers off the definition. - Its name in
main.sim.ts'ssim, and aworld.seedif its rule rolls the die.
Every seat sees it with nothing more. More in Designing a kind.
The testbed
Copy index.html to dev.html to try things: enter any scene, override any value of a scene, prefab or definition in the page's copy before the boot, and add readouts. Nothing else reads it, and what it finds goes into the scene or data files.
Checking it
- Run
yarn editor <game>and openlocalhost:5173/games/<game>/index.html. The square moves with the arrow keys. - From the repo's root, run
node --experimental-strip-types games/<game>/<game>.server.tsand openclient.html. The square moves on the frame after the key goes down. - A second seat needs the scene's
seatsraised and astartentry for slot 1, then a secondclient.htmltab. A second tab ofindex.htmlis a second game. - Run the game's test from the repo's root:
yarn vitest run games/<game>/<game>.sim.test.ts.