Composes a view of the world on a square grid seen from above and in front: floors as squares, standing arts as a front face with their top above it, movers upright.
Cauldron2D.Projection.Oblique.compose(:my_game,
focus: {12.5, 8.5},
cell: &MyGame.cell/1,
size: {320, 200},
movers: [{:hero, {12.5, 8.5}, heading}]
)A tile of t pixels is drawn t wide and t * squash tall, and each storey raises
what stands on it by t * rise pixels, so a wall shows rise of its side and the
ground behind it is covered. Rows are painted back to front.
At the default single facing +x runs right and +y runs down and towards the viewer.
At four facings the view turns in quarters, which leaves the grid square on the screen,
so nothing is resampled; a mover's pose is read from where it heads on the screen rather
than in the world.
Options
:focus—{x, y}in tiles, the world point at the picture's centre, required:cell—fn {x, y} -> cell end, asCauldron2D.Surfacetakes cells, required:size—{width, height}of the picture in pixels, required:squash— a row's height as a fraction of the tile,0.25..1.0. Default0.5:facings—1or4, how many steps make a full turn. Default1, which is fixed and ignores:facing:facing— which quarter the view is turned to,0to3, counted the way+xturns towards-y. Whole numbers only. Default0:rise— a storey's height as a fraction of the tile,0.25..2.0. Default0.75:movers—[{art, {x, y}}]or[{art, {x, y}, heading}]in tiles,headingin radians with0along+x. A mover shows its:frontpose when heading towards the viewer and:backwhen away, mirrored when heading left; with no heading it faces the viewer. Default[]:labels—[{text, {x, y}, colour}]or with a fourth element of options asCauldron2D.Surface.compose/4takes them, positioned by the tile. Default[]:volumes— coloured regions of space, asCauldron2D.Projection.Volumedescribes them, each tinting the rows behind it. Default[]:at— the time in milliseconds an animated art's frame is chosen for. Default0
project/2, unproject/2 and tile_at/2 map between picture pixels and world tiles
for the same options; they answer for the ground, ignoring what stands on it.
Summary
Functions
The cells this picture shows, each as {position, tile} with the tile the :cell
function gave for it.
The picture, as the module documentation describes.
The ground as a straight walk across the picture: {origin, across, down}, the world
point at the top-left pixel and the world it moves one pixel right and one pixel down.
Where world point {x, y} lands in the picture, in pixels from its top-left corner.
The tile under picture pixel {px, py}.
The world point under picture pixel {px, py}, on the ground.
Types
@type option() :: {:focus, {number(), number()}} | {:cell, ({integer(), integer()} -> Cauldron2D.Surface.cell())} | {:size, {pos_integer(), pos_integer()}} | {:squash, number()} | {:facing, integer()} | {:facings, 1 | 4} | {:rise, number()} | {:movers, [tuple()]} | {:labels, [tuple()]} | {:volumes, [map()]} | {:at, integer()}
Functions
@spec cells(Cauldron2D.Atlas.name() | Cauldron2D.Atlas.t(), [option()]) :: [ {{integer(), integer()}, term()} ]
The cells this picture shows, each as {position, tile} with the tile the :cell
function gave for it.
Cells the function answered :void for are left out.
@spec compose(Cauldron2D.Atlas.name() | Cauldron2D.Atlas.t(), [option()]) :: FrenchCurve.Raster.t()
The picture, as the module documentation describes.
@spec ground_map(Cauldron2D.Atlas.name() | Cauldron2D.Atlas.t(), [option()]) :: {{float(), float()}, {float(), float()}, {float(), float()}}
The ground as a straight walk across the picture: {origin, across, down}, the world
point at the top-left pixel and the world it moves one pixel right and one pixel down.
The ground map is exact, so origin + px * across + py * down is the world point
unproject/3 answers for {px, py}. A caller drawing a grid can take the map once and
add.
@spec project(Cauldron2D.Atlas.name() | Cauldron2D.Atlas.t(), {number(), number()}, [ option() ]) :: {float(), float()}
Where world point {x, y} lands in the picture, in pixels from its top-left corner.
@spec tile_at(Cauldron2D.Atlas.name() | Cauldron2D.Atlas.t(), {number(), number()}, [ option() ]) :: {integer(), integer()}
The tile under picture pixel {px, py}.
@spec unproject( Cauldron2D.Atlas.name() | Cauldron2D.Atlas.t(), {number(), number()}, [option()] ) :: {float(), float()}
The world point under picture pixel {px, py}, on the ground.