Build a GameCreating Pitch Shot

9  Locks and Keys

Goal

Your maps keep the stages in order. A lock waits on each unopened place or stage. Use the arrows or WASD to choose a map card, Enter to open it, and Escape to go back.

The game as it is at the end of this chapter. Click the game, then press Enter to start.

Continue from your completed Chapter 8 project. Arriving here without it? Download Chapter 8’s finished project, unzip it, and open its .mythproj through File > Open Project… in Myth. Your maps are ready for these changes.

If you’d like to compare, here is this chapter’s finished project. Unzip it first. You can also start Chapter 10 from it.

Pitch Shot, Chapter 9 finishedZip of a Myth project · 2.8 MB

To open it, right-click the downloaded file, choose Extract All... and then Extract. Start Myth Engine, choose File › Open Project... and pick the .mythproj file in the new folder. Nunito-OFL.txt beside it comes with the game.

9.1 The Idea

The meadow is open. Beyond it, the beach waits under a lock. Its picture is dim, though you can still see the sea. The game has places left to sing.

Until now, every map card opened. This chapter gives the stages an order: find the call in one, and the next opens. A single star is enough. Sunny Meadow starts open, so there is always somewhere to begin.

Each map part keeps that choice in isOpen, a Boolean in Map Spot. Think of a small sign on a door. The lock shows the sign, but the door itself must read it too. Hiding a lock alone would leave the click free to open everything.

The keys have a separate job. They choose which map card you’re pointing at, even if it’s locked. That card’s number lives in $selectedCard. A ring appears there once you use the keys; $isChoosing remembers that you’ve begun.

The ring and the lock can share a map card. You can look at a place before you can open it.

9.2 The Plan

  • A map part hears placed -> Belong To A Place or Belong To A Stage fills isOpen.
  • isOpen -> the lock, picture, words and stars show whether the map card opens. Open A Place and Open A Stage check it before changing Scenes.
  • Choose With The Keys reads the map’s shape -> changes $selectedCard -> Show The Ring answers the changed Global.
  • A click sends chosen to its own map card. The Open Command sends the same message to the selected card, so both pass through the same isOpen check.

Build the choices first. Then give them their pictures, and finally join them to the keys. Keep testing from Title so each map gets a fresh start.

9.3 Set Up

Set upWhat this chapter adds
ART (sprites, from the starter kit)
Lock Art
Place Ring Art
Stage Ring Art
COMMANDS (Game Settings > Input Manager)
Choose2D Axis
LeftLeft Arrow, A
RightRight Arrow, D
UpUp Arrow, W
DownDown Arrow, S
INPUT CONTEXTS (Game Settings > Input Manager)
MenusInactive at Start(changed)
CommandsOpen, Choose, Back
GLOBAL VARIABLES
$selectedCardNumberstarts at 0
$isChoosingBooleanstarts at false

Lock Art is the little padlock. Place Ring Art and Stage Ring Art fit around their different map cards. The Starter Kit already holds them.

Select Menus in the Input Manager before adding Choose. Choose the 2D Axis type. Give each direction an arrow key and its WASD key. Add Keybinding adds another row; use that row’s direction list to choose which direction the new key belongs to.

Back already belongs to Field and Card. With Menus selected, choose Back from Reuse a Command… below Add Command. Use Add Keybinding to give this context Escape. Now the back arrow and Escape can work on the maps too.

Open any Logic Component and add the two Globals from its Globals card. Leave $selectedCard at 0 and $isChoosing false. Keep your Scenes.

9.4 The Maps Learn What Opens

The first meadow stage needs no star before it. Every other stage looks back to the stars earned by the stage before it.

9.4.1 Map Spot, Changed

Add isOpen to the Map Spot you made in Chapter 8. Every map part carrying Map Spot gets the new field. Pick Yes in its Value list for the card’s true, ready for the Belong Logic to decide.

Data StructureMap SpotAddDelete

What the Logic of one part of a map card shares: its card number on the map (cardIndex, told by whoever made it), its place (on the Place Map) or its stage (on the Stage Map), how many of the place's stars are earned, which of a stage card's stars it is, and whether it is open.

cardIndexNumberdefault 0
placeIndexNumberdefault 0
stageNumberNumberdefault 1
starsEarnedNumberdefault 0
starNumberNumberdefault 1
isOpenBooleandefault true

9.4.2 Belong To A Place, Changed

The beach’s first stage follows the meadow’s last. So the beach asks whether that last stage has a star. Each place asks the same question about the stage before its own first.

Sunny Meadow has no place before it. The If names that exception first, then checks the table for the others. The answer goes into isOpen, beside placeIndex.

Logic ComponentBelong To A PlaceAttach to: Place Card, Place Picture, Place Name, Place Stars, Place LockAddDelete

One part of a place card: from its card number (cardIndex, 0 to 11) it keeps its place in placeIndex, and whether the place is open in isOpen (its first stage is open: it is stage 1, or the stage before it has a star). It reads cardIndex (its Map Spot), set by Lay Out The Places (the card) or Lay Out A Place Card (its other parts), when it makes the part.

