Skip to content

Tutorials · Worlds and Levels · Chapter 14

A gallery of worlds

90 minutes Uses: TileMap, SortingGroup, Shape, WorldText, Spawner, SpriteMask, Sprite, pressed, vec2, cell_at, node, position, tile_at, move_to, cell_centre, tile_number, tile_text, set_text, set_tile, spawn, wait, text, floor, random, anneal_point, anneal_colour, vec4, destroy_self, held, translate

By the end

  • An isometric room of diamond flagstones, its tall pillars drawn rightly over each other and the wanderer walking behind them and in front, with its Collision off
  • A staggered map of the same tiles, numbered by the rows of the screen
  • Two boards of hexes, pointy-topped and flat-topped, whose tiles carry a cost and a name, and a token on each that steps from hex to hex and turns each it enters to trodden earth
  • A dungeon cut from Tiny Dungeon’s sheet with its gutters, its sand floor drawn as the brown one, figures that never slice through each other, and outlined pots among them
  • A damage counter: a number every 0.6 seconds over a practice dummy, rising and fading
  • A far ridge on a Parallax plane that collides with nothing, and a spyglass that shows it through a round lens in a dark shade
On this page

Four scenes, seven cases

No grey block stands in for anything here: the vale and the crypt are as chapter 13 left them, and the game still plays from the hut to the bell. This chapter makes four scenes beside them, none of them a level, each a small case the vale and the crypt have no place for: an isometric room and a staggered map, two boards of hexes, a dungeon with a damage counter in it, and a far ridge seen through a spyglass.

Every map so far has laid its cells out in rows and columns of squares. A map’s Grid lays them out four other ways, each for its own kind of game:

GridIts cellsReach for it for
Rectanglesquares in rows and columnsa side view, as the vale and the crypt, or a room seen from straight above, as the dungeon
Isometricdiamonds, numbered along the diamond’s two sidesa room seen from above at an angle
IsometricStaggeredthe same diamonds, numbered by the rows of the screena long isometric strip whose rows run across the screen
HexPointyTop, HexFlatTophexagons, every other row or column half a cell ona board where each neighbour is as far as every other

Open a scene by double-clicking it in Assets. F5 plays the scene that is open; Run game still starts the vale, the project’s startup scene. The arrows, or W, A, S and D, float the wanderer and the knight, step the hex tokens, and pan the lookout.

Every gallery scene starts the same way: a root, and a camera of its own that frames a view 320 by 180, x -160 to 160 and y -90 to 90, and stands still, all but the lookout’s, which pans. The galleries are unlit: none has an Ambient Light, so everything draws at its own colours.

  1. With scenes/vale.ron or scenes/crypt.ron open, press Ctrl+S. Choose File → New scene: an empty scene takes its place, without asking.
  2. Press + Add node and choose Node. Rename it gallery-iso. Choose File → Save as…, open the scenes folder, name the file gallery-iso.ron, and save.
  3. Select gallery-iso, press + Add node and choose Camera: the menu opens on Add child of gallery-iso. Rename it camera, and leave its Position at 0, 0.
  4. In its Camera, set Scaling to Letterbox, type Extent 180 and Width 320, and type Background as the table below gives it. Leave Pixel Snap ticked.
  5. Press Add component and choose PixelPerfectComponent. Leave Assets PPU 1, Reference Width 320 and Reference Height 180 as they come, and tick Upscale Render Texture and Crop Frame. Press Ctrl+S.
Background
Each gallery’s camera, the vale’s0.10, 0.12, 0.20, alpha 1

A colour is typed in linear light, so those dark-looking numbers show on the screen as a lighter slate blue, behind every case. The other three scenes, gallery-hex, gallery-dungeon and gallery-lookout, start the same way, each saved in scenes under its root’s name; each case below says when.

An isometric room

A room of diamond flagstones seen from above at an angle, with four tall pillars standing in it and the wanderer, the pilgrim’s figure, floating where the keys send him. Behind a pillar, the pillar draws over him; in front of it, he draws over the pillar.

What collides, what draws, what sorts: the map draws its floor and its pillars on Figures, the wanderer’s Sort Layer, and nothing in the room collides, its Collision off. Everything under room sorts by Y, each pillar by its cell’s foot and the wanderer by his feet, and the floor, on the same Sort Layer at a z lower, draws under all of it.

  1. With scenes/gallery-iso.ron open, select gallery-iso, press + Add node and choose Node: the menu opens on Add child of gallery-iso. Rename it room, and type its Position -84, -40.
  2. In its Node’s Advanced fold, tick Sort children by Y.
  3. Select room, press + Add node and choose Tilemap: the menu opens on Add child of room. Rename it iso-floor, and leave its Position at 0, 0.
  4. In its TileMapComponent, type Tile Size 32, 16, set Grid to Isometric and Sort Layer to Figures, and untick Collision.
Sort children by Y
A node’s own row, in its Advanced fold: its children draw in the order of their place down the screen, the one nearer the bottom in front. A picture sorts by its node’s place, a Sprite anchored at its foot by its feet; a tile that sorts by Y, by its cell’s foot. Only children on one Sort Layer at one order pass in front of each other: Sort Layer is compared first, then a tile layer’s z, then Y.
The TileMap’s Tile Size, 32 by 16
One cell in world units. An isometric diamond is twice as wide as it is tall, so a cell’s box is 32 by 16, the diamond filling it corner to corner.
The TileMap’s Grid: Isometric
Diamond cells, numbered along the diamond’s two sides: a cell one along in x is half a cell right and half a cell down the screen, one along in y half a cell left and half a cell down. Cell x, y has its box’s corner at x 16(x − y), y 8(x + y), so cell 0, 0 is the room’s top corner and a row of the map runs down to the right.
The TileMap’s Collision, unticked
A map’s tiles collide as their cells’ boxes, and a diamond’s box is the rectangle round it, whose corners reach over the four diamonds beside it: a pillar would stop him at its box’s edge, short of its shaft. So the room collides with nothing, and he floats through a pillar.
  1. Click the Tilemap tab and drop art/iso.png on New tilemap…: the editor writes art/iso.tilemap and points iso-floor at it. The picture, 128 by 16, came with the starter: four cells of 32 by 16, a flagstone, the same worn, a pillar’s foot and its head.
  2. In the Tileset band, type Tile 32 and 16, and Columns 4.
  3. In the Layers band, double-click back and rename it floor, and type its z -1. Rename ground pillars: it stays Solid with Blocks nav, at z 0, as New tilemap made it.
  4. Click pillars’ row and press +: an empty layer goes in over it and lights. Rename it heads, and leave it as a new layer comes: not Solid, z 0.

