# Movement pack — Model A character controller

Default embodiment layer. AI builds controllable agents through this pack, not buried `this.speed` constants.

```
Physics pack  →  solids, gravity, colliders
Movement pack →  start/stop/turn/jump/land against those solids
```

## Construction

```js
const physics = await ensurePhysicsWorld({ thing, worldTune, rapierUrl });
const movement = createMovementPack({ thing, physics });

const moveTune = thing('movement.player', {
  maxSpeed: 6,
  accel: 40,
  decel: 50,
  airControl: 0.4,
  jumpForce: 8,
  fallMultiplier: 1.6,
  coyoteTime: 0.1,
  jumpBuffer: 0.1,
  height: 1.8,
  radius: 0.35,
  stepHeight: 0.35,
  maxSlope: 50
});

movement.createCharacter('player', {
  mesh: playerMesh,
  position: { x: 0, y: 0, z: 0 },
  tune: moveTune
});
bind('movement.player', playerMesh);

// loop
movement.setInput('player', { x: strafe, z: forward, jump: jumpHeld });
movement.step(dt); // fixed 1/60; also steps physics world once per substep
```

## One owner

- **Physics** owns world solids and dynamic props.
- **Movement** owns character kinematic pose (controller result → mesh).
- Game code must **not** also write `player.position` every frame.

## Live vs careful

| Params | Apply |
|---|---|
| maxSpeed, accel, decel, airControl, jumpForce, fallMultiplier, coyote, buffer | **Live** |
| stepHeight, maxSlope | **Live** on controller |
| height, radius | **Rebuild capsule** at feet (honest re-place; may pop slightly) |

## Do not

- Dynamic rigid-body player as V1 default (Model B later)
- Store velocity in Keep — only the inputs above
- Skip physics pack and raycast homemade floors only

## Proof

`substrate/gen/movement-proof/`

```bash
# Serve the substrate tree so physics/ + movement/ packs resolve (not only gen/movement-proof).
node adapters/serve/serve.mjs substrate --port 5423 --shell
# open http://127.0.0.1:5423/gen/movement-proof/
node bridge/bridge-server.js
```