Attach toAny Object
DATA STRUCTURES
Map Spotself.mapSpot
On Placed
WhenplacedCustom Event
1Declare Variable
Name
rowBefore
Value
0
2Change Component Value
Component Value
self.mapSpot.placeIndex
Value
self.mapSpot.cardIndex
3Change Variable
Variable
rowBefore
Value
self.mapSpot.placeIndex * $stagesPerPlace - 1
4Ifself.mapSpot.placeIndex == 0 || data("Stages", rowBefore, "stars") > 0
Then
5Change Component Value
Component Value
self.mapSpot.isOpen
Value
true
6Otherwise
7Change Component Value
Component Value
self.mapSpot.isOpen
Value
false

rowBefore is a Declare Variable, kept only while this part finds its place. Its row is one less than the place’s first stage row. Keep the new If after the placeIndex assignment, on the Event’s main line.

9.4.3 Belong To A Stage, Changed

A stage looks back too. Stage 1 opens without asking the table. Every other stage reads the preceding stage’s stars and keeps the result in isOpen.

Logic ComponentBelong To A StageAttach to: Stage Card, Stage Number, Stage Name, Stage Star, Stage LockAddDelete

One part of a stage card: from its card number (cardIndex, 0 to 9) its stage is cardIndex + 1 of the place shown, kept in stageNumber, and whether it is open, in isOpen. It reads cardIndex (its Map Spot), set by Lay Out The Stages (the card) or Lay Out A Stage Card (its other parts), when it makes the part.

Attach toAny Object
DATA STRUCTURES
Map Spotself.mapSpot
On Placed
WhenplacedCustom Event
1Declare Variable
Name
firstStage
Value
1
2Change Variable
Variable
firstStage
Value
floor(($stage - 1) / $stagesPerPlace) * $stagesPerPlace + 1
3Change Component Value
Component Value
self.mapSpot.stageNumber
Value
firstStage + self.mapSpot.cardIndex
4Ifself.mapSpot.stageNumber == 1 || data("Stages", self.mapSpot.stageNumber - 2, "stars") > 0
Then
5Change Component Value
Component Value
self.mapSpot.isOpen
Value
true
6Otherwise
7Change Component Value
Component Value
self.mapSpot.isOpen
Value
false

The subtraction looks further back than you might expect. A stage number starts at 1, and its table row starts at 0. The preceding stage takes another step. That’s why the card subtracts 2.

9.4.4 Open A Place, Changed

Click a locked beach, and the map should stay put. Open A Place now checks the sign before it opens the door.

A click and the Open Command meet in chosen, sent to this map card itself. Only the selected card answers Open. On Chosen checks isOpen before any click sound or Scene change.

Rebuild the whole On Placed If. Its outer Otherwise needs rebuilding too, even though the card leaves it unmarked. Read the branch explanation below before changing the card.

Logic ComponentOpen A PlaceAttach to: Place CardAddDelete

One place card: highlighted when the stage to play next ($nextStage) is in its place, dim when the place is locked; clicking an open card opens the place's Stage Map. It reads cardIndex, placeIndex and isOpen (its Map Spot), set by Belong To A Place, attached first (cardIndex by Lay Out The Places, when it makes the card).

Attach toAny Object
DATA STRUCTURES
Map Spotself.mapSpot
SHARED VARIABLES
NameTypeKindStarting Value
fadeSecondsNumberConstant0.25
On Placed
WhenplacedCustom Event
1Iffloor(($nextStage - 1) / $stagesPerPlace) == self.mapSpot.placeIndex
Then
2Set Frame
Frame
1
1Ifself.mapSpot.isOpen == true
Then
2Iffloor(($nextStage - 1) / $stagesPerPlace) == self.mapSpot.placeIndex
Then
3Change Variable
Variable
$selectedCard
Value
self.mapSpot.cardIndex
4Set Frame
Frame
1
5Otherwise
6Set Frame
Frame
0
7Otherwise
8Set Frame
Frame
2
Frame
0
When Left Is Clicked
WhenMouse Pressed on ObjectMouse button: left
1Control Sound
Sound
Sound Click
2Change Variable
Variable
$stage
Value
self.mapSpot.placeIndex * $stagesPerPlace + 1
3Go to Scene
Scene
Stage Map
Transition
Fade
Transition Seconds
@self.fadeSeconds
1Trigger Custom Event on Object
Custom Event
chosen
When Open Is Pressed
WhenCommand PressedCommand: Open
1Ifself.mapSpot.cardIndex == $selectedCard
Then
2Trigger Custom Event on Object
Custom Event
chosen
On Chosen
WhenchosenCustom Event
1Ifself.mapSpot.isOpen == true
Then
2Control Sound
Sound
Sound Click
3Change Variable
Variable
$stage
Value
self.mapSpot.placeIndex * $stagesPerPlace + 1
4Go to Scene
Scene
Stage Map
Transition
Fade
Transition Seconds
@self.fadeSeconds

The red Scene-changing Actions leave When Left Is Clicked. Its green replacement sends chosen. Make the new On Chosen Event, then build its If and Actions there. Those values are familiar, but their home has changed.

On Placed now uses the art’s third frame too: Frame 2 is the dim, locked card. Frame 0 stays plain, and Frame 1 marks the next stage’s place.

For this Event, remove the old If and its whole branches. Rebuild On Placed from the new steps on the card, including the unmarked outer Otherwise and its Set Frame. Keep that outer Else’s Frame at 2. Inside the open branch, the smaller If chooses the highlighted frame and sets $selectedCard. Its Else uses Frame 0.