A pillar is drawn 32 high and cut in two: its foot is tile #3, its head #4. Both are painted in the same cell, and the head is told to draw a cell up, onto the foot; both sort by that cell’s foot, so he is behind or in front of the whole pillar, never between its halves.

  1. Click tile #3 in the picker. In the Tile band under it, type Y sort 1.
  2. Click tile #4. Type Art origin’s y -1, and Y sort 1.
The Tilemap tab below its Tileset band: Tile #3, Zoom 2.0, and the picker’s four tiles, the flagstone, the worn flagstone, a pillar’s foot outlined and a pillar’s head; the Tile 3 band, its preview the pillar’s foot, Cell 3 of 4, Tint white, Art origin x 0.00 y 0.00, Z offset 0, Y sort 1.00, Weight 1.00; Animation still and Add frame; Data, no values, and Add value; Scene (none) — drop a scene or artifact; Draws as #3
The foot, #3: Y sort 1.
The same band with tile #4 held, the pillar’s head outlined in the picker: Cell 4 of 4, Art origin x 0.00 y -1.00, Y sort 1.00, Weight 1.00; Draws as #4
The head, #4: drawn a cell up, Art origin y -1, and sorted at the foot of the cell it is painted in.
A tile’s Y sort
Where the tile counts as being for sorting by Y, in cells below the top of its own cell: 0, the top, as every tile comes, to 1, its foot. It matters only under a parent that sorts its children by Y. The foot and the head both sort at 1, the cell’s foot, the line where the pillar meets the floor.
A tile’s Art origin, a cell up
Chapter 4’s, at y -1: the head is painted in its foot’s cell and drawn a whole cell higher, standing on the foot. It still sorts by the cell it is painted in, so foot and head sort as one.
  1. Click floor’s row and tile #1. With Rect, drag from cell 0, 0 to 4, 4: 25 diamonds, the room. The cursor line at the Viewport’s foot names the cell under the pointer.
  2. Click tile #2, and with Line drag from cell 0, 4 to 4, 4: a worn aisle along the room’s south-west edge.
  3. Click pillars’ row and tile #3. With Brush, click cells 1, 1, 2, 2, 3, 1 and 1, 3.
  4. Click heads’ row and tile #4, and click the same four cells. Press the tab’s Save.
  1. Select room, press + Add node and choose Animated Sprite: the menu opens on Add child of room. Rename it wanderer, and type its Position 16, 56: the middle of cell 3, 3, in front of the pillars.
  2. In its Sprite, drag art/pilgrim.png onto Texture, type Size 38, 48 and Anchor 0.5, 1, his feet, and set Sort Layer to Figures.
  3. In its Animated Sprite, drag art/pilgrim.anim onto Animations, leave Clip at idle, and tick Frame Size.
  4. Press Add component and choose CharacterBodyComponent. Set Motion Mode to Floating and type Speed 80. Leave Driven By at Keys and Size at 32, 48. Press Ctrl+S.
The Animated Sprite’s Frame Size
Ticked, each frame of the clip is drawn at its own size, as the pilgrim’s are cut; unticked, every frame is drawn at the Sprite’s Size.
The body’s Motion Mode: Floating
The keys send him every way, up and down as well as across, and nothing pulls him down: a room seen from above has no floor to fall to. Grounded, as it comes, is the pilgrim’s, who walks and jumps. Speed 80 is how far a held key floats him in a second.
The editor on gallery-iso at 513%, iso-floor lit in the Hierarchy under room, wanderer below it; in the Viewport the diamond floor of dark olive flagstones, worn ones with gold cracks along its lower left edge, three tall pillars with pale capitals, and the wanderer in red and gold standing in front of the fourth, which he hides; the Inspector on iso-floor, its TileMapComponent with Tilemap iso.tilemap, Tile Size 32.0 and 16.0, Grid Isometric, a white Color, Sort Layer Figures and 6, Collision unticked
The room: iso-floor on an Isometric grid, and the wanderer in it.
Why the Problems tab says nothing
room sorts its children by Y, and Problems says so when its Y sort is split across bands that never pass each other: two children on different Sort Layers, or tile layers at different orders on one. Here the map and the wanderer are on one Sort Layer, Figures, and pillars and heads sit at his order, 0, so they pass in front of each other. The floor’s layer at z -1 paints no tile that sorts by Y, so it is not read: it is the floor, under everything.
  1. Press F5: Play runs the open scene, the room.
The game: on a slate blue ground, the room’s diamond of dark olive flagstones, the worn aisle along its lower left edge, three pillars with pale capitals, and the wanderer in red and gold standing in front of the fourth pillar, which he hides
The room in the game, the wanderer in front of the pillars.

Of the two pillars on the room’s middle screen column, the nearer, 2, 2, has its head over the farther’s foot, and draws its foot and its head after the farther’s head: the nearer pillar stands in front, whole. Each foot draws just before its own head.

Stood north of a pillar, his feet higher up the screen than its foot, he draws before its foot and its head; stood south of it, after both. On a copy with him at Position 48, 40, north of the pillar at cell 3, 1:

Close on the room: the wanderer standing behind a pillar, the pillar’s shaft and pale capital drawn over his legs and coat; two more pillars at the left edge
Behind the pillar: it draws over him.
  1. In Play, float him with D and W to behind the pillar up and to his right, at cell 3, 1, his feet just above its foot. Then hold S for a moment.
The room in the game, the wanderer standing behind a pillar, its shaft over his legs; he floats a little way down the screen, past the pillar’s foot, and from there he is drawn in front of it, the pillar behind him
Watch the pillar: while his feet are above its foot it draws over him; once he floats past its foot, he draws over it.

He floats through a pillar, as nothing stops him. Stood west of the room’s middle screen row, at -56, 40, and floated east with D held, he passes through the west pillar and on, 160 east in two seconds at his Speed of 80. Half a second in, he is where the pillar is:

The room in the game, close: the wanderer standing where the left-hand pillar is, the pillar drawn over his legs and coat; the other three pillars to his right on the flagstones
Through the west pillar: it stops nothing.

On a copy with iso-floor’s Collision ticked, the same two seconds:

The same view on a copy with the map’s Collision ticked: the wanderer stopped at the room’s left corner, a little short of the left-hand pillar, the four pillars to his right
Collision ticked: he stops at the pillar’s box, out at the room’s corner, short of the pillar as it is drawn.
Node or fileParentPositionSettings
iso.tilemapiso.png, Tile 32 by 16, Columns 4; floor z -1; pillars Solid, Blocks nav; heads; #3 Y sort 1; #4 Art origin 0, -1, Y sort 1
the paintfloor: #1 Rect 0, 0 to 4, 4; #2 Line 0, 4 to 4, 4. pillars: #3 and heads: #4, each at 1, 1, 2, 2, 3, 1 and 1, 3
cameragallery-iso0, 0Camera Letterbox, Extent 180, Width 320, Background as above; Pixel Perfect, Upscale Render Texture and Crop Frame ticked
roomgallery-iso-84, -40Node; Sort children by Y ticked
iso-floorroom0, 0Tilemap iso.tilemap, Tile Size 32, 16, Grid Isometric, Figures, Collision unticked
wandererroom16, 56Sprite pilgrim.png 38 by 48, Anchor 0.5, 1, Figures; Animated Sprite pilgrim.anim, idle, Frame Size ticked; Character Body Floating, Speed 80

