Your first game
This page walks through the example game, one piece at a time: a lobby with a Play button, then a run where the player collects three coins before a 20-second clock runs out. It is for a developer who writes the code. Each step says what a piece does and links the following:
- The API reference page for the component, with its props and a working signature.
- The file in the example game that uses it.
At the end, you step the game headless, take a screenshot of it, and play it in the browser. To have an agent build a game with you instead, see Connect your agent.
Every game on the engine has the following shape. A game holds scenes, a scene holds a world, and a world holds entities, each with the behaviours that make it act:
flowchart TB
Game --> Scene --> World --> Entity --> Behaviour
Scene -.-> UI
Solid arrows are nesting. The dotted arrow is UI, which draws on the screen over the world. How a game fits together explains each level.
1. Create the project
Section titled “1. Create the project”Create a project from the example template, then install it. Install covers the one-time token that the install needs.
npx --@daniel-zarinski:registry=https://npm.pkg.github.com @daniel-zarinski/cli create my-game --template examplecd my-game && pnpm installThe project holds the files this page walks through. The same files live in the repository under games/example.
2. Mount the game and its scenes
Section titled “2. Mount the game and its scenes”A Game holds the scenes and says which one opens first. Each Scene names one screen of the game and the component that draws it. The example opens on the lobby and moves to the run.
- Reference: Game and Scene.
- Example: src/app/app.tsx.
The same file mounts the devtools in development, or with ?debug in the URL. The playtest in step 7 drives the game through them: src/app/devtools.tsx.
3. Build the lobby
Section titled “3. Build the lobby”A scene renders a World, and everything in the scene stands inside it. The meadow map ships with the engine. The Player spawns at the origin, and the Camera stays free rather than following the player. In the run, the camera follows the player. A Button in a Hud moves the game to the run.
- Reference: World, Player, Camera and Button.
- Example: src/scenes/Lobby.tsx.
4. Add the coins
Section titled “4. Add the coins”A coin is an Entity with a Pickup. The player who walks within its radius takes the reward into their wallet, and the coin goes. Spin and Bob move it so that it reads as a coin.
- Reference: Entity, Pickup, Spin and Bob.
- Example: src/components/Coin.tsx, placed three times ahead of the player in src/scenes/Run.tsx.
The run also holds the following entities:
- A ball the player can push, with a collider: Ball.tsx.
- A tree the player walks around, with a collider: Tree.tsx.
- A spinning ring past the coins, which marks the end of the run. The round ends on the coins, not on the ring: Ring.tsx.
The run also plays forest sound with Sound, and shows how to play in a Hud at the bottom of the screen.
5. Add the round
Section titled “5. Add the round”A Round counts down simulated seconds and reads the score from the player’s wallet. The example’s round lasts 20 seconds and is won with three coins. It starts when the scene opens.
- Reference: Round and RoundScreen.
- Example: src/scenes/Run.tsx.
The round is won on the step the third coin lands in the wallet, and lost on the step the clock runs out first. RoundScreen then opens the win or lose dialog, which pauses the world. A game with a rule that Round does not cover writes its own system and passes it to Game.
6. Add the HUD
Section titled “6. Add the HUD”The HUD reads the round with useRound() and draws the seconds left and the score in a Panel at the top of the screen. A Hud draws in the screen layer, over the canvas. The example also shows the wallet at the game’s level, so it reads the same in every scene.
- Reference: useRound, Hud, Panel and useWallet.
- Example: src/components/RoundClock.tsx, and the wallet in src/app/app.tsx.
7. Playtest and run
Section titled “7. Playtest and run”The game commands run the game with no window and report what happened, so you test the game without playing it. Install Chromium once. A game in its own folder does not depend on Playwright, so run the version the CLI pins: pnpm dlx playwright@1.63.0 install chromium. Inside the repository, pnpm exec playwright install chromium does the same. The CLI’s README lists every command.
-
Step the run scene in Node for 21 seconds. With no keys down, the player stands still, and the dump shows the round’s
stateaslost:Terminal window pnpm exec game simulate --scene run --seconds 21 -
Step it again with the player walking forward. The player collects the three coins, and the round’s
statereadswon:Terminal window pnpm exec game simulate --scene run --keys w --seconds 5 -
Start the playtest in Chromium. It prints the page’s URL and the scene’s tree, and the world holds still until you step it:
Terminal window pnpm exec game play start -
Step the lobby for one second, then take a screenshot of that step. The command prints the PNG’s path:
Terminal window pnpm exec game play screenshot --until "steps >= 60" -
Stop the playtest:
Terminal window pnpm exec game play stop
The Devtools API covers what the playtest calls.
To play the game yourself, run pnpm dev and open the URL it prints. Press Play, then walk with WASD.