The keys will begin at the highlighted card, even while the ring is hidden.

9.4.5 Open A Stage, Changed

The stage door works the same way. A click or Open asks chosen, and chosen checks whether the stage can open. Both ways now respect the same lock.

Rebuild this On Placed If too, including the unmarked outer Otherwise. Its Frame 2 belongs to the locked stage.

Logic ComponentOpen A StageAttach to: Stage CardAddDelete

A stage card: highlighted when it is the stage to play next; clicking it starts that stage. It reads cardIndex, stageNumber and isOpen (its Map Spot), set by Belong To A Stage, attached first (cardIndex by Lay Out The Stages, when it makes the card).

Attach toAny Object
DATA STRUCTURES
Map Spotself.mapSpot
SHARED VARIABLES
NameTypeKindStarting Value
fadeSecondsNumberConstant0.25
On Placed
WhenplacedCustom Event
1Ifself.mapSpot.stageNumber == $nextStage
Then
2Set Frame
Frame
1
1Ifself.mapSpot.isOpen == true
Then
2Ifself.mapSpot.stageNumber == $nextStage
Then
3Change Variable
Variable
$selectedCard
Value
self.mapSpot.cardIndex
4Set Frame
Frame
1
5Otherwise
6Set Frame
Frame
0
7Otherwise
8Set Frame
Frame
2
Frame
0
When Left Is Clicked
WhenMouse Pressed on ObjectMouse button: left
1Control Sound
Sound
Sound Click
2Change Variable
Variable
$stage
Value
self.mapSpot.stageNumber
3Go to Scene
Scene
Field
Transition
Fade
Transition Seconds
@self.fadeSeconds
1Trigger Custom Event on Object
Custom Event
chosen
When Open Is Pressed
WhenCommand PressedCommand: Open
1Ifself.mapSpot.cardIndex == $selectedCard
Then
2Trigger Custom Event on Object
Custom Event
chosen
On Chosen
WhenchosenCustom Event
1Ifself.mapSpot.isOpen == true
Then
2Control Sound
Sound
Sound Click
3Change Variable
Variable
$stage
Value
self.mapSpot.stageNumber
4Go to Scene
Scene
Field
Transition
Fade
Transition Seconds
@self.fadeSeconds

Rebuild this On Placed the same way: remove its old If with both branches, then build the new outer and inner Ifs. Include the unmarked outer Otherwise, with Set Frame 2. Replace the click’s old Actions with the message that sends the choice back to this map card. Build the new On Chosen Event below. Keep Belong To A Stage first on Stage Card, so isOpen is ready before Open A Stage reads it.

Run from Title now. Click the beach: it stays closed, though its padlock isn’t there yet. Sunny Meadow still opens. The doors read their signs before their locks arrive.

9.5 A Lock You Can See

The beach fades behind its padlock. On Stage Map, unopened stages lose their stars and their words grow pale.

9.5.1 Show A Lock

Every map card will make a lock, including the open ones. Show A Lock decides which locks remain visible. Both maps share it.

Logic ComponentShow A LockAttach to: Place Lock, Stage Lock

A lock on a card: shown only when its place or stage is locked. It reads isOpen (its Map Spot), set by Belong To A Place or Belong To A Stage, attached first.

Attach toAny Object
DATA STRUCTURES
Map Spotself.mapSpot
On Placed
WhenplacedCustom Event
1Ifself.mapSpot.isOpen == false
Then
2Set Visible
Visible
Yes
3Otherwise
4Set Visible
Visible
No

It waits for placed, when the lock has its card number. The Belong Logic must come first on the lock’s Object, to fill isOpen before Show A Lock reads it.

9.5.2 Place Lock and Stage Lock

The place’s lock sits over its picture. The smaller stage lock sits where the stars would be. Their Draw Orders put them in front of their map cards.

ObjectPlace Lock
Transform
Bounding Box > SizeX 0.64, Y 0.72
Sprite
Scene Depth Draw Order13
SpriteLock Art
Transform > SizeX 0.64, Y 0.72
Data Structure
From LogicBelong To A Place, Show A Lock
Data StructureMap Spot
Logic
Belong To A Place
Show A Lock
ObjectStage Lock
Transform
Bounding Box > SizeX 0.42, Y 0.48
Sprite
Scene Depth Draw Order13
SpriteLock Art
Transform > SizeX 0.42, Y 0.48
Data Structure
From LogicShow A Lock, Belong To A Stage
Data StructureMap Spot
Logic
Belong To A Stage
Show A Lock

Start with Empty Objects. Each needs a Sprite. Attach each Belong Logic first, then Show A Lock. Stage Lock’s From Logic names are listed the other way round; that line doesn’t set attachment order. Map Spot comes with them. Leave both Objects out of the Scenes; their makers come later.

9.5.3 Show The Place Picture, Changed

You can still see a locked place’s painting. It grows faint under the lock, so the beach remains a place to look forward to.

Logic ComponentShow The Place PictureAttach to: Place PictureAddDelete

The picture of one place on its card (frame n is place n), dimmed when the place is locked. It reads placeIndex and isOpen (its Map Spot), set by Belong To A Place, attached first.

