# Make your first game

> Place objects, give them physics and behaviour, test with Play, then save and export a playable build.

Source: https://feather-engine.com/docs/getting-started/first-game/

This walkthrough covers the full authoring loop in Feather 2: add objects, configure physics, attach
behaviour, play-test in the viewport, save a portable project and export a native player. It takes
about ten minutes and uses only built-in content.

Before you start, [install and run the editor](/docs/getting-started/install/).

## 1. Create a project

1. Choose **File → New project…**. A new project starts with a procedural meadow landscape and a
   player start.
2. Alternatively, keep the **Shred & Sort** starter the editor opens by default and edit that.

## 2. Place objects

1. Click **Add** in the toolbar and choose a built-in object: **Group**, **Tree**, **Rock**,
   **Cottage**, **Crystal**, **Cube**, **Sphere** or **Plane**.
2. To use your own model, click **Import** (or **File → Import GLB model…**) and choose a `.glb`
   file. See [Assets](/docs/concepts/assets/) for what the importer accepts.
3. Select objects in the viewport or the **Outliner**.
4. Press **W**, **E** or **R** to move, rotate or scale with the viewport gizmo, or type exact values
   in **Details → Transform**. A root object's height is measured in metres above the terrain.
5. Press **F** to frame the selection and **Cmd/Ctrl+D** to duplicate it.

You can also drag a card from the **Content Browser** into the viewport; it lands on the ground under
the cursor.

## 3. Add physics

Select an object and open **Details → Physics**.

| Setting | What it does |
| --- | --- |
| **Preset** | Applies a ready-made body setup in one step |
| **Body** | **None**, **Static**, **Dynamic** or **Kinematic**. Dynamic bodies fall and collide during Play |
| **Collider** | **Box**, **Sphere**, **Capsule**, **Hull** (convex hull) or **Mesh** (exact triangles; Static and Kinematic only) |
| **Half extents** and **Centre offset** | The collider's size and offset in metres. **Fit box** sizes it to an imported model |
| **Friction**, **Bounce**, **Mass** | Surface and body properties. Mass is in kilograms |
| **Sensor** | The collider reports overlaps but blocks nothing |

For a quick test, add a **Cube**, raise it a few metres, and set **Body** to **Dynamic**.

## 4. Add behaviour

Feather offers three ways to make an object do something. They can be combined on one object.

| Option | Where | Use it for |
| --- | --- | --- |
| Behaviours | **Details → Behaviours** | Spin, bobbing and collectibles, with no code |
| Script | **Details → Script**, or **Tools → Script editor** | Rhai code with `start()` and `update(dt)` |
| Blueprint | **Tools → Blueprints** | A visual node graph compiled to the same runtime |

1. For a collectible, add a **Crystal**, open **Details → Behaviours**, turn on **Collectible** and set
   **Score per item**. Walking into it during Play collects it.
2. For code, click **Add script** in **Details → Script**. The default script rotates the object:

   ```rust
   fn update(dt) {
       rotate(0.0, dt, 0.0);
   }
   ```

3. Press **Cmd/Ctrl+Enter** or click **Apply script** to commit the change. Applying creates an undo
   step.

See [Scripting](/docs/logic/scripting/) and [Blueprints](/docs/logic/blueprints/) for the full APIs.

## 5. Play and stop

1. Click **Play** in the centre of the toolbar. The **Play in** dropdown beside it can run the game
   in the viewport or in its own window instead.
2. Walk with **WASD**, look with the mouse — Play captures the cursor when it starts; press
   **Shift+F1** to free it — jump with **Space** and run with **Shift**.
3. Press **Stop** or **Escape** to return to editing.

Editing is locked during Play, so the simulation cannot change your saved project. Stop restores
every object to its authored state. Script messages and errors appear in the **Output Log** tab.

:::tip
The pin button next to **Play** starts the game at the editor camera's position, facing the way it
looks. Use it to test one area of a large level.
:::

## 6. Save

1. Press **Cmd/Ctrl+S**, or choose **File → Save project**.
2. Choose a folder and file name. The project is saved as a `.feather.json` file with an `assets/`
   folder beside it containing every imported file it uses.

Keep the project file and its `assets/` folder together when you move or share the project. See
[Projects](/docs/concepts/projects/).

## 7. Build

1. Choose **File → Build for this computer**, or **File → Build game…** to pick platforms and settings.
2. Feather validates the project and builds a standalone copy of your game, with the native player,
   the project and its assets.
3. Run it to play the game outside the editor.

See [Build a game](/docs/shipping/export/) for every platform and setting.

## Example: a spinning crystal worth 10 points

You'll put a collectible crystal in front of the player start and a cube that falls when Play
begins, starting from a new project.

1. Choose **File → New project…**. The player start sits at X 0, Z 8, facing towards negative Z.
2. Choose **Add → Crystal**. In **Details → Transform**, set **Location** to `0`, `1`, `2` and name
   it `Seed`.
3. Open **Details → Behaviours**. Set **Spin °/s** to `0`, `90`, `0`, turn on **Collectible** and set
   **Score per item** to `10`.
4. Choose **Add → Cube** and set its **Location** to `3`, `5`, `0`.
5. In the cube's **Details → Physics**, set **Body** to **Dynamic**.
6. Press **Play** and walk forward with **W**. The cube drops onto the grass, and the crystal
   disappears when you walk into it.

Do the same from the command line:

```bash
feather-cli --workspace ./crystal-hunt command project.create \
  --json '{"name":"Crystal Hunt"}' --save project.feather.json

feather-cli --workspace ./crystal-hunt --project project.feather.json command scene.add \
  --json '{"kind":"Crystal","name":"Seed","position":[0,1,2]}' --save project.feather.json

# rotate_speed is in radians per second: 1.5708 is 90°/s.
feather-cli --workspace ./crystal-hunt --project project.feather.json command scene.update \
  --json '{"id":1,"patch":{"gameplay":{"collectible":true,"score":10,"rotate_speed":[0,1.5708,0]}}}' \
  --save project.feather.json

feather-cli --workspace ./crystal-hunt --project project.feather.json command scene.add \
  --json '{"kind":"Cube","name":"Falling cube","position":[3,5,0]}' --save project.feather.json

feather-cli --workspace ./crystal-hunt --project project.feather.json command scene.update \
  --json '{"id":2,"patch":{"physics":{"body":"Dynamic"}}}' --save project.feather.json
```

Check it worked by holding **W** for three seconds of simulated play:

```bash
feather-cli --workspace ./crystal-hunt --project project.feather.json command game.simulate \
  --json '{"frames":180,"inputs":[{"frame":0,"key":"W","pressed":true}]}'
```

The report should contain `"score": 10` and the log entry `Collected Seed (+10).`. The crystal's
`final.visible` is `false`, and the cube's `final.position` is lower than its `initial.position`.

## Automate it

Every step above is also a command. This builds and checks a small scene without opening a window:

```bash
feather-cli --workspace ./my-game command scene.add \
  --json '{"kind":"Cube","name":"Falling cube","position":[0,4,0]}' \
  --save game.feather.json

feather-cli --workspace ./my-game --project game.feather.json command scene.update \
  --json '{"id":1,"patch":{"physics":{"body":"Dynamic"}}}' --save game.feather.json

feather-cli --workspace ./my-game --project game.feather.json \
  command game.simulate --json '{"frames":120}'
```

The simulation report lists each object's initial and final position, so you can confirm the cube
fell. See [Command-line control](/docs/agents/cli/) and [Play-testing with
simulation](/docs/agents/simulation/).
