Skip to content

Tutorials · Cameras and Framing · Chapter 10

A map in the corner

45 minutes Uses: Viewport, in_group, change_scene

By the end

  • The project’s seventeen sorting layers named, back to front, and every node that draws picked onto its own, with nothing moved in the stack
  • A Viewport under the watchman that sees 480 units round him into a texture of its own, and a HUD panel that shows it in the screen’s top right corner, under a brass frame
  • The same map in the castle, pasted with a texture of its own, which shows the next room before the screen does
  • A wooden door at the great hall’s west end that takes him back to the town
On this page

Seventeen named layers

A map should show where things are, and leave out the sky. A view is told which sorting layers to draw, by name, and so far the project’s layers have had no names: every node carries a bare Sort Layer number, from the sky’s -70 to the arrow’s 10, and the project’s list of names holds one row, Default. This chapter names them first.

  1. Open File → Project settings… and its Layers tab. Double-click the one row, Default, type Sky and press Enter.
  2. Click the box beside Add layer, type Clouds and press Enter. The new row lands under the last: further down the list is nearer the camera.
  3. Add the other fifteen the same way, in the order of the table below, from Mountains to Marks. Drag the window’s bottom right corner down to see the whole list.
The Project settings window on its Layers tab, its corner dragged down: a dim note at the top, then Back of the scene at the top, nearest the camera at the bottom, and seventeen rows, Sky id 0, Clouds id 1, Mountains id 2, Lights id 3, Buildings id 4, Forest id 5, Town id 6, Fog id 7, Rooftops id 8, Gate id 9, Fixtures id 10, Ground id 11, Props id 12, Breath id 13, Figures id 14, Glass id 15 and Marks id 16, each with a bin and two arrows; under them a box reading Foreground in grey beside Add layer, Saved to cameras-and-framing/sorting-layers.ron, and a note on what a node stores
The seventeen names, back to front.

The note at the top of the tab says what a name is: each name labels a Sort Layer number, its place in this list, counted from 0 at the top. The game sorts on the number each node stores, and a view picks its layers by those numbers too, without reading the list. The names are what the Inspector shows for the numbers, in a node’s Sort Layer and in a view’s Layers.

#NameIn the townIn the castleThe number it had
0Skysky-70
1Cloudsclouds-65
2Mountainsmountains-60
3Lightslights-59
4Buildingsfar-buildingscastle-wall-50
5Forestforest-40
6Towntownscape-30
7Fogfog-25
8Rooftopsrooftops-20
9Gategatetown-door, made below-2
10Fixturesbars, pillar, beacon-1
11Groundstreettiles0
12Propsleverdemon1, the lever’s; 3, the demon’s
13Breathbreath4
14Figureswatchmanwatchman5
15Glassnone yet: chapter 12’s
16Marksarrow10

Seventeen, and not fewer, because two nodes on one layer are drawn in the order of their pictures’ ids, not the Hierarchy’s: put the clouds on the sky’s layer and they would be drawn behind it, and the lit windows behind the mountains. A layer holds more than one node only where they never overlap, or are never in one scene.

Now put every node that draws on its layer, by name.

  1. In the town, select each node the table names. In its Sprite, its Tilemap or, for fog, its Particles, click Sort Layer and choose the name in its row: sky Sky, clouds Clouds, and so on to arrow Marks.
  2. Press Ctrl+S. Open scenes/castle.ron and do the same for its five: castle-wall, tiles, demon, breath and watchman. Press Ctrl+S.
Sort Layer, picked by name
A node stores its layer’s place in the list, a number: Sky is 0, Marks 16. Lower draws first. The renderer sorts on the number and never reads the list; the field shows the name at that number, and Custom for a number past the list’s end.
The Layers tab
The project’s sorting layers, back to front, saved in sorting-layers.ron. Renaming a row renames it for every node at that place. Moving or removing a row draws nothing differently: each node keeps its number, and shows whichever name is now there.

Every node’s number changes, the sky’s from -70 to 0 and the arrow’s from 10 to 16, but they keep their order, so nothing moves in the stack: both scenes draw exactly as they did. Until you have picked them all, a node still holds its old number and shows whatever is there: the street’s 0 reads Sky for a while.

The map’s eye