A staggered map

The same tiles on a map numbered by the rows of the screen. An isometric map’s rows run down to the right; a staggered map’s rows run straight across, every other one half a cell on, so a long strip of diamonds is a map of few rows and many columns. It draws on Ground and collides with nothing, its one Solid layer left empty.

  1. Press F5 again to stop. Select gallery-iso, press + Add node and choose Node: the menu opens on Add child of gallery-iso. Rename it room-staggered, and type its Position 36, -40, east of the room.
  2. Select room-staggered, press + Add node and choose Tilemap: the menu opens on Add child of room-staggered. Rename it staggered-floor, and leave its Position at 0, 0.
  3. In its TileMapComponent, type Tile Size 32, 16, set Grid to IsometricStaggered and Sort Layer to Ground. Leave Collision ticked: its only Solid layer will stay empty.
  4. In the Tilemap tab, drop art/iso.png on New tilemap…: a second map from one picture is art/iso-2.tilemap. In Assets, rename it staggered.tilemap. In the Tileset band, type Tile 32 and 16, and Columns 4, as the room’s.
  5. Leave both layers as they come. Click back’s row and tile #1, and with Rect drag from cell 0, 0 to 2, 8: 27 diamonds, x 0 to 112 and y 0 to 80 from the node.
  6. Click tile #2, and with Line drag from cell 0, 4 to 2, 4: the three cells of row 4. Press the tab’s Save, and Ctrl+S.
The TileMap’s Grid: IsometricStaggered
The same diamonds, numbered by the rows of the screen: each row of the map is one row of the screen, its cells a cell’s width apart, and every odd row half a cell across and half a cell down from the even one above it. Row 4, the worn one, is three diamonds side by side on one line, 32 apart.
The Terrains band with staggered-floor selected: Terrains match a square cell’s eight neighbours, so they paint on a Rectangle grid only — this map’s Grid is IsometricStaggered. Under it, greyed: Painting tile #2, No terrains yet - add one and give it tiles below, the New terrain box and Add, and Select a terrain to paint it and edit its tiles
On any other Grid the Terrains band is greyed, and says why.
Terrains, on square grids only
A terrain’s rules are a square cell’s eight neighbours, and a diamond’s or a hexagon’s neighbours are other cells, so the band paints on a Rectangle grid only, and on any other it is greyed under the reason. The gallery’s grids are painted tile by tile, with Brush, Rect and Line.
A wide brush on these grids
The Tools band’s Size, wider than 1, paints a square of cells counted along the map’s own rows and columns, as Scatter’s footprint does. On a staggered or a hex grid that square is not a square on the screen, so leave Size at 1 there.
  1. Press F5.
The staggered map in the game, close: nine rows of dark olive diamonds on the slate blue ground, every other row half a diamond across, so the rows interlock; along the middle row, three worn diamonds with gold cracks side by side
The staggered map: its worn row 4 is one row of the screen.

Every tile it draws is one of iso.png’s, the sheet the room cuts the same way: only the numbering differs. The worn row is three diamonds on one line, a cell’s width apart, and the row above it, an odd one, stands half a cell across from it.

Node or fileParentPositionSettings
staggered.tilemapiso.png, Tile 32 by 16, Columns 4; back and ground as they come
the paintback: #1 Rect 0, 0 to 2, 8; #2 Line 0, 4 to 2, 4
room-staggeredgallery-iso36, -40Node
staggered-floorroom-staggered0, 0Tilemap staggered.tilemap, Tile Size 32, 16, Grid IsometricStaggered, Ground

Two boards of hexes

Two boards of grass with a marsh winding down each, one of pointy-topped hexes and one of flat-topped. A token stands on each; each press of a direction steps both tokens into a neighbouring hex, onto its centre, adds up what the hex costs, shows its name, and turns it to trodden earth. The boards draw on Ground and the tokens over them, on Figures, their words on Words. The boards’ Collision is left as it comes: the tokens are moved by their script, which nothing stops.

  1. Press F5 again to stop, then Ctrl+S, and start gallery-hex as the first section says: a new scene, its root gallery-hex, saved as scenes/gallery-hex.ron, and its camera.
  2. Select gallery-hex, press + Add node and choose Tilemap: the menu opens on Add child of gallery-hex. Rename it board-pointy, and type its Position -140, -56.
  3. In its TileMapComponent, type Tile Size 24, 24, set Grid to HexPointyTop and Sort Layer to Ground. Leave Collision ticked.
  4. In the Tilemap tab, drop art/hex-pointy.png on New tilemap…: art/hex-pointy.tilemap. The picture, 72 by 24, came with the starter: three hexes of 24 by 24, grass, marsh and trodden earth. In the Tileset band, type Tile 24 and 24, and Columns 3.
The TileMap’s Grid: HexPointyTop and HexFlatTop
Hexagon cells, each in a 24 square. HexPointyTop lays pointy-topped hexes in rows 18 apart, every odd row 12 on, so a hex has neighbours east and west and four on the slants, and none straight up. HexFlatTop lays flat-topped hexes in columns 18 apart, every odd column 12 down, so a hex has neighbours north and south and none straight across.

Each tile carries two values a script reads wherever it is painted: what the hex costs to enter, and its name.

  1. Click tile #1, the grass. Under Data, press Add value and choose Int: a row named key. Type cost over its name, press Enter, and type its value 1.
  2. Press Add value again and choose Text. Type name over the new row’s name, press Enter, and type grass in its box.
The Tilemap tab with board-pointy selected: Tile #1, Zoom 2.0, cost - name, and the picker’s three hexes, the green grass outlined, the dark marsh and the brown trodden earth; the Tile 1 band, its preview the grass, Cell 1 of 3, Tint white, Art origin, Z offset, Y sort and Weight as they come; Animation still; Data, 2 values: a row cost with 1 and a bin, a row name with grass and a bin, and Add value; Scene (none); Draws as #1
The grass, #1: Data cost 1 and name grass.
  1. Click tile #2, the marsh, and give it the same two rows: cost 2 and name marsh.
  2. Click tile #3, the trodden earth, and give it one row alone: Text, name, trodden.
