Cauldron2D.Drafter.Client (Cauldron2D.Drafter v0.1.3)

Copy Markdown View Source

The drafter application that puts a Cauldron2D.World in front of one player.

Runs a game's client module — one implementing Cauldron2D.Client.Game — through its screens: a title, a lobby listing the arenas, settings, the arena itself, and a summary when the game's outcome/1 says play is over for this player. It holds the player's input, their audio, and their connection to the world.

An arena whose world is {module, opts} is this player's alone: the client starts a Cauldron2D.World for it when the player joins and stops it when they leave, and p pauses and resumes it. A game whose lobby?/0 is false goes from the title straight into its first arena, and back to the title from it.

Drafter.Server.start_ssh(Cauldron2D.Drafter.Client,
  auth: {:accounts, accounts},
  tunnel: true,
  mount_props: %{game: MyGame.Client, accounts: accounts}
)

Mount props

  • :game — the client module. Required
  • :username — the player's name, set by the ssh transport. Default "player"
  • :sink — a TuningFork.Sink module or {module, opts} this player's audio plays through. Default: the game's sink/1 given all the mount props, else TuningFork.Sink.Speaker when that package is present, else silence
  • :settings — the map Cauldron2D.Drafter.Client.Settings.to_props/1 produced, from the account props; a settings file for the player overrides it. Default: the game's first preset
  • :accounts — the Drafter.Accounts server settings are saved to. Default: none
  • :kind — the kind of client this is, the key its settings are kept under (see Cauldron2D.Drafter.Client.Settings). Default :terminal
  • :start — the first screen, :title or :lobby. Started at the lobby, the client has no title of its own: going back from the lobby (Esc or q) stops it, as quitting from the title does. Default :title

Every other mount prop is the game's, read by its sink/1, pages/1 and arenas/1.

Embedding

A game with screens of its own — its own title, a menu, pages that take input — runs its own Drafter.App and drives this one from it: it keeps the client's state from mount/1 (with start: :lobby), and hands it its events, messages and timers through handle_event/2, handle_event/3, on_message/2 and on_ready/1, draws render/1, and calls unmount/1 when done. A {:stop, reason} from the client is its wish to end: the game takes its screens back. The game's use Drafter.App needs the same options this module's has — key_release: true, cell_size: true, frame_pacing: :always — and its refresh_rate/0 should be refresh_rate/0 here.

Tracing

With CAULDRON_TRACE set (see Cauldron2D.Trace), the client writes every key and mouse event it steers with (key, mouse), every input it sends the world (input, with the actions held and the aim in tiles) and every frame the world sends back (frame, with its tick), so mix cauldron.report --from mouse --to frame measures the way round.

Keys

The client's own keys are default_keys/0, each replaceable or dropped by the game's client_keys/0; what follows describes the defaults. In the arena t opens a line to talk to everyone in it — Enter sends, Esc cancels, and no key steers while it is open. Esc goes back: settings to where it was opened from, arena to lobby, lobby to title, title out of the program. q quits the arena for the lobby too, and goes to the title from the lobby. ^Q and ^C quit from anywhere. ? shows the arena's key hints and hides them again; held, it shows them until released. The fps key, bound only when the game binds it, shows under the arena how many frames a second the world sends and hides it again. = (or +) and - zoom the arena in and out through the levels Cauldron2D.Drafter.Surface.zoom_levels/2 gives for the display in use, the wheel too (one step for the events a notch sends within 150 ms), and 0 puts the zoom back; the zoom shows under the world while it is not native. Watching (joined with w), the arrows and a drag with the left button pan the view, the wheel zooms about the pointer, and 0 recentres; flying, the view stays on the ship and the wheel zooms about it. A page the game adds (pages/1) opens from the title on its key; Esc or q closes it.

Title: Enter plays, s opens settings, h the guide, q quits. Lobby: / pick an arena, t a team where the arena has them, Enter joins, w watches, s opens settings, c chats and Enter on an empty line leaves the chat. Settings: / move over the items — preset, each action's binding, pointer steering, effects level, music level, display (pixels where the terminal has them, braille, or glyphs), frame rate (auto picks the terminal's best) — / change the item under the cursor, Enter on a binding then a key or a mouse button adds it to the binding, Backspace removes the binding's last key, Esc during a rebind cancels it. Arena: the game's bindings; Tab opens settings without leaving the ship; the pointer steers only when pointer steering is on, and a key bound to one of the game's steering/0 actions takes over from it until the pointer moves again.

Summary

Functions

The game's arenas, from its arenas/1 given the mount props.

The client's keys by action — a key, or a list of keys — before the game's client_keys/0 is applied.

The point the arena is drawn around: the scene's focus moved by the pan.

The state with its pan dropped when the scene's :subject is not the one the pan was taken on; a scene with no subject keeps the pan.

Callback implementation for Drafter.App.on_timer/2.

Whether the player's own world is paused.

The zoom levels this client steps through: Cauldron2D.Drafter.Surface.zoom_levels/2 for the game's atlas and the display in use.

Functions

arenas(state)

@spec arenas(map()) :: [Cauldron2D.Client.Game.arena()]

The game's arenas, from its arenas/1 given the mount props.

default_keys()

@spec default_keys() :: %{required(atom()) => atom() | [atom()]}

The client's keys by action — a key, or a list of keys — before the game's client_keys/0 is applied.

focus(arg1, arg2)

@spec focus(map(), Cauldron2D.Client.Game.scene()) :: {number(), number()}

The point the arena is drawn around: the scene's focus moved by the pan.

follow(state, arg2)

@spec follow(map(), Cauldron2D.Client.Game.scene()) :: map()

The state with its pan dropped when the scene's :subject is not the one the pan was taken on; a scene with no subject keeps the pan.

keybindings()

on_timer(timer_id, state)

Callback implementation for Drafter.App.on_timer/2.

paused?(map)

@spec paused?(map()) :: boolean()

Whether the player's own world is paused.

zoom_levels(map)

@spec zoom_levels(map()) :: [number()]

The zoom levels this client steps through: Cauldron2D.Drafter.Surface.zoom_levels/2 for the game's atlas and the display in use.