A Viewport draws the world again into a texture of its own, which a sprite or a panel then shows. The view looks from its node: the node is its camera. Put it under the watchman, and it goes where he goes.

  1. With town.ron open, select watchman, press + Add node and choose Viewport. It lands under him. Rename it map-eye and set its Position to 0, -32: 32 above his feet.
  2. In its Viewport, click Texture and choose New render target, the list’s first row. The field then reads map-eye.
  3. Set Size to 96, 96 and Zoom to 0.2. Leave Update at Always, and Subtree and Drawn unticked.
  4. Press the + beside Layers three times, and choose Ground, Props and Figures in the three entries.
  5. Click Clear Colour and, with the picker reading F, set it to 0.04, 0.05, 0.07, alpha 1.
The Inspector of map-eye: Name map-eye, Position 0.0 and -32.0; its ViewportComponent: Texture map-eye, Size 96.0 and 96.0 px, Zoom 0.20, Update Always, Subtree unticked, Layers 3 items, Ground, Props and Figures, each a name in a list with two arrows and a bin, Clear Colour a dark slate, Drawn unticked
The map’s eye: a texture of its own, 96 pixels square, and three layers.
The Viewport’s Texture
The id the view draws into, which a Sprite’s or a Panel’s Texture then shows. New render target, first in the list, gives the view an id of its own, and the field names it by the node. Two views may not share one: Problems says so if they do.
The Viewport’s Size
The texture’s size in pixels: 96 by 96 here. How big it looks on the screen is up to what shows it.
The Viewport’s Zoom
How close it looks, as a Camera’s Zoom does: at 1 a pixel of the texture is a unit of the world, and at 0.2 a pixel holds five units, so 96 pixels see 480 units each way.
Update
How often the view draws into its texture. Always, as it comes, is the map’s; chapter 11 uses the other three.
Always
Draws in every frame, whether or not anything on the screen shows it: the mode for a map of a room things move about in.
Subtree
Unticked, as it comes, the view draws the whole scene, as a camera does. Ticked, it draws only the nodes under its own: chapter 11’s portrait.
Layers
The sorting layers the view draws, one entry each, picked by name; empty, as it comes, draws them all. The map draws Ground, Props and Figures: the stone, the lever and the demon, and him. At the Inspector’s usual width an entry shows its name alone, and the number it stores shows when you hover it.
Clear Colour
What the texture is filled with before the view draws. In F mode it is linear: 0.04, 0.05, 0.07 draws as 56, 63, 75, a slate a little lighter than the night.
Drawn
Whether the view has drawn since this was last unticked. An Always view draws regardless; chapter 11 unticks it from a script to have a picture painted again.

At Zoom 0.2 the view sees 480 by 480 units, centred on map-eye, 32 above his feet: far more than the camera’s 320 by 180, so the map shows what lies past the screen’s edge. Its three layers keep the stone, the lever, the demon and him, and leave out the sky, the planes and the fog.

A panel in the corner

Nothing shows the texture yet. A HUD will: a Canvas over the screen, with a Panel on it that draws the map, and a second panel over that, the frame. art/map-frame.png, a brass ring on a dark riveted plate, is in the starter.

  1. Select town, press + Add node and choose Canvas. It lands under town, last. Rename it hud, and leave its Canvas as it comes: Reference Size 1280 by 720, Scale Mode ScaleWithHeight.
  2. Select hud, press + Add node and choose Panel. Rename it map. In its Rect, set Anchor Min and Anchor Max both to 1, 0; Offset Min to -208, 16; Offset Max to -16, 208; and Pivot to 1, 0.
  3. In its Panel, set Color to 1, 1, 1, alpha 1, click Texture and choose map-eye, the view’s texture. Leave Border at 0.
  4. Select hud again and add another Panel. It lands after map, so it is drawn over it. Rename it map-frame. In its Rect, set Anchor Min and Anchor Max to 1, 0; Offset Min to -224, 0; Offset Max to 0, 224; and Pivot to 1, 0. In its Panel, set Color to 1, 1, 1, alpha 1, and drag art/map-frame.png onto Texture.
  5. Press Ctrl+S.