A tile’s Data: Int and Text, and Add value
Chapter 4’s named values, two more kinds of them. Add value offers Bool, Int, Float and Text, and each adds a row named key at its kind’s blank: 0 for an Int or a Float, unticked for a Bool, empty for a Text. Int is a whole number, read by tile_number; Text is words, read by tile_text. The trodden earth has no cost row, so a hex trodden again costs nothing.
  1. Click ground’s row, and tile #1. With Rect, drag from cell 0, 0 to 4, 5: 30 hexes, x 0 to 132 and y 0 to 114 from the node.
  2. Click tile #2. With Line, drag from cell 2, 0 to 2, 5; with Brush, click cell 3, 4. back stays empty. Press the tab’s Save.
  3. Select gallery-hex and add a second Tilemap the same way: board-flat, at Position 24, -66, Tile Size 24, 24, Grid HexFlatTop, Sort Layer Ground. Drop art/hex-flat.png on New tilemap…, cut it the same, and give its three tiles the same rows.
  4. On its ground, paint #1 with Rect from cell 0, 0 to 5, 4, #2 with Line from 2, 0 to 2, 4, and #2 with Brush at 3, 3. Press the tab’s Save, and Ctrl+S.

The pointy board covers x -140 to -8 and y -56 to 58 in the world, the flat one x 24 to 138 and y -66 to 66. Now a token for each.

  1. In Assets, with Assets clicked in the path bar, click Create, choose New script, type token and press Enter. Click the Code tab, then token.rgs in its Scripts list, replace everything in it with the script below, and press Ctrl+S. Click the Viewport tab.
rgs token.rgs
/// A token on a board of hexes. Each press of a direction steps it into a
/// neighbouring hex, onto the hex's centre. The hex turns to trodden earth,
/// its cost is added to the token's, and its name shows over the token.
component Token {
    /// The board the token walks: the node whose tilemap holds its hexes.
    #[node_path]
    board: i32 = 0,
    /// What the hexes the token has entered cost, added up.
    #[readonly]
    cost: f32 = 0.0,

    fn loop() {
        // Right (D, or the right arrow), left (A, or the left arrow), up (W,
        // or the up arrow) and down (S, or the down arrow) each step it.
        if pressed("right") || pressed("left") || pressed("up") || pressed("down") {
            // Each aims at a point a little under a hex's width from the
            // token's middle, a little to one side of straight. A board of
            // pointy-top hexes has no neighbour straight up, and one of
            // flat-top hexes none straight to the right; aimed this way, a
            // press lands well inside one neighbouring hex on either board,
            // never on the edge between two.
            let aim = vec2(0.0, 0.0);
            if pressed("right") {
                aim = vec2(21.0, -6.0);
            } else if pressed("left") {
                aim = vec2(-21.0, 6.0);
            } else if pressed("up") {
                aim = vec2(6.0, -21.0);
            } else if pressed("down") {
                aim = vec2(-6.0, 21.0);
            }
            // The hex the aim falls in. A cell with no hex painted on the
            // board's ground layer is off its edge, and the token stays put.
            let cell = cell_at(node(board), position() + aim);
            if tile_at(node(board), "ground", cell) != 0 {
                // The token stands on the hex's centre.
                move_to(cell_centre(node(board), cell));
                // The hex's Data rows, read as they were when the step began:
                // its cost is added to the token's, and its name is shown.
                cost += tile_number(node(board), "ground", cell, "cost");
                let name = tile_text(node(board), "ground", cell, "name");
                set_text("WorldTextComponent", "text", name);
                // The hex turns to trodden earth, tile 3, from the next step.
                set_tile(node(board), "ground", cell, 3);
            }
        }
    }
}
component Token, board and cost
A script with no base. board is #[node_path], a node picker in the Inspector, Board: the map whose hexes the token walks. cost is #[readonly], greyed, the hexes’ costs added up, to watch.
The aims
Each press aims at a point a little under a hex’s width from the token’s middle, a little to one side of straight: right at 21, -6, left at -21, 6, up at 6, -21 and down at -6, 21. Each lands well inside one neighbouring hex on either board, never on an edge. One script serves both boards, so up steps up and to the right on the pointy board, which has no hex straight up, and right steps right and up on the flat one, which has none straight across.
cell_at, tile_at and node
cell_at is the cell of the board’s grid a point in the world falls in, a hexagon here, as chapter 4’s found a square. tile_at is the tile painted there on ground, 0 for none: off the board’s edge the token stays put.
cell_centre and move_to
cell_centre is the middle of a cell in the world, on any grid: on odd rows and odd columns too, half a cell on. move_to stands the token there.
tile_number and tile_text
The value of a Data row of the tile in a cell, by its name: tile_number an Int’s or a Float’s as a number, tile_text a Text’s as words. A tile with no such row gives 0, or no words: trodden earth has no cost, so it adds 0.
set_tile and set_text
set_tile turns the hex to tile 3, trodden earth, in the map’s own copy for the run, as chapter 12’s bridge was laid: the .tilemap on disk is as painted. set_text writes the hex’s name on the token’s World Text.
What a step reads
Every tile a script reads in a step is as the step began, and a set_tile lands from the next step. So the hex’s cost and name are its own, not trodden earth’s, whichever line comes first: reading before writing, as token.rgs does, changes nothing.
  1. Select gallery-hex, press + Add node and choose Shape: the menu opens on Add child of gallery-hex. Rename it token-pointy, and type its Position -92, -26: the centre of board-pointy’s cell 1, 1.
  2. In its Shape, set Kind to Circle, type Size 12, 12, and leave Anchor at 0.5, 0.5. Type Color and Outline Color as the table below gives them, Outline 1, and set Sort Layer to Figures.
  3. Press Add component and choose WorldTextComponent. Clear its Text, type Offset 0, -14, and set Sort Layer to Words. Leave the rest as it comes.
  4. Drag token.rgs onto its Inspector: it adds Token, a Board row, empty, and Cost greyed. Click Board and choose board-pointy.
  5. Right-click token-pointy in the Hierarchy and choose Duplicate: token-pointy copy appears straight after it. Rename it token-flat, type its Position 54, -18, the centre of board-flat’s cell 1, 1, and set its Board to board-flat. Press Ctrl+S.
Typed
Color, the signposts’ bone0.93, 0.86, 0.66, alpha 1
Outline Color, their words’ brown0.18, 0.10, 0.05, alpha 1

On the screen each token is a cream disc with a thin brown rim, the rim lighter than its numbers look, as a colour typed in linear light shows.