Attach toAny Object
DATA STRUCTURES
Map Spotself.mapSpot
SHARED VARIABLES
NameTypeKindStarting Value
lockedAlphaNumberConstant0.55
On Placed
WhenplacedCustom Event
1Set Frame
Frame
self.mapSpot.placeIndex
2Ifself.mapSpot.isOpen == false
Then
3Set Alpha
Alpha
@self.lockedAlpha

Set Alpha changes how solid the picture looks. An Alpha of 1 is fully visible; lockedAlpha is 0.55, leaving the painting a little over half strength. Its new If follows Set Frame.

Place Picture already carries Belong To A Place first. Keep that order. The changed Logic brings lockedAlpha’s default to Place Picture. Leave that Object value alone.

9.5.4 Dim When Locked

A locked stage keeps its number and name. You can read where you’re going, but the paler words set it apart from an open stage.

Logic ComponentDim When LockedAttach to: Stage Number, Stage Name

A part of a locked stage's card is dimmed to lockedAlpha. It reads isOpen (its Map Spot), set by Belong To A Stage, attached first.

Attach toAny Object
DATA STRUCTURES
Map Spotself.mapSpot
SHARED VARIABLES
NameTypeKindStarting Value
lockedAlphaNumberConstant0.5
On Placed
WhenplacedCustom Event
1Ifself.mapSpot.isOpen == false
Then
2Set Alpha
Alpha
@self.lockedAlpha

This is the same Set Alpha idea, shared by both text Objects. lockedAlpha starts at 0.5, half strength.

9.5.5 Stage Number and Stage Name, Changed

Attach Dim When Locked after Belong To A Stage on both Objects. Their Map Spot is already there. The From Logic line grows by itself when you attach the new Logic.

ObjectStage NumberAddDelete
Transform
Presentation > SpaceWindow / UI
Presentation > Render LayerUI
Bounding Box > SizeX 200, Y 64
Text / UI
Text{stageNumber}
FontNunito
Font Size56
EmphasisExtra Bold
Color#3A1D0B
AlignmentCenter
RenderingVector
Data Structure
From LogicBelong To A Stage, Dim When Locked
From LogicBelong To A Stage
Data StructureMap Spot
Logic
Belong To A Stage
Dim When Locked
ObjectStage NameAddDelete
Transform
Presentation > SpaceWindow / UI
Presentation > Render LayerUI
Bounding Box > SizeX 310, Y 34
Text / UI
Text{data("Stages", stageNumber - 1, "name")}
FontNunito
Font Size22
EmphasisExtra Bold
Color#3A1D0B
AlignmentCenter
RenderingVector
Data Structure
From LogicBelong To A Stage, Dim When Locked
From LogicBelong To A Stage
Data StructureMap Spot
Logic
Belong To A Stage
Dim When Locked

9.5.6 Light A Stage Star, Changed

An unopened stage has a lock where its stars would sit. Its stars hide. Open stages still show their earned stars as before.

Logic ComponentLight A Stage StarAttach to: Stage StarAddDelete

One of the three stars on a stage card (its starNumber, 1 to 3, told by the card that made it): lit when the stage has earned at least that many stars. It reads stageNumber, starNumber and isOpen (its Map Spot), set by Belong To A Stage, attached first (starNumber by Lay Out A Stage Card, when it makes the star).

Attach toAny Object
DATA STRUCTURES
Map Spotself.mapSpot
On Placed
WhenplacedCustom Event
1Ifself.mapSpot.isOpen == false
Then
2Set Visible
Visible
No
3Ifdata("Stages", self.mapSpot.stageNumber - 1, "stars") >= self.mapSpot.starNumber
Then
4Set Frame
Frame
1
5Otherwise
6Set Frame
Frame
0

The new If goes before the old star-lighting If, on the main line. The old If still chooses each star’s frame, even when that star is hidden. Keep Stage Star’s Logic order.

The locks are ready. Their makers will put them on the maps after the rings are ready too.

9.6 A Ring That Follows Your Keys

Press an arrow, and a ring appears around one map card. Press again, and it steps to the next. Each ring stays where its own map card made it, waiting for the selection to reach it.

9.6.1 Map Grid

The keyboard needs to know where a row ends. Map Grid keeps that shape on each Director: how many map cards there are, and how many fit across.

Data StructureMap Grid

What a map's Director shares: how many cards the map has (cardCount) and how many to a row (cardsInARow), kept by the Logic that lays the cards out.

cardCountNumberdefault 1
cardsInARowNumberdefault 1

Make this Data Structure before adding it to the following Logic. The keys read what the layout writes. Each Director gets its own copy, because the maps have different shapes.

9.6.2 Lay Out The Places and Lay Out The Stages, Changed

The layouts know their shape already. Now each writes those values into Map Grid before making its cards. That shape guides the keys.

Logic ComponentLay Out The PlacesAttach to: Places DirectorAddDelete

When the Place Map is made, lays out a card for each place (each row of the Places table): columns cards to a row from the top left, each told its number (cardIndex). The Map Grid keeps how many cards there are and how many to a row, for the keys.

