# Motion

> Reference for everything that moves objects: Spin, defineBehavior, Vehicle with VehicleOptions and VehicleState, Pile with its physics options, usePath and Path, useTrip and TripHandle, useTripStatus, TripState and FollowPath.

```ts
import { defineBehavior, FollowPath, Path, Pile, Spin, Trip, usePath, useTrip, useTripStatus, Vehicle } from "@apricot/react";
import type { TripHandle, TripState, TripStatus, VehicleOptions, VehicleState } from "@apricot/react";
```

For shared values, `useFrame` and `useAnimatable`, see [Hooks](https://matthiasbrandolin.dev/apricot/reference/hooks).

## `Spin`

Spins its children.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `speed` | `number` or shared value | `1` | Radians per second |
| `axis` | `Vec3` or shared value | `[0, 1, 0]` | The axis to spin around |
| `children` | `ReactNode` | | |

## `defineBehavior(definition)`

Turns per-frame logic into a component that wraps children (`Spin` is built with it). Returns a component whose props are the keys of `defaults` (each plain or shared) plus `children`.

| Field | Type | Description |
| --- | --- | --- |
| `name` | `string` | Display name and the wrapping group's name |
| `defaults` | `object` | Every prop with its default value |
| `frame` | `(object, props, state) => boolean \| undefined` | Runs before each frame on the wrapping group. `state` is `{ time, delta, frame }`. Return `true` while still moving |

See [Custom geometry and behaviors](https://matthiasbrandolin.dev/apricot/guides/custom#your-own-behavior-definebehavior).

## `Vehicle`

Drives its children like a toy car on the ground plane. Renders only while the car moves or an input is non-zero. Options are **read once, at mount**.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `throttle` | `number` or shared value | `0` | −1 (reverse, brake) to 1 (full throttle) |
| `steer` | `number` or shared value | `0` | −1 (left) to 1 (right) |
| `start` | `{ x?, z?, heading? }` | `{ 0, 0, 0 }` | Start place; `heading` in radians, 0 faces +z |
| `onUpdate` | `(state: VehicleState) => void` | | After each simulated frame, on the JS thread |
| `ref` | `Ref<SceneObject>` | | The moving group (a `<FollowCamera>` target) |
| `children` | `ReactNode` | | The car. Descendants named `wheel_f…` steer and spin; `wheel_r…` spin |
| `maxSpeed` | units/s | `12` | Top speed forwards |
| `maxReverse` | units/s | `4` | Top speed in reverse |
| `acceleration` | units/s² | `9` | At full throttle |
| `braking` | units/s² | `20` | Throttle against the motion |
| `drag` | units/s² | `3` | Coasting |
| `wheelBase` | units | `1.4` | Distance between the axles: shorter turns tighter |
| `maxSteer` | radians | `0.6` | Largest front-wheel angle |
| `steerSpeed` | per second | `8` | How fast the wheels reach the requested angle |
| `wheelRadius` | units | `0.3` | For the wheels' spin |
| `bounds` | `[minX, minZ, maxX, maxZ]` | none | Keeps the car inside this box |

`VehicleState`: `{ x, z, heading, speed, steer, wheelSpin }`. `heading` and `steer` in radians (positive steer is right); `speed` signed, units per second; `wheelSpin` accumulated radians.

## `Pile`

Drops copies of its children from above the visible area; they collide, bounce and heap up. Each kind is one draw call. The scene stops rendering once the pile rests.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `count` | number | required | How many objects in total |
| `duration` | seconds | `5` | Over how long they drop |
| `bounds` | `{ min: Vec3, max: Vec3 }` | the visible area | The box to fill; floor at `min[1]`. Changing it moves the walls without restarting |
| `depth` | units | `0.5` | Half the thickness of the default area |
| `scale` | `[min, max]` | `[0.9, 1.1]` | Random size range, relative to each child |
| `speed` | units/s | `2` | Downward speed on entry |
| `spin` | radians/s | `4` | Largest initial tumble |
| `seed` | number | `1` | Random seed |
| `physics` | `SphereWorldOptions` | see below | Solver settings |
| `onSettled` | `() => void` | | Everything dropped and rests |
| `children` | `ReactNode` | required | Templates: one kind each, meshes only. Their own transforms are ignored. Collision radius: `userData.radius`, else the bounding sphere |

`physics`: `gravity` (`[0, -15, 0]`), `friction` (`0.6`, floor only), `bodyFriction` (`0.15`), `damping` (`0.05`), `contactDamping` (`4`), `restSpeed` (`0.12`), `settleTime` (`0.4` s), `maxSpeed` (`40`), `iterations` (`2`), `maxSubstep` (`1/120` s).

The pile restarts when an option changes (compared by value). Change its `key` to replay.

## Paths

### `usePath(points, options?)`

Returns a `Path`: a smooth curve through `points` (`Vec3[]`). Rebuilt only when the values change.

| Option | Default | Description |
| --- | --- | --- |
| `closed` | `false` | Joins the end back to the start |
| `tension` | `0.5` | 0–1: how tightly the curve hugs the points. 0.5 is smooth with no overshoot |

`new Path(points, options)` builds one outside React.

### `Path`

| Member | Returns | Description |
| --- | --- | --- |
| `length` | number | Total length |
| `pointAt(distance, target?)` | `Vector3` | The point at that distance |
| `tangentAt(distance, target?)` | `Vector3` | Unit direction of travel there |
| `place(object, distance, direction = 1)` | | Moves and turns an object onto the path, +z forward, +y up. −1 faces backwards |
| `every(spacing, start = 0)` | `number[]` | Distances every `spacing` units |
| `distanceTo(point, samples = 400)` | number | The distance along the path closest to a point |
| `clamp(distance)` | number | Wraps around a closed path, clamps to the ends of an open one |

## Trips

### `useTrip(options)`

Runs a vehicle along stops: speeds up, cruises, brakes exactly onto each stop, waits, goes on. Time-based, exact at any frame rate, and it keeps its place while the app sleeps. Works outside `<Scene>`.

| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `stops` | `number[]` | required | Distances of the stops along the path, in order |
| `path` | `Path` | | Gives `"loop"` trips their length |
| `speed` | units/s | `20` | Top speed |
| `acceleration` | units/s² | `1.2` | |
| `deceleration` | units/s² | the acceleration | |
| `dwell` | seconds | `8` | Wait at each stop |
| `pattern` | `"shuttle" \| "loop" \| "once"` | `"shuttle"` | After the last stop: run back, go on round to the first, or stay |
| `start` | seconds | `0` | Seconds into the trip at mount. 0 is waiting at the first stop |
| `clock` | `() => number` | device clock | Seconds now. Pass a server clock to sync devices |
| `onArrive`, `onDepart` | `(stop: number) => void` | | With the stop's index |

Returns a `TripHandle`: `{ trip, elapsed(), state() }`. `new Trip(options)` (with `length` for loops) gives the timeline outside React: `trip.at(seconds)` returns a `TripState`.

### `TripState`

| Field | Description |
| --- | --- |
| `distance` | Along the path |
| `speed` | Units per second (0 at a stop) |
| `direction` | `1` forward along the path, `-1` back |
| `stopped` | Waiting at a stop |
| `stop` | Index of the stop it is at, or last left |
| `nextStop` | Index of the stop it is heading for |
| `eta` | Seconds until the next stop (moving) or until it leaves (stopped) |

### `useTripStatus(trip, every = 1)`

Returns a `TripStatus`: `TripState` plus `seconds` (`eta` rounded up), refreshed every `every` seconds by a timer. It re-renders its component every second: use it in a small component of its own.

### `FollowPath`

Puts its children on a path, facing along it (+z forward).

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `path` | `Path` | required | |
| `distance` | `number` or shared value | `0` | Distance along the path |
| `trip` | `TripHandle` | | Or ride a trip: distance and direction come from it |
| `offset` | units | `0` | Ahead (+) or behind (−) of that distance: one per car of a train |
| `orient` | boolean | `true` | Face along the path; `false` keeps the children's rotation |
| `ref` | `Ref<SceneObject>` | | The moving group |
| `children` | `ReactNode` | | |

## Related

- [Animation and shared values](https://matthiasbrandolin.dev/apricot/concepts/animation).
- [Vehicles](https://matthiasbrandolin.dev/apricot/guides/vehicles), [Falling objects](https://matthiasbrandolin.dev/apricot/guides/falling-objects), [Paths, trips and labels](https://matthiasbrandolin.dev/apricot/guides/paths-and-labels).