The World Text’s Offset, over the token
0, -14: the words stand 14 above the token’s middle, clear of the disc. They draw on Words, over the boards and the tokens.
The editor on gallery-hex at 295.3%, board-pointy lit in the Hierarchy, board-flat, token-pointy and token-flat below it; in the Viewport two boards of green grass hexes, the left one pointy-topped in rows, the right one flat-topped in columns, a dark marsh winding down the middle of each, and a cream token near the top left of each; the Inspector on board-pointy, its TileMapComponent with Tilemap hex-pointy.tile…, Tile Size 24.0 and 24.0, Grid HexPointyTop, a white Color, Sort Layer Ground and 4, Collision ticked
The two boards and their tokens.
  1. Press F5. Press D twice, then S twice, A twice and W twice, a moment between each: a ring of eight presses.
The hex boards in the game: at each press both tokens step into a neighbouring hex and stand on its centre, the word over each token says what that hex was, and the hex under each turns brown, trodden earth; round the ring of eight presses the trodden hexes make a ring on each board, and the tokens end back where they began
Watch each press: both tokens step onto a hex’s centre, the word over each says what the hex was, and the hex turns to trodden earth.

Round the ring each token stands on a hex’s centre at every press, on odd rows and columns as on even ones, and ends where it began. Each hex it enters reads trodden in the map’s copy for the run, and the exported game’s map is as it was painted.

  1. Press F5 twice, to stop and play again: the trodden earth goes with the run. Select token-pointy, to watch its Cost in the Inspector, and press D, D, then A.

The first right steps each token onto marsh, adding its cost of 2 and reading “marsh”; the second, onto grass, adds 1 and reads “grass”; and the left, back onto the marsh just trodden, adds 0 and reads “trodden”.

Node or fileParentPositionSettings
hex-pointy.tilemap, hex-flat.tilemaptheir pictures, Tile 24 by 24, Columns 3; Data: #1 cost 1, name grass; #2 cost 2, name marsh; #3 name trodden
the paintpointy ground: #1 Rect 0, 0 to 4, 5; #2 Line 2, 0 to 2, 5 and 3, 4. Flat ground: #1 Rect 0, 0 to 5, 4; #2 Line 2, 0 to 2, 4 and 3, 3
board-pointygallery-hex-140, -56Tilemap hex-pointy.tilemap, Tile Size 24, 24, Grid HexPointyTop, Ground
board-flatgallery-hex24, -66Tilemap hex-flat.tilemap, the same, Grid HexFlatTop
token-pointygallery-hex-92, -26Shape Circle 12 by 12, Outline 1, colours as above, Figures; WorldTextComponent, empty, Offset 0, -14, Words; Token, Board board-pointy
token-flatgallery-hex54, -18a duplicate of token-pointy, Board board-flat

A dungeon cut with its gutters

A room seen from straight above, walled in stone, with a knight who walks it and an orc who stands still, each with a weapon in hand, and two pots between them. Its tiles come from Kenney’s Tiny Dungeon, whose sheet has a gutter of one pixel between every two tiles. The map draws on Ground and its walls stop the knight; the figures and the pots draw on Figures, sorted by their feet under hall.

  1. Press F5 again to stop. Copy the picture above into art, and press Refresh in Assets.
  2. Double-click art/tiny-dungeon.png in Assets: the Sprite sheet tab opens on it, 203 by 186, cut in cells of 32 as it opens.
  3. In the Grid band, press Detect grid: it reads the cells off the picture’s gaps, Cell 16 and 16, Margin 0 and 0, Spacing 1 and 1, 12 x 11 cells. Typing those does the same.
  4. Name five regions, one cell each, as the table below gives them: click the cell, type its name in the box beside Name it under Regions, and press Name it. Then click the Viewport tab.
RegionCell (column, row)From (x, y)
knight, the armoured knight0, 80, 136
sword8, 8136, 136
orc, the one-eyed brute1, 917, 153
axe, a double axe10, 9170, 153
dummy, a wooden target6, 5102, 85
The Sprite sheet tab on tiny-dungeon.png, 203x186: Grid with Cell w 16 h 16, Margin x 0 y 0, Spacing x 1 y 1, Detect grid and 12 x 11 cells; Clips; Regions saying Select cells to name a region., and knight, sword, orc, axe and dummy, each with a bin; and the sheet under its grid of 16-pixel cells with a gap between each two: floors and walls, doors, chests, then rows of heroes, monsters, weapons and potions
Tiny Dungeon’s sheet, its grid read off its gutters, and its five regions.

Each region starts 17 pixels on from the one before it, across or down: a tile and its gutter. The knight in column 0, row 8, is at 0, 136, not the 0, 128 a sheet with no gutter would give.

  1. Press Ctrl+S, and start gallery-dungeon as the first section says: a new scene, its root gallery-dungeon, saved as scenes/gallery-dungeon.ron, and its camera.
  2. Select gallery-dungeon, press + Add node and choose Tilemap: the menu opens on Add child of gallery-dungeon. Rename it dungeon, leave its Position at 0, 0, and set Sort Layer to Ground. Leave Tile Size 16, 16, Grid Rectangle and Collision ticked as they come: the walls stop the knight.
  3. In the Tilemap tab, drop art/tiny-dungeon.png on New tilemap…. In Assets, rename art/tiny-dungeon.tilemap dungeon.tilemap. New tilemap cuts it in tiles of 16, twelve to a row, all that fit across 203.
  4. In the Tileset band, type Spacing 1 and 1, and leave Margin at 0.
The Tileset band with dungeon selected: Sheet tiny-dungeon.png, Tile w 16 h 16, Columns 12, Margin x 0 y 0, Spacing x 1 y 1, Sheet 203x186, 132 tiles, 11 rows, and the sheet cut on that grid, every tile in its own cell
The sheet cut with its gutter: 132 tiles, eleven rows of twelve.
The Tileset band’s Spacing
The gutter between tiles on the sheet, in pixels, across and down: 1 and 1 here, where chapter 2’s sheet had none. Tile n of the cut, counting from 0, starts at 17 × its column and 17 × its row: the stone wall, #41, the cell 40, at 68, 51, four gutters across and three down, not the 64, 48 a sheet with no gutter would give. The Sprite sheet tab’s Spacing is the same gutter, for regions.
  1. Rename back floor and ground walls. floor stays as it comes, not Solid; walls stays Solid with Blocks nav, both at z 0.
  2. Click floor’s row and tile #49, the plain sand floor. With Rect, drag from cell -8, -4 to 7, 3: 128 cells, x -128 to 128 and y -64 to 64.
  3. Click walls’ row and tile #41, stone bricks. With Line, draw the four sides of a ring round the floor, as the table below gives them: 52 cells, x -144 to 144 and y -80 to 80, a room 18 by 10.
WallFrom cellTo cell
north-9, -58, -5
south-9, 48, 4
west-9, -4-9, 3
east8, -48, 3

