Cauldron2D.Net.Session (Cauldron2D.Net v0.1.2)

Copy Markdown View Source

A browser player's life in a world, as functions over a struct, for a channel process to drive: the process calling join/4 becomes the world's player and gets its frames and its audio's PCM as messages.

{:ok, session, pushes} = Session.join(MyGame.Client, world, "alice", %{settings: %{sfx: 0.8, music: 0.3}})
{session, pushes} = Session.frame(session, frame_message)
session = Session.input(session, ["left", "act"], [10.5, 4.0], %{"act" => 0.5})

Every function that has something for the browser returns pushes, {event, payload} pairs in the order to send them; a payload that is a binary is a "pcm" chunk.

What a session's sound costs the server is Cauldron2D.Net.Audio's policy: its own stage for effects and music, a stage for effects with the world's shared music (Cauldron2D.Net.Audio.Shared) mixed under them, or none. The chunks reach the calling process as {:pcm, chunk} from its own stage and {:cauldron_shared_pcm, chunk} from the shared one; pcm/2 and shared_pcm/2 turn them into pushes, and rerate/2 answers {:cauldron_audio_rate, rate} from the policy.

Summary

Functions

A {:cauldron_atlas, name, :changed} for the game's atlas: the new sheet, and the map goes again with the next frame.

A {:cauldron_frame, message} from the world: the map first if not yet sent, then the frame; events and cues reach the audio.

What the browser holds and aims at, and how hard it holds what an analog control holds (strength, action name to 0.0–1.0); actions the game does not know, and strengths for actions not held or out of range, are dropped.

Join world as name from the calling process; game implements Cauldron2D.Client.Game. A world of {module, opts} is this player's alone, started here and stopped by leave/1.

Leave the world and stop the audio.

Set the effects and music levels, 0.0 to 1.0; shared music is scaled by the session's music level as it is mixed.

Switch the music off, or back on at the session's music level, leaving the effects alone; the switch outlives a change of levels.

A chunk from the session's own stage, {:pcm, chunk}: the push, with the world's shared music under it when the music is shared.

The policy's rate changed, {:cauldron_audio_rate, rate}: the session's audio starts again at the new rate, and the browser is told the format.

A chunk of the world's shared music, {:cauldron_shared_pcm, chunk}: pushed as it is when the session has no stage of its own, else kept for the next chunk of its own to go under.

Pause or resume the player's own world; nothing for a shared one.

Types

push()

@type push() :: {String.t(), map() | binary()}

t()

@type t() :: %Cauldron2D.Net.Session{
  actions: %{required(String.t()) => atom()},
  audio: pid() | nil,
  cue: term(),
  format: Cauldron2D.Net.Audio.format(),
  game: module(),
  levels: %{sfx: float(), music: float()},
  local_world: pid() | nil,
  map_sent?: boolean(),
  music: :own | :static | :shared | :off,
  music_on?: boolean(),
  name: String.t(),
  queued: :queue.queue(binary()),
  shared: pid() | nil,
  sheet: Cauldron2D.Net.Sheet.t(),
  sheet_url: String.t(),
  world: GenServer.server()
}

Functions

atlas_changed(session)

@spec atlas_changed(t()) :: {t(), [push()]}

A {:cauldron_atlas, name, :changed} for the game's atlas: the new sheet, and the map goes again with the next frame.

frame(session, map)

@spec frame(t(), %{view: term(), events: list()}) :: {t(), [push()]}

A {:cauldron_frame, message} from the world: the map first if not yet sent, then the frame; events and cues reach the audio.

input(session, held, aim, strength \\ %{})

@spec input(t(), [String.t()], [number()] | nil, %{required(String.t()) => number()}) ::
  t()

What the browser holds and aims at, and how hard it holds what an analog control holds (strength, action name to 0.0–1.0); actions the game does not know, and strengths for actions not held or out of range, are dropped.

join(game, world, name, props, opts \\ [])

@spec join(module(), GenServer.server(), String.t(), map(), keyword()) ::
  {:ok, t(), [push()]} | {:error, term()}

Join world as name from the calling process; game implements Cauldron2D.Client.Game. A world of {module, opts} is this player's alone, started here and stopped by leave/1.

props carries :settings (:sfx and :music levels, default Cauldron2D.Audio.default_levels/0) and anything the game's join_props/1 adds. Options: :sheet_url, where the game serves the sheet PNG (default "/atlas.png"); :sink, a sink for the audio instead of TuningFork.Sink.Process to this process; :audio, the PCM format asked for as %{rate: hertz, channels: 1 | 2} (default 44 100 Hz stereo — 22 050 Hz mono is a quarter of the bytes) or :off for no sound; :policy, a sound policy instead of Cauldron2D.Net.Audio.policy/0. The pushes are the sheet, then "audio" with the format the PCM comes in, or %{off: true} when none will. The process is subscribed to the game's atlas; atlas_changed/1 answers the message.

leave(session)

@spec leave(t()) :: :ok

Leave the world and stop the audio.

levels(session, sfx, music)

@spec levels(t(), number(), number()) :: t()

Set the effects and music levels, 0.0 to 1.0; shared music is scaled by the session's music level as it is mixed.

music(session, on?)

@spec music(t(), boolean()) :: t()

Switch the music off, or back on at the session's music level, leaving the effects alone; the switch outlives a change of levels.

pcm(session, chunk)

@spec pcm(t(), binary()) :: {t(), [push()]}

A chunk from the session's own stage, {:pcm, chunk}: the push, with the world's shared music under it when the music is shared.

rerate(session, rate)

@spec rerate(t(), pos_integer()) :: {t(), [push()]}

The policy's rate changed, {:cauldron_audio_rate, rate}: the session's audio starts again at the new rate, and the browser is told the format.

shared_pcm(session, chunk)

@spec shared_pcm(t(), binary()) :: {t(), [push()]}

A chunk of the world's shared music, {:cauldron_shared_pcm, chunk}: pushed as it is when the session has no stage of its own, else kept for the next chunk of its own to go under.

toggle_pause(session)

@spec toggle_pause(t()) :: t()

Pause or resume the player's own world; nothing for a shared one.