Attach toAny Object
DATA STRUCTURES
Map Gridself.mapGrid
SHARED VARIABLES
NameTypeKindStarting Value
placeCardObjectConstantNone
columnsNumberConstant6
firstCardXNumberConstant1.85
firstCardYNumberConstant7.35
acrossNumberConstant3.1
downNumberConstant3.1
When Created
WhenCreate
1Declare Variable
Name
cardX
Value
0
2Declare Variable
Name
cardY
Value
0
3Change Component Value
Component Value
self.mapGrid.cardCount
Value
dataCount("Places")
4Change Component Value
Component Value
self.mapGrid.cardsInARow
Value
@self.columns
5RepeatdataCount("Places")times
Each time
6Change Variable
Variable
cardX
Value
@self.firstCardX + mod(local.index, @self.columns) * @self.across
7Change Variable
Variable
cardY
Value
@self.firstCardY - floor(local.index / @self.columns) * @self.down
8Create Instance
Object to Create
@self.placeCard
X
cardX
Y
cardY
Variable Name
newCard
9Change Variable
Variable
newCard.cardIndex
Value
local.index
10Trigger Custom Event on Object
Applies to
newCard
Custom Event
placed
Logic ComponentLay Out The StagesAttach to: Stages DirectorAddDelete

When the Stage Map is made, lays out a card for each stage of the place shown: columns cards to a row from the top left, each told its number (cardIndex). The Map Grid keeps how many cards there are and how many to a row, for the keys.

Attach toAny Object
DATA STRUCTURES
Map Gridself.mapGrid
SHARED VARIABLES
NameTypeKindStarting Value
stageCardObjectConstantNone
columnsNumberConstant5
firstCardXNumberConstant2.4
firstCardYNumberConstant6.9
acrossNumberConstant3.6
downNumberConstant2.6
When Created
WhenCreate
1Declare Variable
Name
cardX
Value
0
2Declare Variable
Name
cardY
Value
0
3Change Component Value
Component Value
self.mapGrid.cardCount
Value
$stagesPerPlace
4Change Component Value
Component Value
self.mapGrid.cardsInARow
Value
@self.columns
5Repeat$stagesPerPlacetimes
Each time
6Change Variable
Variable
cardX
Value
@self.firstCardX + mod(local.index, @self.columns) * @self.across
7Change Variable
Variable
cardY
Value
@self.firstCardY - floor(local.index / @self.columns) * @self.down
8Create Instance
Object to Create
@self.stageCard
X
cardX
Y
cardY
Variable Name
newCard
9Change Variable
Variable
newCard.cardIndex
Value
local.index
10Trigger Custom Event on Object
Applies to
newCard
Custom Event
placed

Add Map Grid from each Logic canvas’s Data Structures card. The two new Change Component Values go after the Declare Variables and before the Repeat. The old layout sums stay as they are.

9.6.3 Choose With The Keys

Left and Right step along the map’s list, stopping at its ends. Up and Down step a whole row when another row exists. Choose With The Keys reads Map Grid for both maps, so it needs no place-specific version.

Logic ComponentChoose With The KeysAttach to: Places Director, Stages Director

The arrow keys (or W A S D, the Choose Command) move the selection one card at a time on a map of cards in rows; the selection ring shows from the first key press. It reads cardCount and cardsInARow (its Map Grid), set by Lay Out The Places or Lay Out The Stages, on the same Director, when the map is made.

Attach toAny Object
DATA STRUCTURES
Map Gridself.mapGrid
When the Scene Starts
WhenScene Start
1Change Variable
Variable
$selectedCard
Value
0
2Change Variable
Variable
$isChoosing
Value
false
When Choose Left Is Pressed
When2D Direction PressedCommand: ChooseDirection: Left
1Change Variable
Variable
$selectedCard
Value
max(0, $selectedCard - 1)
2Trigger Custom Event on Object
Custom Event
moved
When Choose Right Is Pressed
When2D Direction PressedCommand: ChooseDirection: Right
1Change Variable
Variable
$selectedCard
Value
min(self.mapGrid.cardCount - 1, $selectedCard + 1)
2Trigger Custom Event on Object
Custom Event
moved
When Choose Up Is Pressed
When2D Direction PressedCommand: ChooseDirection: Up
1If$selectedCard >= self.mapGrid.cardsInARow
Then
2Change Variable
Variable
$selectedCard
Operator
-=
Value
self.mapGrid.cardsInARow
3Trigger Custom Event on Object
Custom Event
moved
When Choose Down Is Pressed
When2D Direction PressedCommand: ChooseDirection: Down
1If($selectedCard + self.mapGrid.cardsInARow) < self.mapGrid.cardCount
Then
2Change Variable
Variable
$selectedCard
Operator
+=
Value
self.mapGrid.cardsInARow
3Trigger Custom Event on Object
Custom Event
moved
On Moved
WhenmovedCustom Event
1Change Variable
Variable
$isChoosing
Value
true
2Control Sound
Sound
Sound Click

Use 2D Direction Pressed for the four direction Events. Each chooses the Choose Command and its own Direction. A held key gives one step per press here, as the Event’s name says.

Each direction sends moved to its own Director. On Moved makes $isChoosing true and plays the click. Up and Down send moved after their If, on the main line. A press can reveal the ring even when the selection has reached the edge and cannot step further.