The room is painted in sand. The sheet has a brown dungeon floor too, tile #1, and the room is to be brown: rather than repaint 128 cells, the sand is told to draw as the brown.

  1. Click tile #49 in the picker. In the Tile band, type Draws as 1. Press the tab’s Save.
The Tile 49 band: its preview the brown floor, Cell 49 of 132 and, in amber, Reads as 1; Tint white; Art origin, Z offset, Y sort and Weight as they come; Animation still and Add frame; Data, no values, and Add value; Scene (none) — drop a scene or artifact; Draws as #1 and a cross
The sand, #49, drawn as #1: every cell painted with it shows the brown floor.
A tile’s Draws as
Chapter 4’s, for real: every cell painted with #49 draws #1’s art, and the band says Reads as 1, its preview the brown. The file still holds the sand in all 128 cells, so nothing is repainted, and pressing the cross beside Draws as gives the sand back. It is for a sheet whose art is changed after a room is painted on it, or a room re-skinned at a stroke.

Then the figures. Each is a Sorting Group holding its body and its weapon, so the two sort as one by the group’s place, its feet, and nothing of another figure comes between them.

  1. Select gallery-dungeon, press + Add node and choose Node: the menu opens on Add child of gallery-dungeon. Rename it hall, leave its Position at 0, 0, and in its Node’s Advanced fold tick Sort children by Y.
  2. Select hall, press + Add node and choose Sorting Group: the menu opens on Add child of hall. Rename it knight, type its Position -72, -32, his feet, and set Sort Layer to Figures. Leave Depth and Enabled as they come.
  3. Press Add component and choose CharacterBodyComponent. Set Motion Mode to Floating, type Speed 80 and Size 12, 8: a footprint at his feet. Leave Driven By at Keys.
  4. Select knight, press + Add node and choose Sprite: the menu opens on Add child of knight. Rename it knight-body, and leave its Position at 0, 0. In its Sprite, drag art/tiny-dungeon.png onto Texture, type knight in Atlas Region, Size 16, 16 and Anchor 0.5, 1, and set Sort Layer to Figures.
  5. Select knight again and add a second Sprite: knight-sword, at Position 8, -7, beside his right hand. The same picture, Atlas Region sword, Size 16, 16, Anchor left at 0.5, 0.5, Sort Layer Figures.
  6. Select hall, and add a second Sorting Group: orc, at Position -80, 8, Sort Layer Figures. It has no body: it stands still.
  7. Select orc and add a Sprite as the knight’s body: orc-body, at Position 0, 0, Atlas Region orc, Size 16, 16, Anchor 0.5, 1, Sort Layer Figures.
  8. Select orc again and add a second Sprite: orc-axe, at Position -8, -7, Atlas Region axe, Size 16, 16, Anchor left at 0.5, 0.5, Sort Layer Figures.
The Sorting Group’s Sort Layer, under a parent that sorts by Y
The group draws its children as one, on its own Sort Layer, Figures, sorted by Y among hall’s other children by the group’s own place, the figure’s feet. A weapon stands 7 above its figure’s feet: inside its group it draws with the body, behind it; sorted on its own by its own Y, it would slice the figure whenever another’s feet were up to 7 above his.

Two pots, outlined Circles among the figures.

  1. Select hall, press + Add node and choose Shape: the menu opens on Add child of hall. Rename it pot-1, and type its Position -40, 40.
  2. In its Shape, set Kind to Circle, type Size 10, 10 and Anchor 0.5, 1, its foot. Type Color and Outline Color as the table below gives them, Outline 1, and set Sort Layer to Figures.
  3. Right-click pot-1 in the Hierarchy and choose Duplicate: pot-1 copy appears straight after it. Rename it pot-2, and type its Position 24, -24. Press Ctrl+S.
Typed
Color, the sheet’s brown0.509, 0.150, 0.068, alpha 1
Outline Color, its dark outline0.050, 0.019, 0.031, alpha 1

Typed in linear light, the brown shows lighter than its numbers look, as the sheet’s terracotta, ringed in a dark plum.

The Shape’s Outline, and where the ring sorts
An outlined Circle draws its fill and its ring as one, in one draw, so the ring sorts with its fill, by the pot’s foot: with the knight’s feet just above the pot’s it draws over both his parts, ring and all, and with his feet just below, under them.
  1. Press F5, and hold S.
The dungeon in the game: a room of grey stone bricks round a brown floor, two terracotta pots on it; the knight in his helmet, his sword at his side, floats down the room past the orc with its double axe, behind it as he reaches it and in front of it as he passes, his sword with him all the way
Watch the knight pass the orc: behind it while his feet are above the orc’s, in front once they are below, his sword with him all the way.

On every frame the knight’s body and his sword draw together, with nothing of the orc between them: before both the orc’s parts while his feet are above the orc’s, after both once they are below, through the band where each part sorted by its own place would have sliced him.

Node or fileParentPositionSettings
tiny-dungeon.pngregions knight, sword, orc, axe, dummy, cut on Cell 16, Spacing 1
dungeon.tilemaptiny-dungeon.png, Columns 12, Spacing 1, 1; floor, walls; #49 Draws as 1
the paintfloor: #49 Rect -8, -4 to 7, 3. walls: #41, four Lines, the ring above
dungeongallery-dungeon0, 0Tilemap dungeon.tilemap, Ground
hallgallery-dungeon0, 0Node; Sort children by Y ticked
knighthall-72, -32Sorting Group, Figures; Character Body Floating, Speed 80, Size 12, 8
knight-body, knight-swordknight0, 0; 8, -7Sprites, regions knight, Anchor 0.5, 1, and sword; 16 by 16, Figures
orchall-80, 8Sorting Group, Figures
orc-body, orc-axeorc0, 0; -8, -7Sprites, regions orc, Anchor 0.5, 1, and axe; 16 by 16, Figures
pot-1, pot-2hall-40, 40; 24, -24Shape Circle 10 by 10, Anchor 0.5, 1, Outline 1, colours as above, Figures

A damage counter

A practice dummy in the dungeon, and over it, about every 0.6 seconds, a number saying how hard it was struck, which rises and fades and is gone. Each number is a World Text made by a Spawner and gone when its script is done; it draws on Words, over everything, and collides with nothing.

  1. Press F5 again to stop. In Assets, with Assets clicked in the path bar, click Create, choose New script, type number and press Enter. Click the Code tab, then number.rgs in its Scripts list, replace everything in it with the script below, and press Ctrl+S. Click the Viewport tab.