The editor with map selected: hud last under town, with map and map-frame under it; the Viewport shows the town zoomed out, and in its top right corner the map in its brass frame, a thin blue box round the map with a handle at each corner and the move arrows at its top right; the Inspector shows the PanelComponent, Color white, Texture map-eye, Border 0.00, and the RectComponent, Anchor Min 1.0 and 0.0, Anchor Max 1.0 and 0.0, Offset Min -208.0 and 16.0, Offset Max -16.0 and 208.0, Pivot 1.0 and 0.0
The map’s panel: the view’s texture, 192 square, 16 in from the corner.
The Canvas’s Scale Mode ScaleWithHeight
The canvas is 1280 by 720 units, its Reference Size, scaled to the window’s height: at a window 1080 tall, a unit is 1.5 pixels.
Anchor Min, Anchor Max
The Rect’s two points of the canvas it is held to, as fractions of its width and height: 0, 0 is the top left corner, 1, 1 the bottom right. Both at 1, 0, the panel is held to the top right corner, whatever the window’s width.
Offset Min, Offset Max
The Rect’s top left and bottom right corners, in the canvas’s units from the anchors: -208, 16 and -16, 208 make the map 192 square, 16 in from the corner.
Pivot
The point of the Rect, as fractions of its own size, that counts as its position: 1, 0 is its top right corner.
The Panel’s Color, Texture
Texture is what the panel draws: a picture, or a view’s texture, picked by its node’s name. Color tints it; white leaves it as it is. A new Panel’s is half see-through black.
The game a second in: the watchman at the town’s west end, before the houses, the rooftops and the mountains, the west wall dark at the left; in the top right corner a round brass frame on a dark riveted plate, and through its window a slate disc, with the west wall as a dark column, the street’s stone as a band and him as a red speck on it
The map in the corner: the stone and him, and no sky.

The panel shows the 96-pixel texture at twice its size, 192 square, just as the view drew it, so the Clear Colour’s slate is a disc lighter than the night round it. The frame’s plate is 224 square, in the corner itself, so it hides the map’s square corners, and its window is the map’s round middle. The map draws in every frame, a second pass beside the game’s, into a texture of its own; on a phone, each switch to another texture makes the graphics chip write out its tiles and start again. Chapter 11 has the whole of what a view costs.

The Canvas scales with the window’s height: at 1920 by 1080 the map is 288 square, 24 in from the corner. Under Pixel Perfect the HUD is laid out in the rectangle the game is cropped to: at 1366 by 768, that is 43, 24 to 1323, 744, and the map is 192 square, 16 in from that rectangle’s corner.

The same game at 1366 by 768: the picture whole in the middle with thin dark bars on all four sides, and the map in its brass frame tucked into the picture’s own top right corner, inside the bars
At 1366 by 768: the map in the corner of the picture, not of the window.

The castle’s map

The castle gets the same map: copy the eye and the HUD together, and paste them.

  1. In the town’s Hierarchy, select map-eye, then Ctrl-click hud, and press Ctrl+C.
  2. Open scenes/castle.ron, right-click castle and choose Paste as child. Both land under castle, last.
  3. Drag the pasted map-eye onto watchman. It becomes his child, and keeps its Position of 0, -32.
  4. Press Ctrl+S.

The paste gives the castle’s eye a render target of its own and points the pasted map panel at it, since two views may not share one.

The castle a second in: the watchman where he comes in at the great hall’s west end, a wooden door in a dark frame behind him against the west wall, brick walls and a lantern above; in the top right corner the brass-framed map shows the hall’s floor and walls round him on the slate, and no door
The castle’s map. The door behind him is on Gate, which the map leaves out.

In the town the rig leads him, so the map sees only a little further ahead than the screen. In the castle each room holds the camera, and nothing holds the map. Near the great hall’s east end the picture stops at the hall’s edge, x 640, while the map, 240 east of him, already shows the stair shaft’s ledges and its east wall:

The game in the castle’s great hall: the watchman walks east; the view follows him, then holds still at the hall’s east end while he walks on toward the edge of the picture; the map in the corner, centred on him, shows the stair shaft’s ledges and its wall past the picture’s edge; then the view slides east into the shaft, and its ledges come into the picture
The map past the screen’s edge. Watch the corner: while the hall holds the camera, the map goes on with him and shows the shaft’s ledges before the picture does.

The door back

