Cauldron2D.Projection.Oblique (Cauldron2D v0.2.2)

Copy Markdown View Source

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, as Cauldron2D.Surface takes 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. Default 0.5
  • :facings — 1 or 4, how many steps make a full turn. Default 1, which is fixed and ignores :facing
  • :facing — which quarter the view is turned to, 0 to 3, counted the way +x turns towards -y. Whole numbers only. Default 0
  • :rise — a storey's height as a fraction of the tile, 0.25..2.0. Default 0.75
  • :movers — [{art, {x, y}}] or [{art, {x, y}, heading}] in tiles, heading in radians with 0 along +x. A mover shows its :front pose when heading towards the viewer and :back when 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 as Cauldron2D.Surface.compose/4 takes them, positioned by the tile. Default []
  • :volumes — coloured regions of space, as Cauldron2D.Projection.Volume describes them, each tinting the rows behind it. Default []
  • :at — the time in milliseconds an animated art's frame is chosen for. Default 0

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

option()

@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

cells(atlas, opts)

@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.

compose(atlas, opts)

The picture, as the module documentation describes.

ground_map(atlas, opts)

@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.

project(atlas, point, opts)

@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.

tile_at(atlas, point, opts)

@spec tile_at(Cauldron2D.Atlas.name() | Cauldron2D.Atlas.t(), {number(), number()}, [
  option()
]) ::
  {integer(), integer()}

The tile under picture pixel {px, py}.

unproject(atlas, pixel, opts)

@spec unproject(
  Cauldron2D.Atlas.name() | Cauldron2D.Atlas.t(),
  {number(), number()},
  [option()]
) ::
  {float(), float()}

The world point under picture pixel {px, py}, on the ground.