rgs number.rgs
/// A number rising over the practice dummy. It shows how hard the blow was,
/// a whole number from 1 to 19, rises and fades for 0.8 of a second, and is
/// gone.
component Number {
    fn on_create() {
        // random gives a number from 1 up to, but never, 20; floor drops what
        // comes after the point, and text writes it with none.
        set_text("WorldTextComponent", "text", text(floor(random(1.0, 20.0))));
        // Over 0.8 of a second the words rise from the node to 16 above it,
        // quickly at first and slowing as they arrive...
        anneal_point("WorldTextComponent", "offset", vec2(0.0, -16.0), 0.8, .OutCubic);
        // ...and over the same 0.8 they fade evenly until nothing is left.
        await anneal_colour("WorldTextComponent", "color", vec4(1.0, 1.0, 1.0, 0.0), 0.8, .Linear);
        // Faded out, the number is gone.
        destroy_self();
    }
}
on_create
Runs once, as the copy is made: each number shows, rises and fades of its own accord, and nothing else need tell it to.
random, floor and text
random(1.0, 20.0) is a number from 1 up to, but never, 20; floor drops what comes after its point; text writes it as words, with no point. A whole number from 1 to 19, new for every copy.
Two anneals at once, and destroy_self
Chapter 10’s anneal_point and anneal_colour, on the words’ Offset and Color. The first is not awaited, so both run together for 0.8 seconds: the words rise to 16 above the node, fast then slowing, and fade evenly to nothing. The second is awaited, and once it is done the copy takes itself away.
  1. Press Ctrl+S. Choose File → New scene: an empty scene takes the dungeon’s place.
  2. Press + Add node and choose World Text. Rename it number. Clear its Text, and set Sort Layer to Words. Leave the rest as the preset gives it: Pixel Size, Offset 0, 0, white, outlined black, Copies, the project’s face.
  3. Drag number.rgs onto its Inspector: it adds Number, with nothing to set.
  4. Right-click number in the Hierarchy and choose Save as artifact…, and save it in artifacts as number.artifact.
  5. Double-click scenes/gallery-dungeon.ron in Assets. The editor asks Save the open scene?: press Discard. The number is in its artifact, and the scene round it is not wanted.
  1. In Assets, with Assets clicked in the path bar, click Create, choose New script, type dummy and press Enter. Click the Code tab, then dummy.rgs in its Scripts list, replace everything in it with the script below, and press Ctrl+S. Click the Viewport tab.
rgs dummy.rgs
/// A practice dummy. Every 0.6 of a second it takes a blow, and a number
/// saying how hard rises over it: a copy of the artifact its Spawner names
/// number.
component Dummy {
    fn loop() {
        // The number is made at the end of the step, 24 above the dummy's
        // feet, just over its head. Then 0.6 of a second's wait before the
        // next blow.
        spawn("number", position() + vec2(0.0, -24.0));
        await wait(0.6);
    }
}
spawn and await wait
Chapter 13’s: a copy of the artifact the dummy’s Spawner names number, made at the end of the step 24 above its feet, then 0.6 seconds before loop() comes round again. The loop starts its next turn a step after its wait ends, so the numbers come 37 steps apart: about every 0.6 seconds.
  1. Select hall, press + Add node and choose Sprite: the menu opens on Add child of hall. Rename it dummy, and type its Position 72, 0.
  2. In its Sprite, drag art/tiny-dungeon.png onto Texture, type dummy in Atlas Region, Size 16, 16 and Anchor 0.5, 1, and set Sort Layer to Figures.
  3. Press Add component and choose SpawnerComponent. Press the + beside Entries, open the new row, type number into Name, and drag artifacts/number.artifact from Assets onto Artifact.
  4. Drag dummy.rgs onto its Inspector: it adds Dummy. Press Ctrl+S.
  5. Press F5.
Close on the dummy, a wooden target on the brown floor: a white number appears over its head, rises, slowing as it goes, and fades away; another follows, and another
Watch over the dummy: a number about every 0.6 seconds, each rising 16 and fading as it goes.

Over four seconds a number appears every 0.6 seconds, give or take two steps, each a whole number from 1 to 19. It rises to 16 above its node within 0.8 seconds, and fades evenly: half of it is left 0.4 seconds in, and it is gone within a second of appearing.

The dungeon in the game: a room of grey stone bricks round a brown floor; near the top left the knight with his sword, below him the orc with its double axe, two terracotta pots, and on the right the wooden dummy with a small white 3 over it
The dungeon, its dummy struck.
Node or fileParentPositionSettings
number.artifactWorld Text number, empty, Words; Number
dummyhall72, 0Sprite, region dummy, 16 by 16, Anchor 0.5, 1, Figures; Spawner, number, number.artifact; Dummy

A far ridge

A skyline of stone far behind, which the camera pans along and which drifts slower than the camera. The ridge is the crypt’s stone on a second map, laid with chapter 3’s blob terrain and tinted dim. It rides a Parallax plane, draws on Far, and collides with nothing.

  1. Press F5 again to stop, then Ctrl+S, and start gallery-lookout as the first section says: a new scene, its root gallery-lookout, saved as scenes/gallery-lookout.ron, and its camera.
  2. In Assets, with Assets clicked in the path bar, click Create, choose New script, type pan and press Enter. Click the Code tab, then pan.rgs in its Scripts list, replace everything in it with the script below, and press Ctrl+S. Drag it onto camera’s Inspector: it adds Pan. Click the Viewport tab.
rgs pan.rgs
/// The lookout's camera. Held left or right (A or D, or the arrows), it pans
/// along the far ridge, 80 a second.
component Pan {
    fn loop(dt: f32) {
        // Across only: the ridge is a skyline, and the spyglass looks along
        // it.
        if held("left") {
            translate(vec2(-80.0 * dt, 0.0));
        }
        if held("right") {
            translate(vec2(80.0 * dt, 0.0));
        }
    }
}
held and translate
held("right") is true on every step D or the right arrow is down. translate moves the camera’s node by 80 × dt, the step’s share of a second: 80 units a second, left or right.
  1. Select gallery-lookout, press + Add node and choose Node: the menu opens on Add child of gallery-lookout. Rename it ridge, and leave its Position at 0, 0.
  2. Press Add component and choose ParallaxComponent. Type its Factor 0.4, 1. Leave Repeat X ticked, and Offset, Autoscroll and Color as they come.
  3. Select ridge, press + Add node and choose Tilemap: the menu opens on Add child of ridge. Rename it ridge-tiles, and type its Position -192, -16. Set Sort Layer to Far, and type Color as the table below gives it. Leave Collision ticked for now.
  4. In the Tilemap tab, drop art/crypt-stone.png on New tilemap…: the editor writes art/crypt-stone-3.tilemap, as the status line says, and points ridge-tiles at it: the names chapter 2’s and chapter 13’s maps left still hold their ids. In Assets, rename it ridge.tilemap. It is cut as it comes: 16 pixels, Columns 8. Leave both layers as they come, back and a Solid ground.
  5. In the Terrains band, type stone in the box and press Add. Click the stone row: it lights, armed. 47-tile blob from reads #1: press Add blob, as in chapter 3.
  6. Click ground’s row, and click the stone row again. With Rect, drag the foot row, from cell 0, 7 to 23, 7; then each run of columns in the table below, from its top row down to row 7. Press the tab’s Save, and Ctrl+S.