Scene Start clears the old choice before any cards are made. The highlighted card then supplies the new selection when placed arrives. Nothing resets it after that.

9.6.4 The Directors, Changed

Attach Choose With The Keys to both Directors. To match the card’s order, choose Logic from the Object Editor Mode list above the preview. Focus the grip beside Choose With The Keys, then press Alt+Up to move it above the layout. Keep its other Logic attached; moving a row keeps the layout’s Object choices. Choose With The Keys and the layout share Map Grid on that Director.

ObjectPlaces DirectorAddDelete
Data Structure
From LogicChoose With The Keys, Lay Out The Places
Data StructureMap Grid
Logic
Play The Title Tune
Choose The Next Stage
Choose With The Keys
Lay Out The Places
Shared Variables
placeCardPlace Card
ObjectStages DirectorAddDelete
Data Structure
From LogicChoose With The Keys, Lay Out The Stages
Data StructureMap Grid
Logic
Play The Title Tune
Choose The Next Stage
Choose With The Keys
Lay Out The Stages
Shared Variables
stageCardStage Card

The existing placements stay. On Stages Director’s placement, Per Instance Variables still has Select It set to No. That’s Choose The Next Stage’s selectIt: No keeps the place you clicked.

9.6.5 Show The Ring

Each map card gets its own ring. They all stay still. When the choice changes, one shows and the others hide, so your eye sees a ring moving across the map.

Logic ComponentShow The RingAttach to: Place Ring, Stage Ring

The selection ring of one card: shown on the selected card ($selectedCard) once the keys are used ($isChoosing). It reads cardIndex (its Map Spot), set by Lay Out A Place Card or Lay Out A Stage Card, when the card makes the ring.

Attach toAny Object
DATA STRUCTURES
Map Spotself.mapSpot
When Created
WhenCreate
1Set Visible
Visible
No
On Variable Changed · Selected Card
WhenVariable ChangedGlobal Variable: selectedCard
1Trigger Custom Event on Object
Custom Event
placeRing
On Variable Changed · Is Choosing
WhenVariable ChangedGlobal Variable: isChoosing
1Trigger Custom Event on Object
Custom Event
placeRing
On Place Ring
WhenplaceRingCustom Event
1If$isChoosing == true && self.mapSpot.cardIndex == $selectedCard
Then
2Set Visible
Visible
Yes
3Otherwise
4Set Visible
Visible
No

The two Variable Changed Events watch Globals. Pick selectedCard for one and isChoosing for the other. Both send placeRing to their own Object, which checks whether this is the selected ring.

Why watch isChoosing too? Press Left at the first map card, and selectedCard stays put. The first key still needs to reveal the ring. isChoosing changes even when the number doesn’t.

The Create Event hides the ring before any key is pressed. There’s no Step Event. The changed Globals call the rings when they’re needed.

9.6.6 Place Ring and Stage Ring

Both rings use Show The Ring. Their Sprites fit the different map cards, with Draw Order in front of everything else.

ObjectPlace Ring
Transform
Bounding Box > SizeX 3.06, Y 2.84
Sprite
Scene Depth Draw Order14
SpritePlace Ring Art
Transform > SizeX 3.06, Y 2.84
Data Structure
From LogicShow The Ring
Data StructureMap Spot
Logic
Show The Ring
ObjectStage Ring
Transform
Bounding Box > SizeX 3.5, Y 2.18
Sprite
Scene Depth Draw Order14
SpriteStage Ring Art
Transform > SizeX 3.5, Y 2.18
Data Structure
From LogicShow The Ring
Data StructureMap Spot
Logic
Show The Ring

Map Spot comes from Show The Ring. These Objects need no Belong Logic: their own cardIndex is enough to compare with $selectedCard.

The rings stay unplaced too. Now each map card can make its new parts.

9.7 The Map Cards Put It Together

The makers return to familiar work: make a part, give it a number, then announce placed. You’ve built that pattern before.

9.7.1 Lay Out A Place Card, Changed

The place maker adds a lock over the picture and a ring around the whole map card. Both receive the same cardIndex as the other parts. pictureAbove places the lock.

Look for newLock and newRing. Each new group makes its Object, gives it cardIndex, then sends placed. The familiar parts stay.

Logic ComponentLay Out A Place CardAttach to: Place CardAddDelete

When the card is placed, makes the rest of it around its middle: the place's picture, its name, a star and the count of its stars, its lock and its keyboard ring, each told the card's number. It reads cardIndex (its Map Spot), set by Lay Out The Places, when it makes the card.

