Resolves which part of a world is on screen.
Cauldron2D.Camera.view(
focus: {x, y},
size: {columns, rows},
cell: fn {x, y} -> cell end
):cell is called exactly once per visible tile, with that tile's world coordinate, and
returns a Cauldron2D.Surface.cell/0. It is the only thing the engine asks of a game.
The viewport is always centred on :focus: at a world's edge, or zoomed out past it, the
coordinates asked for run outside the world and :cell answers for them (:void, or a
wrapped tile) — the focus never moves off the centre to keep the world on screen.
A tile occupies two terminal cells across and one down. columns_for/1 and rows_for/1
convert a pane's size in cells into a viewport size in tiles; zoomed/2 scales that
size for a zoom — how many times larger than native a tile is drawn — and tile_at/3
and zoom_about/6 map cells back through it. A :size may be fractional: the origin
centres the focus exactly, and the tiles read cover the fraction.
Summary
Functions
How many tiles wide a pane width terminal cells across can show; always at least 1.
Where a viewport size tiles across sits in world coordinates when focus is at its
exact centre, as floats.
The view as glyphs and colours, for renderers that draw characters.
Where a viewport size tiles across sits in world coordinates when centred on focus.
How many tiles tall a pane height terminal cells high can show; always at least 1.
The world tile under {column, row}, given in terminal cells relative to the pane's
top-left corner, for a viewport whose origin is the first argument.
tile_at/2 through a zoom: a tile drawn zoom times its native size spans 2 * zoom cells across and zoom down.
Resolve the viewport and read every tile in it.
The focus that keeps the world under cell where it is on screen when a pane of native
size goes from from to to zoom, centred on focus before. Zooming back the same
way about the same cell returns to the focus it started from.
The viewport in tiles of a pane size tiles across at native size, drawn at zoom.
Types
@type t() :: %Cauldron2D.Camera{ cells: [[Cauldron2D.Surface.cell()]], columns: pos_integer(), origin: point(), rows: pos_integer(), scroll: {float(), float()} }
Functions
@spec columns_for(non_neg_integer()) :: pos_integer()
How many tiles wide a pane width terminal cells across can show; always at least 1.
Where a viewport size tiles across sits in world coordinates when focus is at its
exact centre, as floats.
@spec glyphs(Cauldron2D.Atlas.name() | Cauldron2D.Atlas.t(), t()) :: [ [{String.t(), Cauldron2D.Atlas.rgb()}] ]
The view as glyphs and colours, for renderers that draw characters.
Each cell becomes {glyph, {r, g, b}} with the tint already applied, in the same row and
column order as :cells. A cell with overlays takes the glyph and colour of its topmost
overlay; :void becomes two spaces in the atlas's void colour.
@spec origin(point(), {pos_integer(), pos_integer()}) :: point()
Where a viewport size tiles across sits in world coordinates when centred on focus.
This is the :origin view/1 produces for the same arguments, so a caller mapping a screen
position back to the world resolves against the same tiles that were drawn.
A fractional focus is rounded to the nearest tile first.
@spec rows_for(non_neg_integer()) :: pos_integer()
How many tiles tall a pane height terminal cells high can show; always at least 1.
The world tile under {column, row}, given in terminal cells relative to the pane's
top-left corner, for a viewport whose origin is the first argument.
The result is fractional and resolves to the centre of the cell, so trunc/1 on either
coordinate gives the whole tile the cell belongs to. The column is halved, since a tile is
two cells wide: cells 0 and 1 both fall in tile 0, at 0.25 and 0.75.
Pair with origin/3 to map a pointer position back to the world it is over.
tile_at/2 through a zoom: a tile drawn zoom times its native size spans 2 * zoom cells across and zoom down.
Resolve the viewport and read every tile in it.
Returns a t/0 whose :cells is a list of rows rows, each of columns cells, in
top-to-bottom and left-to-right order, and whose :origin is the world coordinate of the
top-left tile.
Options
:focus— the{x, y}world point to centre on, required:size—{columns, rows}in tiles, required, both positive, whole or not:cell—fn {x, y} -> cell end, required:scroll—trueto keep the focus at the exact centre::originis then the exact origin rounded down,:cellsholds one more column and one more row than:size, and:scrollis the fraction of a tile,{0.0..1.0, 0.0..1.0}, the cells are to be shifted left and up by. Defaultfalse::originisorigin/3,:cellsis exactly:size,:scrollis{0.0, 0.0}
@spec zoom_about( {number(), number()}, {number(), number()}, {number(), number()}, number(), number() ) :: {float(), float()}
The focus that keeps the world under cell where it is on screen when a pane of native
size goes from from to to zoom, centred on focus before. Zooming back the same
way about the same cell returns to the focus it started from.
The viewport in tiles of a pane size tiles across at native size, drawn at zoom.