Color
The ridge’s map0.25, 0.25, 0.35, alpha 1
ColumnsFrom row
1 to 35
4 to 63
7 and 82
9 to 11, the peak0
12 to 141
15 to 173
18 to 204
21 and 226

That is 114 cells, each the blob tile its neighbours call for, 24 cells, 384, wide. Both ends are the foot row alone, under the view, so where Repeat X lays the next copy, 384 on, the two meet out of sight. At the start the ridge is x -192 to 192 and y -16 to 112, its peak x -48 to 0, just left of the middle.

  1. Press F5.
The lookout in the game, before its spyglass: under the slate blue sky a skyline of dark olive stone rising in steps from the left to a peak just left of the middle and falling away in steps to the right, each step lipped in brown
The ridge, its map tinted dim by its Color.
The Parallax’s Factor, 0.4
How much of the camera’s pan the plane is carried along by: at 0.4 across, panned 80 the ridge is carried 32, so it slides past 0.6 as fast as the camera, far away. 1 down: the camera never moves down. Repeat X lays a copy every ridge’s width, so the skyline never runs out.
The TileMap’s Color, on the ridge
A tint over every tile, white as it comes: 0.25, 0.25, 0.35 dims the crypt’s stone, as a far skyline is. Typed in linear light, it keeps more of the stone than the numbers suggest: dark olive, still lipped in brown.

With its Collision ticked, as it comes, the Problems tab has a row for the map:

The Problems tab, Problems (1): All 1, Errors 0 and a search box; Warnings 1, one orange row on ridge-tiles: This tilemap is on or under the Parallax plane "ridge", which moves what it draws but not what it collides with: its solid and Blocks-nav layers stop bodies and block navigation where the map would be without the plane — untick Collision for a backdrop, or untick Solid and Blocks nav on its layers
The ridge with its Collision ticked: a row says so.
The row for a map under a plane
“This tilemap is on or under the Parallax plane "ridge", which moves what it draws but not what it collides with”: a plane carries the ridge’s tiles as the camera pans, but its Solid ground would collide where the map stands without the plane, an invisible ridge in the wrong place. A backdrop should collide with nothing.
  1. Press F5 again to stop. Select ridge-tiles and untick Collision: the row goes. Press Ctrl+S.

Panned right for a second, the camera moves 80 and the ridge is drawn 32 further along, and its map puts up no solid anywhere. On a copy with its Collision ticked, its tiles do collide, where the map would be without the plane.

Node or fileParentPositionSettings
ridge.tilemapcrypt-stone.png, 16 pixels, Columns 8; terrain stone, Add blob from #1; ground: the foot row and eight runs, 114 cells
cameragallery-lookout0, 0as every gallery’s; Pan
ridgegallery-lookout0, 0Node; ParallaxComponent Factor 0.4, 1, Repeat X ticked
ridge-tilesridge-192, -16Tilemap ridge.tilemap, Far, Color as above, Collision unticked

A spyglass

A round view of the ridge in a dark shade: a Sprite Mask under the camera writes a disc, and a dark Sprite over the whole view draws everywhere outside it. Both ride with the camera, on Words over everything, and neither collides.

  1. Select camera, press + Add node and choose Sprite Mask: the menu opens on Add child of camera. Rename it lens, and leave its Position at 0, 0.
  2. In its Sprite Mask, drag art/reveal.png onto Texture, chapter 11’s soft reveal, and type Size 128, 128. Leave Alpha Cutoff at 0.5, and set Sort Layer to Words. Leave Anchor, Channel 0 and Enabled as they come. Problems says nothing reads channel 0, until the next steps.
  3. Select camera, press + Add node and choose Sprite: the menu opens on Add child of camera. Rename it shade, and leave its Position at 0, 0.
  4. In its Sprite, drag art/shade.png onto Texture, a small white square that came with the starter, type Size 336, 196, the view and 8 to spare each side, type Color as the table below gives it, and set Sort Layer to Words.
  5. Tick Mask, and untick Inside: it draws outside the lens. The row in Problems goes. Press Ctrl+S.
Color
The shade0.02, 0.02, 0.05, alpha 0.85
shade’s SpriteComponent in the Inspector: Texture shade.png, Size 336.0 and 196.0, Anchor 0.5 and 0.5, a dark Color over a chequer, Flash 0.00, Sort Layer Words and 7, Flip X and Y unticked, Opaque unticked, Blend Alpha, Unshaded and Light Only unticked, Normal Map none, Specular 0.00; Draw mode Simple, Slice Border 0.0, Tile Size 0.0 and 0.0; Atlas Region empty; Mask ticked, Channel 0, Inside unticked
shade: Mask ticked, reading channel 0, Inside unticked.
The Sprite Mask’s Size and Alpha Cutoff, a hard disc
The reveal’s alpha falls evenly from 1 at its middle to 0 at 32 of its 64 pixels out. At 0.5 the disc keeps half of those, 16, and laid at 128, two units a pixel, it is a disc of radius 32, (1 − 0.5) × 64. Two units a pixel is a whole number, so its edge steps evenly, a step every two units.
The Sprite’s Inside, unticked
Chapter 11’s murals read their channel from the inside, and showed only where the lantern wrote it. Unticked, the shade draws only where channel 0 is not written: everywhere but the lens.
  1. Press F5.
The lookout in the game, close on its middle: a disc of slate blue sky, its round edge stepping in even squares, the ridge’s peak inside it in dark olive stone lipped with brown; outside the disc the same sky and stone darkened to a deep blue-grey
Through the lens: inside the disc the ridge as it is, outside it the shade, the edge stepping evenly.

Inside the disc, 32 about the camera, every pixel is what the view would show with no shade; outside it every pixel is darkened 0.85 of the way to the shade’s near black, its alpha. Hold D:

The lookout in the game: the view dark but for the round lens in the middle, the ridge’s peak in it; as the camera pans right the ridge slides left, through the lens and across the darkened view, until only sky is in the lens, the lens and the shade staying still in the view
Watch the lens: the ridge slides left through it as the camera pans right, 0.6 as fast as the camera, while the lens and the shade stay put.
Node or fileParentPositionSettings
lenscamera0, 0Sprite Mask reveal.png, Size 128, 128, Alpha Cutoff 0.5, Words, Channel 0
shadecamera0, 0Sprite shade.png, Size 336, 196, Color as above, Words; Mask ticked, Channel 0, Inside unticked

Check it works