Attach toAny Object
DATA STRUCTURES
Map Spotself.mapSpot
SHARED VARIABLES
NameTypeKindStarting Value
placePictureObjectConstantNone
placeLockObjectConstantNone
placeRingObjectConstantNone
placeNameObjectConstantNone
placeStarObjectConstantNone
placeStarsObjectConstantNone
pictureAboveNumberConstant0.44
nameBelowNumberConstant0.62
starsBelowNumberConstant1.04
starLeftNumberConstant0.4
countRightNumberConstant0.5
On Placed
WhenplacedCustom Event
1Create Instance
Object to Create
@self.placePicture
X
self.transform.position.x
Y
self.transform.position.y + @self.pictureAbove
Variable Name
newPicture
2Change Variable
Variable
newPicture.cardIndex
Value
self.mapSpot.cardIndex
3Trigger Custom Event on Object
Applies to
newPicture
Custom Event
placed
4Create Instance
Object to Create
@self.placeLock
X
self.transform.position.x
Y
self.transform.position.y + @self.pictureAbove
Variable Name
newLock
5Change Variable
Variable
newLock.cardIndex
Value
self.mapSpot.cardIndex
6Trigger Custom Event on Object
Applies to
newLock
Custom Event
placed
7Create Instance
Object to Create
@self.placeRing
X
self.transform.position.x
Y
self.transform.position.y
Variable Name
newRing
8Change Variable
Variable
newRing.cardIndex
Value
self.mapSpot.cardIndex
9Trigger Custom Event on Object
Applies to
newRing
Custom Event
placed
10Create Instance
Object to Create
@self.placeName
X
0
Y
0
Variable Name
newName
11Set Position
Applies to
newName
X
self.transform.position.x
Y
self.transform.position.y - @self.nameBelow
12Change Variable
Variable
newName.cardIndex
Value
self.mapSpot.cardIndex
13Trigger Custom Event on Object
Applies to
newName
Custom Event
placed
14Create Instance
Object to Create
@self.placeStar
X
self.transform.position.x - @self.starLeft
Y
self.transform.position.y - @self.starsBelow
Variable Name
newStar
15Create Instance
Object to Create
@self.placeStars
X
0
Y
0
Variable Name
newStarCount
16Set Position
Applies to
newStarCount
X
self.transform.position.x + @self.countRight
Y
self.transform.position.y - @self.starsBelow
17Change Variable
Variable
newStarCount.cardIndex
Value
self.mapSpot.cardIndex
18Trigger Custom Event on Object
Applies to
newStarCount
Custom Event
placed

Add the two new Object Shared Variables and their Action groups. The ring’s placed message has no listener; the maker gives every part the same announcement. Show The Ring waits for the Globals to change. Its number is ready when that happens.

9.7.2 Place Card, Changed

Under Variables on Place Card, choose Place Lock for placeLock and Place Ring for placeRing. Keep its other Object choices and its Logic order.

ObjectPlace CardAddDelete
Transform
Bounding Box > SizeX 2.86, Y 2.68
Sprite
Scene Depth Draw Order10
SpritePlace Card Art
Transform > SizeX 2.86, Y 2.68
Data Structure
From LogicBelong To A Place, Open A Place, Lay Out A Place Card
Data StructureMap Spot
Logic
Belong To A Place
Open A Place
Lay Out A Place Card
Shared Variables
placePicturePlace Picture
placeLockPlace Lock
placeRingPlace Ring
placeNamePlace Name
placeStarPlace Star
placeStarsPlace Stars

9.7.3 Lay Out A Stage Card, Changed

The stage maker puts its lock beside the stars and its ring around the map card. Each gets cardIndex before placed. The Repeat still gives every star its separate starNumber, as in Chapter 8.

Here too, look for newLock and newRing. The number, name and star-making Repeat keep their places around these new groups.

Logic ComponentLay Out A Stage CardAttach to: Stage CardAddDelete

When the card is placed, makes the rest of it around its middle: the stage's number and name, its three stars, its lock and its keyboard ring, each told the card's number (and each star which it is). It reads cardIndex and starNumber (its Map Spot), set by Lay Out The Stages, when it makes the card.

Attach toAny Object
DATA STRUCTURES
Map Spotself.mapSpot
SHARED VARIABLES
NameTypeKindStarting Value
numberLabelObjectConstantNone
nameLabelObjectConstantNone
stageStarObjectConstantNone
stageLockObjectConstantNone
stageRingObjectConstantNone
numberAboveNumberConstant0.46
nameBelowNumberConstant0.66
starsBelowNumberConstant0.14
starSpacingNumberConstant0.44
On Placed
WhenplacedCustom Event
1Create Instance
Object to Create
@self.numberLabel
X
0
Y
0
Variable Name
newNumber
2Set Position
Applies to
newNumber
X
self.transform.position.x
Y
self.transform.position.y + @self.numberAbove
3Change Variable
Variable
newNumber.cardIndex
Value
self.mapSpot.cardIndex
4Trigger Custom Event on Object
Applies to
newNumber
Custom Event
placed
5Create Instance
Object to Create
@self.nameLabel
X
0
Y
0
Variable Name
newName
6Set Position
Applies to
newName
X
self.transform.position.x
Y
self.transform.position.y - @self.nameBelow
7Change Variable
Variable
newName.cardIndex
Value
self.mapSpot.cardIndex
8Trigger Custom Event on Object
Applies to
newName
Custom Event
placed
9Create Instance
Object to Create
@self.stageLock
X
self.transform.position.x
Y
self.transform.position.y - @self.starsBelow
Variable Name
newLock
10Change Variable
Variable
newLock.cardIndex
Value
self.mapSpot.cardIndex
11Trigger Custom Event on Object
Applies to
newLock
Custom Event
placed
12Create Instance
Object to Create
@self.stageRing
X
self.transform.position.x
Y
self.transform.position.y
Variable Name
newRing
13Change Variable
Variable
newRing.cardIndex
Value
self.mapSpot.cardIndex
14Trigger Custom Event on Object
Applies to
newRing
Custom Event
placed
15Repeat3times
Each time
16Create Instance
Object to Create
@self.stageStar
X
self.transform.position.x + (local.index - 1) * @self.starSpacing
Y
self.transform.position.y - @self.starsBelow
Variable Name
newStar
17Change Variable
Variable
newStar.cardIndex
Value
self.mapSpot.cardIndex
18Change Variable
Variable
newStar.starNumber
Value
local.index + 1
19Trigger Custom Event on Object
Applies to
newStar
Custom Event
placed

