# `Cauldron2D.Net.Frame`
[🔗](https://github.com/jaman/cauldron/blob/v0.1.3/cauldron_2d_net/lib/cauldron_2d/net/frame.ex#L1)

What goes over the wire to a browser: the static map once, and a frame per tick, with
arts as sheet indices.

    Cauldron2D.Net.Frame.map(%{width: w, height: h, cell: fun}, sheet)
    Cauldron2D.Net.Frame.frame(%{focus: {x, y}, movers: [{art, {x, y}}], labels: [{"alice", {x, y}, {255, 255, 0}}]}, hud_rows, outcome, sheet)

`sheet` is what `Cauldron2D.Net.Sheet.build/1` returned, or any map with `:arts` and
`:tile`. A mover whose art the sheet lacks is left out. Hud rows are as
`Cauldron2D.Client.Hud` describes them and go out as `[text, "#rrggbb" | nil]` runs;
a row's tag goes in `tags` at the same position (`nil` for a row without one) —
`tags` is there only when some row has a tag. Labels go out as
`[text, x, y, "#rrggbb", scale]`.

# `row`

```elixir
@type row() :: Cauldron2D.Client.Hud.row()
```

# `sheet`

```elixir
@type sheet() :: %{arts: %{required(atom()) =&gt; pos_integer()}, tile: pos_integer()}
```

# `frame`

```elixir
@spec frame(
  %{
    :focus =&gt; {number(), number()},
    :movers =&gt; [{atom(), {number(), number()}}],
    optional(:labels) =&gt; list(),
    optional(:subject) =&gt; term()
  },
  [row()],
  map() | nil,
  sheet()
) :: map()
```

One tick: the focus, the movers, the labels, the hud rows (with their tags when any row has one), the subject when the scene names one, and the outcome when the round is over for this player.

# `map`

```elixir
@spec map(
  %{
    :width =&gt; pos_integer(),
    :height =&gt; pos_integer(),
    :cell =&gt; ({integer(), integer()} -&gt; atom() | nil),
    optional(:wrap?) =&gt; boolean()
  },
  sheet()
) :: map()
```

The static layer: `width` by `height` rows of art indices, 0 where `cell` returns `nil`, and whether the world wraps at its edges (`:wrap?`, default false).

---

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