The gate leads into the castle, and nothing leads back. A door at the great hall’s west end will: the castle tileset’s own wooden door in its teal stone frame, cut out of the sheet as chapter 6 cut the castle’s wall.

  1. In Assets, double-click art/old-dark-castle-interior-tileset.png. In the Sprite sheet tab, under Grid, set Cell to 16 and 16 and Margin to 0 and 0.
  2. Drag from cell 41, 3 to cell 43, 6: Selected 3 x 4. Hovering Name it reads 48x64 at 656, 48. In the Regions band, click the Name box, type door and press Name it.
  3. With castle.ron open, select castle, press + Add node and choose Sprite. It lands under castle, last. Rename it town-door and set its Position to 32, -64.
  4. In its Sprite, drag the tileset onto Texture, click Atlas Region, type door and press Enter. Set Size to 48, 64, Anchor to 0, 0, and Sort Layer to Gate.
  5. Press Add component and choose AreaComponent. In its Shape, set Size to 12, 64 and Offset to 6, 32.
rgs town_door.rgs
/// The way back to the town, through the door at the great hall's west end.
/// The watchman stepping into it goes back out into the street.
component TownDoor : Area {
    fn on_enter(other: NodeId) {
        if in_group(other, "watchman") {
            change_scene("town");
        }
    }
}
  1. Make town_door.rgs with the script above, as in chapter 7: in Assets, click Assets in the path bar, then Create, New script, town_door and Enter, the script in the Code tab, and Ctrl+S.
  2. Select town-door, press Add component and choose TownDoor. Press Ctrl+S.
change_scene("town")
Opens scenes/town.ron in place of this scene, as a scene opens: everything in it as it was saved, so he is at his start and the gate is shut.
town-door selected and framed at 673.2%: a pale box round the wooden door at the great hall’s west end, its planks dark under a lighter top, in a teal stone frame; the watchman stands in front of it; a narrow box runs up its left side, the Area; the Inspector shows Position x 32.0 and y -64.0 and the AreaComponent: Shape Kind Rectangle, Size 12.0 and 64.0, Offset 6.0 and 32.0, Solid unticked
The door, and its Area along its west edge.

The door stands on the floor against the hall’s west wall, x 32 to 80, behind him where he comes in, at x 64, and behind the hall’s stone, which is on Ground. Its Area is the door’s west edge, x 32 to 44: he comes in clear of it, and reaches it only by walking west. Then, within a second, he is in the town. The map does not show the door: Gate is not one of its Layers.

Who moves the camera

Nothing new moves the game’s camera: the rig, every step, and the room holding it. The map has a camera of its own, its node. map-eye goes where he goes, as his child, and no rig and no room move it, which is why it shows what the room keeps off the screen. Naming the layers moved nothing either: the nodes’ numbers keep the order they had.

The layers, the map and the door

SceneNodeComponentFieldValue
projectLayers tabrowsSky to Marks, the seventeen of the table above
town, castleevery node that drawsSprite, Tilemap or ParticlesSort Layerits name in the table above
townmap-eye, under watchmanNodePosition0, -32
ViewportTextureNew render target
Size, Zoom, Update96, 96; 0.2; Always
LayersGround, Props, Figures
Clear Colour0.04, 0.05, 0.07, 1
hud, last under townCanvasas it comes
map, under hudRectAnchor Min, Anchor Max1, 0; 1, 0
Offset Min, Offset Max, Pivot-208, 16; -16, 208; 1, 0
PanelColor, Texture1, 1, 1, 1; map-eye
map-frame, under hud, after mapRectAnchor Min, Anchor Max1, 0; 1, 0
Offset Min, Offset Max, Pivot-224, 0; 0, 224; 1, 0
PanelColor, Texture1, 1, 1, 1; art/map-frame.png
castlemap-eye, hudthe town’s, pasted under castle; map-eye dragged onto watchman
town-door, last under castleNodePosition32, -64
SpriteTexture, Atlas Regionart/old-dark-castle-interior-tileset.png, door
Size, Anchor, Sort Layer48, 64; 0, 0; Gate
AreaSize, Offset12, 64; 6, 32
TownDoorthe script
projectart/old-dark-castle-interior-tileset.pngregiondoor656, 48, 48 by 64

Check it works