The two new groups belong before the star-making Repeat, on the Event’s main line. These groups belong to the whole map card. Its Repeat supplies starNumber to each star, as in Chapter 8, while Lay Out The Stages supplies the parent’s cardIndex. The Description mixes those jobs. You may describe them in your own words; that text doesn’t run.

9.7.4 Stage Card, Changed

Pick Stage Lock and Stage Ring in Stage Card’s new Object Variables. Keep Belong To A Stage first, followed by Open A Stage and Lay Out A Stage Card.

ObjectStage CardAddDelete
Transform
Bounding Box > SizeX 3.3, Y 2.02
Sprite
Scene Depth Draw Order10
SpriteStage Card Art
Transform > SizeX 3.3, Y 2.02
Data Structure
From LogicBelong To A Stage, Open A Stage, Lay Out A Stage Card
Data StructureMap Spot
Logic
Belong To A Stage
Open A Stage
Lay Out A Stage Card
Shared Variables
numberLabelStage Number
nameLabelStage Name
stageStarStage Star
stageLockStage Lock
stageRingStage Ring

Run from Title. Sunny Meadow is bright, and the other places have locks. Press Right. A ring appears on the beach, but Enter leaves you on the map. Press Left and Enter. The meadow’s stages appear, with their own locks and an open first stage waiting for you.

The ring can visit every door. Only an open door lets you through.

Play it!

Watch how the ring can choose a locked place without opening it, and how the stars open the next stage.

  • Start a fresh game and press Play. Sunny Meadow opens; the other places show locks over dim pictures. Clicking a locked place leaves the map showing.
  • The ring starts hidden. Press Left at Sunny Meadow. The ring appears even though the choice stays on the first card.
  • Press Right, then Enter or Space, on the locked beach. Menus’ Open uses both keys. The beach stays closed, waiting for the meadow’s last stage to earn its first star.
  • Press Left and Enter. Stage Map opens with stage 1 highlighted and the later stages locked. Locked stages have pale words and no stars showing.
  • Move Right and Left by one card. Down reaches the next row, and Up returns to the row you started from. At the map’s first and last cards, Left and Right stop. WASD does the same work.
  • Open stage 1 and find its call. After the win card appears, use Escape to return to Stage Map and look at the next stage. Your stars show, stage 2 opens, and later stages stay locked.
  • Escape returns from Field to Stage Map, then Place Map, then Title. The on-screen back arrows still work.
How it works

The Belong Logic fills isOpen. The display and the click both read that answer, so the lock and the door agree. The layout writes Map Grid, and the keys use that shape to choose a card. The rings answer changed Globals.

The maps separate a choice from permission to open it. You can point at a locked place and see it waiting. Finding the preceding call changes the stars, and the next map reads them again.

9.8 If It Didn’t Work

Watch which half goes missing: the lock, or the choice. One tells you whether a door opens; the other tells you which door you’re asking.

The beach opens while its lock is showing? Look at On Chosen. Its Scene change belongs inside the isOpen If. Move it there, and the lock and the click agree again.

A lock shows on Sunny Meadow? Look at Place Lock’s Logic order. Belong To A Place must run before Show A Lock. The lock needs the answer before it can show it.

Stage 1 stays locked? Look at Belong To A Stage’s If. Its first condition opens stage 1 without asking for a preceding star. Restore that condition, and there’s somewhere to begin.

The keys do nothing? Is Choose in Menus, with its directional keybindings? Do both Directors carry Choose With The Keys? The Field’s Aim Command has its own keys; the maps need Choose.

Up or Down steps the wrong distance? Look at the layout’s two Map Grid assignments. cardsInARow takes columns, and cardCount takes the map’s count. The keys read these values from the same Director.

The first key leaves the ring hidden, though the second makes it appear? Check Show The Ring’s Variable Changed Event for isChoosing. That change reveals the ring when the selected number stays put.

Every ring appears on the first card? Look at the makers’ newRing.cardIndex, before placed. Each ring needs the number of the map card that made it.

Escape leaves a map open? Select Menus and reuse Back there, with Escape as its keybinding. Keep Field and Card’s bindings too, so Escape continues to work while aiming and after a win.

Make one change, run from Title, and watch that moment again. The Goal’s catch-up project has the whole map if you’d like to compare.

Challenge

Make a map whose shape feels different under your keys. Change Lay Out The Places’ columns, across and down together, and see how the rows and arrow movements follow. Or change lockedAlpha on Stage Name to keep a locked name more visible. Which parts would you want to read before reaching a place? Restore the card’s values before Chapter 10.

Still stuck? Search the manual, or ask in the Myth Engine Discord (opens a new tab).

The meadow opens first, and the beach waits its turn. Next, the game will remember the stars after its window closes.