# `Cauldron2D.Game`
[🔗](https://github.com/jaman/cauldron/blob/v0.2.2/cauldron_2d/lib/cauldron_2d/game.ex#L1)

What a game gives `Cauldron2D.World` to run: a pure value and the callbacks that change it.

    defmodule MyGame do
      @behaviour Cauldron2D.Game

      def init(opts), do: ...
      def join(state, player_id, props), do: {:ok, state}
      def leave(state, player_id), do: state
      def handle_input(state, player_id, %{held: held, aim: aim}), do: state
      def step(state, dt), do: state
      def view(state, player_id), do: ...
      def drain_events(state), do: {events, state}
    end

Every callback is pure. `step/2` is called once per fixed tick with `dt` in seconds;
`handle_input/3` before the tick for each player whose input changed; `view/2` after it
for each player, and what it returns is sent to that player; `drain_events/1` after it,
once, and the events go to every player. Nothing here reads a clock, and a game built
with the same options and given the same calls in the same order runs identically.

`join/3`'s `props` are the game's to define. The clients in the `cauldron_2d_*`
packages pass `:username` (the player's name as a string) and whatever the game's own
`join_props` callback adds; a game that wants teams, spectators or anything else names
those props itself and reads them here.

# `input`

```elixir
@type input() :: %{
  :held =&gt; MapSet.t(atom()),
  :aim =&gt; {number(), number()} | nil,
  optional(:strength) =&gt; %{required(atom()) =&gt; float()},
  optional(:heading) =&gt; float()
}
```

A player's input: `Cauldron2D.Input.state/1`'s map, which a client looking through an
eye adds `:heading` to — where the player looks, in radians with `0` along `+x` — so
a game can walk `:up` along it, `:down` against it and `:left` and `:right` across it.

# `player_id`

```elixir
@type player_id() :: term()
```

# `state`

```elixir
@type state() :: term()
```

# `drain_events`

```elixir
@callback drain_events(state()) :: {[term()], state()}
```

# `handle_input`

```elixir
@callback handle_input(state(), player_id(), input()) :: state()
```

# `init`

```elixir
@callback init(keyword()) :: state()
```

# `join`

```elixir
@callback join(state(), player_id(), map()) :: {:ok, state()} | {:error, term()}
```

# `leave`

```elixir
@callback leave(state(), player_id()) :: state()
```

# `step`

```elixir
@callback step(state(), float()) :: state()
```

# `view`

```elixir
@callback view(state(), player_id()) :: term()
```

---

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