# `Cauldron2D.Particles`
[🔗](https://github.com/jaman/cauldron/blob/v0.1.3/cauldron_2d/lib/cauldron_2d/particles.ex#L1)

Short-lived sprites — sparks, debris, smoke — with a cap on how many exist at once.

    particles =
      Cauldron2D.Particles.new(300)
      |> Cauldron2D.Particles.spawn([%{art: :spark, pos: {x, y}, vel: {vx, vy}, ttl: 0.4}])
      |> Cauldron2D.Particles.step(dt, fields: gravity, drag: 0.5)

    Cauldron2D.Particles.movers(particles, {-0.5, -0.5})

A particle is `%{art: art, pos: {x, y}, vel: {vx, vy}, ttl: seconds}`. When spawning
would exceed the cap, the oldest particles go first.

# `particle`

```elixir
@type particle() :: %{
  art: term(),
  pos: Cauldron2D.Body.point(),
  vel: Cauldron2D.Body.point(),
  ttl: number()
}
```

# `t`

```elixir
@type t() :: %Cauldron2D.Particles{cap: pos_integer(), items: [particle()]}
```

# `count`

```elixir
@spec count(t()) :: non_neg_integer()
```

How many particles are alive.

# `movers`

```elixir
@spec movers(t(), Cauldron2D.Body.point()) :: [{term(), Cauldron2D.Body.point()}]
```

The particles as `{art, {x, y}}` movers, oldest first, each position shifted by `offset`.

The offset is what turns a particle's centre into the top-left corner a sprite is drawn
from; `{-0.5, -0.5}` centres a one-tile sprite.

# `new`

```elixir
@spec new(pos_integer()) :: t()
```

An empty set holding at most `cap` particles.

# `spawn`

```elixir
@spec spawn(t(), [particle()]) :: t()
```

Add `particles`, dropping the oldest when the cap is exceeded.

# `step`

```elixir
@spec step(t(), number(), keyword()) :: t()
```

Move every particle for `dt` seconds and drop those whose time is up.

## Options

  * `:fields` — gravity fields as `Cauldron2D.Body.gravitate/3` takes. Default `[]`
  * `:drag` — a coefficient as `Cauldron2D.Body.drag/3` takes. Default `0`

---

*Consult [api-reference.md](api-reference.md) for complete listing*
