Skip to content

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.

Create a project from the example template, then install it. Install covers the one-time token that the install needs.

Terminal window
npx --@daniel-zarinski:registry=https://npm.pkg.github.com @daniel-zarinski/cli create my-game --template example
cd my-game && pnpm install

The project holds the files this page walks through. The same files live in the repository under games/example.

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.

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.

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.

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.

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.

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.

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.

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.

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.

  1. Step the run scene in Node for 21 seconds. With no keys down, the player stands still, and the dump shows the round’s state as lost:

    Terminal window
    pnpm exec game simulate --scene run --seconds 21
  2. Step it again with the player walking forward. The player collects the three coins, and the round’s state reads won:

    Terminal window
    pnpm exec game simulate --scene run --keys w --seconds 5
  3. 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
  4. 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"
  5. 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.