- Learn
- Build a Game
- Pitch Shot
- Appendices
- A Logic Reference
Appendix A — Logic Reference
Every Logic Component and Function in Pitch Shot, as it is in the finished game. Each entry stands on its own: read what it does, see what it needs, and build it from its card into your own game. A card’s Shared Variables and Per Instance Variables are the values you can change. A Shared Variable holds one value for the whole Object, under Variables in its Properties. A Per Instance Variable holds one for each placement in the Scene.
A.1 Backdrop Of The Place
Built in Chapter 1, A Stage Stands.
Shows the backdrop of the place of the stage being played: the Sprite its row of the Places table names.
Any Object- Name
placeRow- Value
0
- Variable
placeRow- Value
dataFind("Places", "name", data("Stages", $stage - 1, "place"))
- Action Name
placeFound- Table
Places- Row
placeRow
placeFound.value == true- Sprite
data("Places", placeRow, "backdrop")
A.2 Bob While Waiting
Built in Chapter 1, A Stage Stands.
Moves this singing note gently up and down around where it was placed, each note starting at its own moment.
Any Objectself.noteState- Component Value
self.noteState.homeY- Value
self.transform.position.y
- Action Name
startOffset- Minimum
0- Maximum
1
- Component Value
self.noteState.startDelay- Value
startOffset.value * @self.secondsPerSwing
$calmMotion == false- Timer Name
"bob"- Repeat Every (s)
@self.secondsPerSwing- First Delay (s)
self.noteState.startDelay
- Value
self.transform.position.y- Target
self.noteState.homeY + @self.bobMeters * self.noteState.swingDirection- Duration
@self.secondsPerSwing- Ease
Quad in Out
- Component Value
self.noteState.swingDirection- Value
-self.noteState.swingDirection
$calmMotion == true- Timer Name
"bob"
- Which
Value- Value
self.transform.position.y
- X
self.transform.position.x- Y
self.noteState.homeY
- Timer Name
"bob"- Repeat Every (s)
@self.secondsPerSwing- First Delay (s)
self.noteState.startDelay
A.3 Build A Floor (Function)
Built in Chapter 1, A Stage Stands.
Builds one floor of a tower from its material (a row of the Materials table): a support at each side, supportSpread from the middle of the tower, and a plank across them, standing on floorBottom (meters).
- Type
Text- Name
supportKind
- Name
supportHeight- Value
0
- Type
Text- Name
plankKind
- Name
plankHeight- Value
0
- Variable
supportKind- Value
data("Materials", material, "support")
- Variable
supportHeight- Value
data("Block Kinds", supportKind, "height")
data("Materials", material, "supportsHigh")times- x
towerX - supportSpread- y
floorBottom + supportHeight * (local.index + 0.5)- tower
tower- builder
builder- kind
supportKind
data("Materials", material, "supportsHigh")times- x
towerX + supportSpread- y
floorBottom + supportHeight * (local.index + 0.5)- tower
tower- builder
builder- kind
supportKind
- Variable
plankKind- Value
data("Materials", material, "plank")
- Variable
plankHeight- Value
data("Block Kinds", plankKind, "height")
- x
towerX- y
floorBottom + floorHeight - plankHeight / 2- tower
tower- builder
builder- kind
plankKind
A.4 Build The Stage
Built in Chapter 1, A Stage Stands.
When the Field starts, builds the stage being played from the Stages, Tower Plans, Floors and Notes tables: every tower, floor by floor from the ground up, and every singing note where its pitch puts it.
Any Object- Name
tower- Value
0
- Name
towerRow- Value
0
- Name
towerX- Value
0
- Name
floorRow- Value
0
- Name
floorBottom- Value
0
- Type
Text- Name
roofKind
- Name
row- Value
0
- Table
Towers
- Label
"Towers"- Color
#C27A3A
data("Stages", $stage - 1, "towerCount")times- Variable
tower- Value
local.index
- Variable
towerRow- Value
data("Stages", $stage - 1, "firstTower") + tower
- Variable
towerX- Value
data("Tower Plans", towerRow, "x")
- Variable
floorBottom- Value
@self.groundHeight
data("Tower Plans", towerRow, "floorCount")times- Variable
floorRow- Value
data("Tower Plans", towerRow, "firstFloor") + local.index
- tower
tower- towerX
towerX- floorBottom
floorBottom- floorHeight
@self.floorHeight- supportSpread
@self.supportSpread- builder
self- material
data("Floors", floorRow, "material")
- Variable
floorBottom- Operator
+=- Value
@self.floorHeight
- Action Name
roofFound- Table
Materials- Row
data("Tower Plans", towerRow, "roof")
roofFound.value == true- Variable
roofKind- Value
data("Materials", data("Tower Plans", towerRow, "roof"), "support")
- x
towerX - @self.roofSpread- y
floorBottom + data("Block Kinds", roofKind, "height") / 2- tower
tower- builder
self- kind
roofKind
- x
towerX + @self.roofSpread- y
floorBottom + data("Block Kinds", roofKind, "height") / 2- tower
tower- builder
self- kind
roofKind
- Label
"Singing Notes"- Color
#E8B923
data("Stages", $stage - 1, "noteCount")times- Variable
row- Value
data("Stages", $stage - 1, "firstNote") + local.index
- Action Name
noteSpot- noteRow
row- groundHeight
@self.groundHeight- floorHeight
@self.floorHeight- noteAboveFloor
@self.noteAboveFloor
- Table
Notes- Row
row- Column
"x"- Value
noteSpot.x
- Table
Notes- Row
row- Column
"y"- Value
noteSpot.y
- Object to Create
@self.singingNote- X
noteSpot.x- Y
noteSpot.y- Variable Name
newNote
- Variable
newNote.noteRow- Value
data("Stages", $stage - 1, "firstNote") + local.index
- Variable
newNote.turn- Value
local.index
- Applies to
newNote- Custom Event
placed
- Custom Event
stageBuilt
A.5 Place A Block (Function)
Built in Chapter 1, A Stage Stands.
Creates one block of a tower: the block Object named kind, its middle at x, y (meters). The new block is told its tower and its kind, and "placed" tells it to read its size and material.
- Applies to
builder- Object to Create
kind- X
x- Y
y- Variable Name
newBlock
- Variable
newBlock.tower- Value
tower
- Variable
newBlock.kind- Value
kind
- Applies to
newBlock- Custom Event
placed
A.6 Where A Note Sits (Function)
Built in Chapter 1, A Stage Stands.
Works out where a singing note of the stage being played sits, from its pitch: a higher note sits higher. noteRow is its row of the Notes table; x and y are the middle of the note (meters).
- Name
pitch- Value
0
- Name
lowestPitch- Value
0
- Name
semitonesPerFloor- Value
1
- Name
floorNumber- Value
0
- Name
tower- Value
0
- Name
towerRow- Value
0
- Name
noteX- Value
0
- Name
noteY- Value
0
- Variable
pitch- Value
data("Notes", noteRow, "midi")
- Variable
lowestPitch- Value
data("Notes", data("Stages", $stage - 1, "firstNote"), "midi")
- Variable
semitonesPerFloor- Value
data("Stages", $stage - 1, "semitonesPerFloor")
- Variable
floorNumber- Value
round((pitch - lowestPitch) / semitonesPerFloor)
- Variable
tower- Value
data("Notes", noteRow, "tower")
- Variable
towerRow- Value
data("Stages", $stage - 1, "firstTower") + tower
- Variable
noteX- Value
data("Tower Plans", towerRow, "x")
- Variable
noteY- Value
groundHeight + floorNumber * floorHeight + noteAboveFloor
- x
noteX- y
noteY
A.7 Ask For The Call
Built in Chapter 2, Listening.
The Hear it again button, and its key (the Hear It Again Command, Space): asks for the call to be played again.
Any Object- Custom Event
callRequested
- Custom Event
callRequested
A.8 Call A Note
Built in Chapter 2, Listening.
After the opening, says "Listen…" and chooses the call, one of the stage's singing notes at random: $calledPitch is its pitch. Repeat The Call plays it.
Any Object- Variable
$calledPitch- Value
0
- Variable
$message- Value
'listen'
- Timer Name
"callNote"- Repeat Every (s)
@self.secondsBeforeCall- Ring Once
Yes
- Name
calledRow- Value
0
- Action Name
calledTurn- Minimum
0- Maximum
data("Stages", $stage - 1, "noteCount") - 1
- Variable
calledRow- Value
data("Stages", $stage - 1, "firstNote") + calledTurn.value
- Variable
$calledPitch- Value
data("Notes", calledRow, "midi")
- Custom Event
callRequested
A.9 Make Way For The Notes
Built in Chapter 2, Listening.
Keeps the music quiet under the notes ($musicLevel), fades it down while a note sings and brings it back afterwards, so the notes are always heard clearly.
Any Objectself.makeWayForTheNotesData- Component Value
self.makeWayForTheNotesData.loudness- Value
1
- Component Value
self.makeWayForTheNotesData.targetLoudness- Value
1
- Audio Bus
Music- Volume
$musicLevel
- Component Value
self.makeWayForTheNotesData.targetLoudness- Value
0
- Timer Name
"musicBack"- Repeat Every (s)
@self.holdSeconds- Ring Once
Yes
- Timer Name
"fadeMusic"- Repeat Every (s)
@self.stepSeconds- First Delay (s)
@self.stepSeconds
- Component Value
self.makeWayForTheNotesData.targetLoudness- Value
1
- Timer Name
"fadeMusic"- Repeat Every (s)
@self.stepSeconds- First Delay (s)
@self.stepSeconds
self.makeWayForTheNotesData.loudness > self.makeWayForTheNotesData.targetLoudness- Component Value
self.makeWayForTheNotesData.loudness- Value
max(self.makeWayForTheNotesData.targetLoudness, self.makeWayForTheNotesData.loudness - @self.stepSeconds / @self.secondsToFadeOut)
self.makeWayForTheNotesData.loudness < self.makeWayForTheNotesData.targetLoudness- Component Value
self.makeWayForTheNotesData.loudness- Value
min(self.makeWayForTheNotesData.targetLoudness, self.makeWayForTheNotesData.loudness + @self.stepSeconds / @self.secondsToFadeIn)
- Audio Bus
Music- Volume
self.makeWayForTheNotesData.loudness * $musicLevel
self.makeWayForTheNotesData.loudness == self.makeWayForTheNotesData.targetLoudness- Timer Name
"fadeMusic"
A.10 Play Piano Note (Function)
Built in Chapter 2, Listening.
Plays the piano note of one pitch (a MIDI number: 53 is F3, 60 is middle C, 79 is G5), the Sound its row of the Pitches table names.
- Action Name
pitchFound- Table
Pitches- Row
dataFind("Pitches", "midi", pitch)
pitchFound.value == true- Sound
data("Pitches", dataFind("Pitches", "midi", pitch), "noteSound")
- Custom Event
noteSung
A.11 Play The Place’s Tune
Built in Chapter 2, Listening.
When a stage starts, crossfades to the tune of its place, the Sound its row of the Places table names (a tune already playing carries on). How loud the music is belongs to Make Way For The Notes.
Any Object- Name
placeRow- Value
0
- Variable
placeRow- Value
dataFind("Places", "name", data("Stages", $stage - 1, "place"))
- Action Name
placeFound- Table
Places- Row
placeRow
placeFound.value == true- Operation
Crossfade Music- Sound
data("Places", placeRow, "tune")- Crossfade Seconds
@self.crossfadeSeconds
A.12 Repeat The Call
Built in Chapter 2, Listening.
Plays the call whenever it is asked for while the stage is being played, and again by itself after a quiet spell, at most twice in a row, never over the player's aim or a shot in the air.
Any Objectself.repeatTheCallData- Action Name
isPlaying- Game State
Playing
isPlaying.value == true && $calledPitch > 0- pitch
$calledPitch
- Component Value
self.repeatTheCallData.repeatsLeft- Value
@self.mostRepeats
- Timer Name
"repeatTheCall"- Repeat Every (s)
@self.quietSeconds- First Delay (s)
@self.quietSeconds
self.repeatTheCallData.isNoteWaiting == true- pitch
$calledPitch
- Component Value
self.repeatTheCallData.repeatsLeft- Operator
+=- Value
-1
self.repeatTheCallData.repeatsLeft <= 0- Timer Name
"repeatTheCall"
- Timer Name
"repeatTheCall"- Repeat Every (s)
@self.quietSeconds- First Delay (s)
@self.waitSeconds
- Component Value
self.repeatTheCallData.isNoteWaiting- Value
true
- Component Value
self.repeatTheCallData.isNoteWaiting- Value
false
- Component Value
self.repeatTheCallData.isNoteWaiting- Value
true
- Component Value
self.repeatTheCallData.isNoteWaiting- Value
false
- Action Name
isStillPlaying- Game State
Playing
isStillPlaying.value == true- Timer Name
"repeatTheCall"- Repeat Every (s)
@self.quietSeconds- First Delay (s)
@self.quietSeconds
- Timer Name
"repeatTheCall"
A.13 Show The Message
Built in Chapter 2, Listening.
Shows the message named by $message (a row of the Messages table) for a few seconds, then clears it.
Any Object- Variable
$message- Value
""
- Visible
No
$message != ""- Visible
Yes
- Timer Name
"hideMessage"- Repeat Every (s)
@self.showSeconds- Ring Once
Yes
- Visible
No
- Variable
$message- Value
""
A.14 Sing In The Opening
Built in Chapter 2, Listening.
Before the first call, the singing notes sing once from the lowest to the highest. Each note sings its own turn and swells while it sings. It reads noteRow and turn (its Note State), set by Build The Stage, when it creates the note.
Any Objectself.noteState- Component Value
self.noteState.pitch- Value
data("Notes", self.noteState.noteRow, "midi")
$howToPlaySeen == true- Timer Name
"singTurn"- Repeat Every (s)
@self.openingStartSeconds + self.noteState.turn * @self.secondsBetweenNotes- Ring Once
Yes
- Timer Name
"singTurn"- Repeat Every (s)
@self.afterHowToPlaySeconds + self.noteState.turn * @self.secondsBetweenNotes- Ring Once
Yes
self.noteState.turn == 0- Variable
$message- Value
'lowToHigh'
self.noteState.turn == (data("Stages", $stage - 1, "noteCount") - 1)- Timer Name
"openingDone"- Repeat Every (s)
@self.pauseAfterOpeningSeconds- Ring Once
Yes
- pitch
self.noteState.pitch
- Value
self.transform.scale- Target
@self.swellScale- Duration
@self.swellSeconds / 2- Ease
Quad Out
- Timer Name
"swellFull"- Repeat Every (s)
@self.swellSeconds / 2- Ring Once
Yes
- Value
self.transform.scale- Target
1- Duration
@self.swellSeconds / 2- Ease
Quad in
- Custom Event
openingFinished
A.15 Aim At (Function)
Built in Chapter 3, Aiming.
Sets the aim ($aimX, $aimY): the point the happy note is pulled to, towards a point but never more than maxPull from home (the band point); and the speed it will leave at ($launchVX, $launchVY): launchPower times the pull, back towards home.
shotSumsData StructureShot Sums- Component Value
happyNote.shotSums.pullX- Value
pointX - homeX
- Component Value
happyNote.shotSums.pullY- Value
pointY - homeY
- Component Value
happyNote.shotSums.pullLength- Value
hypot(happyNote.shotSums.pullX, happyNote.shotSums.pullY)
- Component Value
happyNote.shotSums.pullScale- Value
min(1, maxPull / happyNote.shotSums.pullLength)
- Variable
$aimX- Value
homeX + happyNote.shotSums.pullX * happyNote.shotSums.pullScale
- Variable
$aimY- Value
homeY + happyNote.shotSums.pullY * happyNote.shotSums.pullScale
- Variable
$launchVX- Value
(homeX - $aimX) * launchPower
- Variable
$launchVY- Value
(homeY - $aimY) * launchPower
A.16 Band At Rest
Built in Chapter 3, Aiming.
The band hangs between the prongs while a happy note waits in it and nobody is pulling; it makes the stretching sound when a pull starts.
Any Object- Visible
No
- Visible
Yes
- Visible
No
- Sound
Sound Stretch
- Visible
Yes
- Visible
No
A.17 Drop The Pull (Function)
Built in Chapter 3, Aiming.
Ends a pull with no shot: the happy note goes back to the band (home), and the band and the aiming dots rest.
- Applies to
happyNote- X
homeX- Y
homeY
- Custom Event
pullEnded
A.18 Load The Happy Note
Built in Chapter 3, Aiming.
Puts a happy note in the band when the opening is over, and again a moment after each shot ends, if none is there.
Any Object- bandX
self.transform.position.x + @self.bandOffsetX- bandY
self.transform.position.y + @self.bandOffsetY- happyNote
@self.happyNote- slingshot
self
- Timer Name
"loadNext"- Repeat Every (s)
@self.secondsAfterShot- Ring Once
Yes
- Action Name
isPlaying- Game State
Playing
isPlaying.value == true- bandX
self.transform.position.x + @self.bandOffsetX- bandY
self.transform.position.y + @self.bandOffsetY- happyNote
@self.happyNote- slingshot
self
A.19 Make The Aiming Dots
Built in Chapter 3, Aiming.
When the slingshot is created, it makes its aiming dots: dotCount of them, numbered from 1 (nearest the band) out, each hidden until a pull starts.
Any Object@self.dotCounttimes- Object to Create
@self.aimDot- X
self.transform.position.x- Y
self.transform.position.y- Variable Name
newDot
- Variable
newDot.dotNumber- Value
local.index + 1
- Applies to
newDot- Custom Event
placed
A.20 Pull Back
Built in Chapter 3, Aiming.
Lets the player pull the waiting happy note back from the band, with the mouse (or a finger) or with the keys, and let go. A pull cut off by another window or by the device is dropped.
Any Objectself.shotSumsself.pullBackData- Component Value
self.pullBackData.homeX- Value
self.transform.position.x
- Component Value
self.pullBackData.homeY- Value
self.transform.position.y
- Name
pointerDistance- Value
0
- Name
pointerX- Value
0
- Name
pointerY- Value
0
- Type
Boolean- Name
isInReach- Value
false
- Variable
pointerX- Value
eventValue("position.x", 0)
- Variable
pointerY- Value
eventValue("position.y", 0)
- Variable
pointerDistance- Value
hypot(pointerX - self.pullBackData.homeX, pointerY - self.pullBackData.homeY)
pointerDistance <= @self.reach || pointerX <= @self.reachLeftOf- Variable
isInReach- Value
true
- Variable
isInReach- Value
false
pointerY < @self.aimAreaTop && isInReach == true- Component Value
self.pullBackData.isKeyAiming- Value
false
- Timer Name
"steerAim"
- Component Value
self.pullBackData.isPulled- Value
true
- homeX
self.pullBackData.homeX- homeY
self.pullBackData.homeY- pointX
pointerX- pointY
pointerY- maxPull
@self.maxPull- launchPower
@self.launchPower- happyNote
self
- X
$aimX- Y
$aimY
- Custom Event
pullStarted
- Name
pointerX- Value
0
- Name
pointerY- Value
0
self.pullBackData.isPulled == true- Variable
pointerX- Value
eventValue("position.x", 0)
- Variable
pointerY- Value
eventValue("position.y", 0)
- homeX
self.pullBackData.homeX- homeY
self.pullBackData.homeY- pointX
pointerX- pointY
pointerY- maxPull
@self.maxPull- launchPower
@self.launchPower- happyNote
self
- X
$aimX- Y
$aimY
- Component Value
self.pullBackData.turnKeys- Value
eventValue("axisVector.y", 0)
- Component Value
self.pullBackData.pullKeys- Value
eventValue("axisVector.x", 0)
self.pullBackData.turnKeys != 0 || self.pullBackData.pullKeys != 0- Component Value
self.pullBackData.isKeyHeld- Value
true
- Component Value
self.pullBackData.isKeyHeld- Value
false
self.pullBackData.isPulled == false && self.pullBackData.isKeyAiming == false && self.pullBackData.isKeyHeld == true- Component Value
self.pullBackData.isKeyAiming- Value
true
- Component Value
self.pullBackData.keyAngle- Value
@self.startAngle
- Component Value
self.pullBackData.keyPull- Value
@self.startPull
- Custom Event
pullStarted
- Timer Name
"steerAim"- Repeat Every (s)
@self.stepSeconds- First Delay (s)
0
- Component Value
self.pullBackData.keyAngle- Operator
+=- Value
self.pullBackData.turnKeys * @self.degreesPerSecond * @self.stepSeconds
- Component Value
self.pullBackData.keyAngle- Value
clamp(self.pullBackData.keyAngle, @self.lowestAngle, @self.highestAngle)
- Component Value
self.pullBackData.keyPull- Operator
+=- Value
self.pullBackData.pullKeys * @self.pullPerSecond * @self.stepSeconds
- Component Value
self.pullBackData.keyPull- Value
clamp(self.pullBackData.keyPull, @self.leastPull, 1)
- homeX
self.pullBackData.homeX- homeY
self.pullBackData.homeY- pointX
self.pullBackData.homeX - cos(degtorad(self.pullBackData.keyAngle)) * @self.maxPull * self.pullBackData.keyPull- pointY
self.pullBackData.homeY - sin(degtorad(self.pullBackData.keyAngle)) * @self.maxPull * self.pullBackData.keyPull- maxPull
@self.maxPull- launchPower
@self.launchPower- happyNote
self
- X
$aimX- Y
$aimY
self.pullBackData.isKeyAiming == true- Component Value
self.pullBackData.isKeyAiming- Value
false
- Timer Name
"steerAim"
- homeX
self.pullBackData.homeX- homeY
self.pullBackData.homeY- shortestShot
@self.shortestShot- happyNote
self
self.pullBackData.isPulled == true- Component Value
self.pullBackData.isPulled- Value
false
- homeX
self.pullBackData.homeX- homeY
self.pullBackData.homeY- shortestShot
@self.shortestShot- happyNote
self
self.pullBackData.isPulled == true- Component Value
self.pullBackData.isPulled- Value
false
- homeX
self.pullBackData.homeX- homeY
self.pullBackData.homeY- happyNote
self
self.pullBackData.isPulled == true- Component Value
self.pullBackData.isPulled- Value
false
- homeX
self.pullBackData.homeX- homeY
self.pullBackData.homeY- happyNote
self
A.21 Show The Flight
Built in Chapter 3, Aiming.
One of the white dots that show where the happy note will fly while it is pulled: dot number n is where the note will be n x secondsBetweenDots after it is let go. It reads dotNumber (its Dot State), set by Make The Aiming Dots, when the slingshot makes the dot.
Any Objectself.dotState- Visible
No
- Name
dotScale- Value
1
- Variable
dotScale- Value
@self.firstDotScale - self.dotState.dotNumber * @self.shrinkPerDot
- Variable
dotScale- Value
max(@self.smallestDotScale, dotScale)
- Horizontal Scale
dotScale- Vertical Scale
dotScale
- Event
Every Step- Mode
Shown
- Visible
No
- Event
Every Step- Mode
Hidden
- Name
dotY- Value
0
- Name
dotX- Value
0
- Name
t- Value
0
- Variable
t- Value
self.dotState.dotNumber * @self.secondsBetweenDots
- Variable
dotX- Value
$aimX + $launchVX * t
- Variable
dotY- Value
$aimY + $launchVY * t - $gravity / 2 * t * t
dotY > @self.groundHeight && dotX < @self.screenRight && dotY < @self.highestShown- Visible
Yes
- X
dotX- Y
dotY
- Visible
No
A.22 Stretch The Band
Built in Chapter 3, Aiming.
One side of the band: while the happy note is pulled it stretches from its prong (where it is placed) to the note.
Any Objectself.stretchTheBandData- Component Value
self.stretchTheBandData.prongX- Value
self.transform.position.x
- Component Value
self.stretchTheBandData.prongY- Value
self.transform.position.y
- Visible
No
- Visible
Yes
- Event
Every Step- Mode
Stretched
- Visible
No
- Event
Every Step- Mode
Slack
- X
(self.stretchTheBandData.prongX + $aimX) / 2- Y
(self.stretchTheBandData.prongY + $aimY) / 2
- Degrees
radtodeg(atan2($aimY - self.stretchTheBandData.prongY, $aimX - self.stretchTheBandData.prongX))
- Horizontal Scale
hypot($aimX - self.stretchTheBandData.prongX, $aimY - self.stretchTheBandData.prongY) / @self.bandThickness- Vertical Scale
1
A.23 Ask Again
Built in Chapter 4, Flying.
After a shot that did not find the called note, tells the player and plays the call again: "Missed! Listen again…" when the shot reached no singing note, "Not that one. Listen again…" when it reached a wrong one, and after a few wrong notes which way the call is.
Any Object$aimedPitch == 0- Variable
$message- Value
'missed'
- Timer Name
"callAgain"- Repeat Every (s)
@self.secondsAfterMiss- Ring Once
Yes
$wrongNotes >= @self.hintAfterWrongNotes$calledPitch > $aimedPitch- Variable
$message- Value
'hintHigher'
- Variable
$message- Value
'hintLower'
- Custom Event
hintWanted
- Variable
$message- Value
'notThatOne'
- Timer Name
"callAgain"- Repeat Every (s)
@self.secondsAfterWrongNote- Ring Once
Yes
- Custom Event
callRequested
A.24 Count The Shots
Built in Chapter 4, Flying.
Counts the shots of this stage in $shots (the Shots Count at the top shows it), and how many of them reached a wrong note in $wrongNotes.
Any Object- Variable
$shots- Value
0
- Variable
$wrongNotes- Value
0
- Variable
$wrongNotes- Operator
+=- Value
1
- Custom Event
wrongNoteCounted
- Variable
$shots- Operator
+=- Value
1
A.25 Fly
Built in Chapter 4, Flying.
Flings the happy note from the aim when it is launched, lets it fly, land and roll, and ends the shot when it has stood still for a moment, left the field or flown too long.
Any Objectself.shotSumsself.flyDataCollider- Logic Component
Pull Back- State
Disable
- Component Value
self.collider.fixed- Value
false
- Component Value
self.transform.gravity- Value
true
- X Velocity
$launchVX- Y Velocity
$launchVY
- groundHeight
@self.groundHeight- fieldLeft
@self.fieldLeft- fieldRight
@self.fieldRight- shot
self
$aimedPitch == $calledPitch- Value
@self.hitBounce
- Event
Every Step- Mode
Hard
- Value
@self.springBackBounce
- Sound
Sound Launch
- Timer Name
"watchFlight"- Repeat Every (s)
@self.checkSeconds- First Delay (s)
@self.checkSeconds
- Event
shotNear- Radius
@self.nearRadius
- Name
speed- Value
0
- Component Value
self.flyData.flightSeconds- Operator
+=- Value
@self.checkSeconds
- Variable
speed- Value
hypot(self.transform.velocity.x, self.transform.velocity.y)
speed < @self.stillSpeed- Component Value
self.flyData.stillFor- Operator
+=- Value
@self.checkSeconds
- Component Value
self.flyData.stillFor- Value
0
self.transform.position.y < @self.rollingHeight- Amount
@self.rollingSlowdown
self.flyData.stillFor >= @self.stillSeconds || self.flyData.flightSeconds >= @self.longestFlightSeconds || self.transform.position.x < @self.fieldLeft || self.transform.position.x > @self.fieldRight || self.transform.position.y < @self.fieldBottom- Timer Name
"watchFlight"
- Particles
Landing Dust- Position Relative To
World- X
clamp(self.transform.position.x, @self.screenLeft, @self.screenRight)- Y
max(self.transform.position.y - @self.dustBelowNote, @self.groundHeight)- Z Index Offset
@self.dustLayer
- Custom Event
shotEnded
A.26 Let Go (Function)
Built in Chapter 4, Flying.
Ends a pull: a pull shorter than shortestShot puts the happy note back in the band; a longer one launches it.
- Custom Event
pullEnded
hypot($aimX - homeX, $aimY - homeY) < shortestShot- Applies to
happyNote- X
homeX- Y
homeY
- Custom Event
happyNoteLaunched
A.27 Put A Note In The Band (Function)
Built in Chapter 4, Flying.
Puts a happy note at the band point, unless one is already there or flying.
instanceCount("Happy Note") == 0- Applies to
slingshot- Object to Create
happyNote- X
bandX- Y
bandY- Variable Name
newHappyNote
- Custom Event
happyNoteLoaded
A.28 Answer The Shot
Built in Chapter 5, Wrong Notes.
When the shot aimed at this singing note reaches it, the note answers: a wrong note sings its own pitch, shakes and says so; the called note bursts and plays its flourish. It reads pitch (its Note State), set by Sing In The Opening, when the note hears "placed".
Any Objectself.noteStateself.answerTheShotData- Component Value
self.answerTheShotData.homeX- Value
self.transform.position.x
- Event
On Shot Arrived- Mode
Waiting
- Custom Event
shotArrived
self.noteState.pitch != $calledPitch- Custom Event
shotArrived
- Custom Event
shotArrived
self.noteState.pitch == $aimedPitch- Event
On Shot Arrived- Mode
Answered
self.noteState.pitch != $calledPitch- pitch
self.noteState.pitch
- Component Value
self.answerTheShotData.shakeLeft- Value
@self.shakeSeconds
- Timer Name
"shake"- Repeat Every (s)
@self.shakeStepSeconds- First Delay (s)
0
- Custom Event
wrongNoteReached
- Particles
Note Burst- Position Relative To
World- X
self.transform.position.x- Y
self.transform.position.y- Z Index Offset
@self.burstLayer
- pitch
self.noteState.pitch
- Custom Event
callFound
- Component Value
self.answerTheShotData.shakeSide- Value
-self.answerTheShotData.shakeSide
- Component Value
self.answerTheShotData.shakeLeft- Operator
+=- Value
-@self.shakeStepSeconds
self.answerTheShotData.shakeLeft > 0- Value
self.transform.position.x- Target
self.answerTheShotData.homeX + self.answerTheShotData.shakeSide * @self.shakeMeters- Duration
@self.shakeStepSeconds
- Value
self.transform.position.x- Target
self.answerTheShotData.homeX- Duration
@self.shakeStepSeconds
- Timer Name
"shake"
A.29 Judge The Shot (Function)
Built in Chapter 5, Wrong Notes.
Follows the path the aiming dots show, from the aim at the launch speed, and sets $aimedPitch to the pitch of the first singing note it comes within reach of (0 if it reaches none). A shot is judged as it leaves the slingshot.
shotSumsData StructureShot Sums- Variable
$aimedPitch- Value
0
- Component Value
shot.shotSums.t- Value
0
round(longestPathSeconds / pathStepSeconds)times- Component Value
shot.shotSums.t- Operator
+=- Value
pathStepSeconds
- Component Value
shot.shotSums.pathX- Value
$aimX + $launchVX * shot.shotSums.t
- Component Value
shot.shotSums.drop- Value
$gravity / 2 * shot.shotSums.t * shot.shotSums.t
- Component Value
shot.shotSums.pathY- Value
$aimY + $launchVY * shot.shotSums.t - shot.shotSums.drop
data("Stages", $stage - 1, "noteCount")times- Component Value
shot.shotSums.noteRow- Value
data("Stages", $stage - 1, "firstNote") + local.index
- Component Value
shot.shotSums.noteX- Value
data("Notes", shot.shotSums.noteRow, "x")
- Component Value
shot.shotSums.noteY- Value
data("Notes", shot.shotSums.noteRow, "y")
- Component Value
shot.shotSums.gapX- Value
shot.shotSums.pathX - shot.shotSums.noteX
- Component Value
shot.shotSums.gapY- Value
shot.shotSums.pathY - shot.shotSums.noteY
- Component Value
shot.shotSums.distanceToNote- Value
hypot(shot.shotSums.gapX, shot.shotSums.gapY)
$aimedPitch == 0 && shot.shotSums.distanceToNote < reach && shot.shotSums.pathY > groundHeight && shot.shotSums.pathX > fieldLeft && shot.shotSums.pathX < fieldRight- Variable
$aimedPitch- Value
data("Notes", shot.shotSums.noteRow, "midi")
A.30 Point To The Call
Built in Chapter 5, Wrong Notes.
When a hint is wanted, shows this arrow beside the wrong note the shot reached, pointing up or down towards the called note, bobbing gently, for a few seconds.
Any Objectself.pointToTheCallData- Visible
No
- Name
noteRow- Value
0
- Name
noteX- Value
0
- Name
noteY- Value
0
data("Stages", $stage - 1, "noteCount")times- Variable
noteRow- Value
data("Stages", $stage - 1, "firstNote") + local.index
data("Notes", noteRow, "midi") == $aimedPitch- Variable
noteX- Value
data("Notes", noteRow, "x")
- Variable
noteY- Value
data("Notes", noteRow, "y")
$calledPitch > $aimedPitch- Degrees
0
- Component Value
self.pointToTheCallData.baseY- Value
noteY + @self.aboveMeters
- Degrees
180
- Component Value
self.pointToTheCallData.baseY- Value
noteY - @self.aboveMeters
- X
noteX - @self.besideMeters- Y
self.pointToTheCallData.baseY
- Visible
Yes
- Timer Name
"bob"- Repeat Every (s)
@self.secondsPerSwing- First Delay (s)
0
- Timer Name
"hideHint"- Repeat Every (s)
@self.showSeconds- Ring Once
Yes
$calmMotion == false- Value
self.transform.position.y- Target
self.pointToTheCallData.baseY + @self.bobMeters * self.pointToTheCallData.swingDirection- Duration
@self.secondsPerSwing- Ease
Quad in Out
- Component Value
self.pointToTheCallData.swingDirection- Value
-self.pointToTheCallData.swingDirection
$calmMotion == true- Which
Value- Value
self.transform.position.y
- X
self.transform.position.x- Y
self.pointToTheCallData.baseY
- Timer Name
"bob"
- Visible
No
A.31 Tell Of A Strike
Built in Chapter 5, Wrong Notes.
When the happy note strikes this block, tells everyone that the shot has reached the towers.
Any Object- Custom Event
towerStruck
A.32 Come Down When Struck
Built in Chapter 6, The Tower Comes Down.
A block stands until a shot at the called note strikes it, or a falling block knocks into it while a tower is coming down. Then it cuts its tower at its top, and every block of that tower at or above the cut comes loose and falls. It reads tower and kind (its Block State), set by Place A Block, when it creates the block.
Any Objectself.blockStateself.comeDownWhenStruckDataCollider- Component Value
self.comeDownWhenStruckData.width- Value
data("Block Kinds", self.blockState.kind, "width")
- Component Value
self.comeDownWhenStruckData.height- Value
data("Block Kinds", self.blockState.kind, "height")
$aimedPitch == $calledPitch- Custom Event
struck
- Name
gapY- Value
0
- Name
gapX- Value
0
- Name
reachAhead- Value
0
- Name
otherSpeed- Value
0
- Variable
otherSpeed- Value
hypot(other.transform.velocity.x, other.transform.velocity.y)
- Variable
reachAhead- Value
@self.nearMeters + otherSpeed * @self.lookAheadSeconds
- Variable
gapX- Value
abs(other.transform.position.x - self.transform.position.x)
- Variable
gapY- Value
abs(other.transform.position.y - self.transform.position.y)
gapX < (self.comeDownWhenStruckData.width / 2 + reachAhead) && gapY < (self.comeDownWhenStruckData.height / 2 + reachAhead)- Custom Event
struck
- Name
otherSpeed- Value
0
- Variable
otherSpeed- Value
hypot(other.transform.velocity.x, other.transform.velocity.y)
$towersFalling == true && otherSpeed > @self.knockSpeed- Custom Event
struck
- Name
top- Value
0
- Component Value
self.comeDownWhenStruckData.isStruck- Value
true
- Variable
top- Value
self.transform.position.y + self.comeDownWhenStruckData.height / 2
top < data("Towers", self.blockState.tower, "cut")- Table
Towers- Row
self.blockState.tower- Column
"cut"- Value
top
- Custom Event
towerCut
- Name
bottom- Value
0
- Variable
bottom- Value
self.transform.position.y - self.comeDownWhenStruckData.height / 2
self.comeDownWhenStruckData.isStruck == true || bottom >= (data("Towers", self.blockState.tower, "cut") - @self.cutTolerance)- Component Value
self.blockState.isFalling- Value
true
- Component Value
self.collider.fixed- Value
false
- Component Value
self.transform.gravity- Value
true
- Custom Event
cameLoose
- Logic Component
Come Down When Struck- State
Disable
A.33 Fall With A Knock
Built in Chapter 6, The Tower Comes Down.
Once a block has come loose: it knocks when it lands (wood, stone or ice), throws splinters or dust when it lands hard, and a block of ice shatters when it is hit or lands hard while a tower is coming down. A block that falls out of the field is removed. It reads kind and isFalling (its Block State), set by Place A Block (kind, when it creates the block) and Come Down When Struck (isFalling), on the same block.
Any Objectself.blockStateself.fallWithAKnockDataCollider- Component Value
self.fallWithAKnockData.material- Value
data("Block Kinds", self.blockState.kind, "material")
- Event
Every Step- Mode
Falling
- Component Value
self.fallWithAKnockData.lastSpeed- Value
self.fallWithAKnockData.speed
- Component Value
self.fallWithAKnockData.speed- Value
hypot(self.transform.velocity.x, self.transform.velocity.y)
self.fallWithAKnockData.lastSpeed > @self.landingSpeed && (self.fallWithAKnockData.lastSpeed - self.fallWithAKnockData.speed) > @self.landingDrop- Custom Event
landed
self.transform.position.y < @self.fieldBottom || self.transform.position.x < @self.fieldLeft || self.transform.position.x > @self.fieldRightself.fallWithAKnockData.material == "ice" && $towersFalling == true && self.fallWithAKnockData.lastSpeed > @self.iceLandingSpeed && (self.fallWithAKnockData.lastSpeed - self.fallWithAKnockData.speed) > @self.iceLandingDrop- Custom Event
shatter
- Variable
$knockMaterial- Value
self.fallWithAKnockData.material
- Custom Event
blockKnocked
(self.fallWithAKnockData.lastSpeed - self.fallWithAKnockData.speed) > @self.hardDrop && self.fallWithAKnockData.material == "wood" && $calmMotion == false- Particles
Wood Splinters- Position Relative To
World- X
self.transform.position.x- Y
self.transform.position.y- Z Index Offset
@self.effectLayer
(self.fallWithAKnockData.lastSpeed - self.fallWithAKnockData.speed) > @self.hardDrop && self.fallWithAKnockData.material == "stone" && $calmMotion == false- Particles
Stone Dust- Position Relative To
World- X
self.transform.position.x- Y
self.transform.position.y- Z Index Offset
@self.effectLayer
- Name
otherSpeed- Value
0
- Variable
otherSpeed- Value
hypot(other.transform.velocity.x, other.transform.velocity.y)
self.fallWithAKnockData.material == "ice" && self.blockState.isFalling == true && $towersFalling == true && otherSpeed > @self.iceShotSpeed- Custom Event
shatter
- Name
otherSpeed- Value
0
- Variable
otherSpeed- Value
hypot(other.transform.velocity.x, other.transform.velocity.y)
self.fallWithAKnockData.material == "ice" && self.blockState.isFalling == true && $towersFalling == true && otherSpeed > @self.iceKnockSpeed- Custom Event
shatter
- Particles
Ice Shatter- Position Relative To
World- X
self.transform.position.x- Y
self.transform.position.y- Z Index Offset
@self.effectLayer
- Variable
$knockMaterial- Value
'ice'
- Custom Event
blockKnocked
A.34 Play Flourish (Function)
Built in Chapter 6, The Tower Comes Down.
Plays the short rising flourish of one pitch (a MIDI number), the sound of the called note found: the Sound its row of the Pitches table names.
- Action Name
pitchFound- Table
Pitches- Row
dataFind("Pitches", "midi", pitch)
pitchFound.value == true- Sound
data("Pitches", dataFind("Pitches", "midi", pitch), "flourishSound")
- Custom Event
noteSung
A.35 Slow The Moment
Built in Chapter 6, The Tower Comes Down.
When the called note is found, slows the world for a moment and gives the camera a small shake.
Any Object$calmMotion == false- Speed
@self.slowPace- Ease Seconds
@self.easeSeconds- Hold Seconds
@self.slowSeconds
- Intensity
@self.shakeStrength- Seconds
@self.shakeSeconds
A.36 Sound The Fall
Built in Chapter 6, The Tower Comes Down.
Plays the knock of each block that lands, the Sound its material's row of the Materials table names (never two closer than knockGapSeconds), and a crash that grows with the fall: a small crash once enough knocks come close together, a big crash if many more do.
Any Objectself.soundTheFallData- Component Value
self.soundTheFallData.crash- Operator
+=- Value
1
- Timer Name
"crashFade"- Repeat Every (s)
@self.fadeStepSeconds- First Delay (s)
@self.fadeStepSeconds
- Action Name
knockReady- Cooldown Key
"knock"
knockReady.value == true- Cooldown Key
"knock"- Seconds
@self.knockGapSeconds
- Action Name
materialFound- Table
Materials- Row
$knockMaterial
materialFound.value == true- Sound
data("Materials", $knockMaterial, "knockSound")
- Component Value
self.soundTheFallData.crash- Value
max(0, self.soundTheFallData.crash - @self.fadePerSecond * @self.fadeStepSeconds)
self.soundTheFallData.crash >= @self.bigCrashKnocks && self.soundTheFallData.crashLevel < 2- Component Value
self.soundTheFallData.crashLevel- Value
2
- Sound
Sound Crash Big
self.soundTheFallData.crash >= @self.smallCrashKnocks && self.soundTheFallData.crashLevel < 1- Component Value
self.soundTheFallData.crashLevel- Value
1
- Sound
Sound Crash Small
self.soundTheFallData.crash < @self.quietKnocks- Component Value
self.soundTheFallData.crashLevel- Value
0
- Timer Name
"crashFade"
A.37 Watch The Towers Fall
Built in Chapter 6, The Tower Comes Down.
Keeps $towersFalling Yes from the moment a tower is cut until settleSeconds after the shot ends: while it is Yes, falling blocks knock standing blocks loose.
Any Object- Variable
$towersFalling- Value
false
- Variable
$towersFalling- Value
true
- Timer Name
"settle"
$towersFalling == true- Timer Name
"settle"- Repeat Every (s)
@self.settleSeconds- Ring Once
Yes
- Variable
$towersFalling- Value
false
A.38 Bring Up The Card
Built in Chapter 7, Winning.
When the stage is won, the card comes up cardAfterSeconds later, or later while blocks are still crashing, and at latestCardSeconds at the latest.
Any Object- Timer Name
"showCard"- Repeat Every (s)
@self.cardAfterSeconds- Ring Once
Yes
- Timer Name
"latestCard"- Repeat Every (s)
@self.latestCardSeconds- Ring Once
Yes
- Cooldown Key
"stillCrashing"- Seconds
@self.restSeconds
- Action Name
isQuiet- Cooldown Key
"stillCrashing"
isQuiet.value == true- Custom Event
cardDue
- Timer Name
"showCard"- Repeat Every (s)
@self.restSeconds- Ring Once
Yes
- Custom Event
cardDue
- Timer Name
"showCard"
- Timer Name
"latestCard"
- Input Context
Field- Active
No
- Input Context
Card
- Custom Event
cardShown
A.39 Fill The Bar
Built in Chapter 7, Winning.
The bar on the card fills over fillSeconds; when it is full it says the card has had its time.
Any Object- Horizontal Scale
0- Vertical Scale
1
- Value
self.transform.scale.x- Target
1- Duration
@self.fillSeconds
- Timer Name
"barFull"- Repeat Every (s)
@self.fillSeconds- Ring Once
Yes
- Custom Event
cardTimeUp
A.40 Go On From The Card
Built in Chapter 7, Winning.
Clicking or tapping the card asks to go on at once.
Any Object- Custom Event
goOnWanted
A.41 Go On To The Next Stage
Built in Chapter 7, Winning.
From the card, the next stage starts: by itself when the card has had its time, or at once with Enter or a click. After the last stage the finale comes instead.
Any Object- Custom Event
goOn
- Custom Event
goOn
- Custom Event
goOn
- Logic Component
Go On To The Next Stage- State
Disable
$stage >= dataCount("Stages")- Custom Event
finaleShown
- Variable
$stage- Operator
+=- Value
1
A.42 Light A Star
Built in Chapter 7, Winning.
One of the three stars on the card (each placement has its starNumber): it shows lit when the stage earned at least that many stars.
Any Object$starsWon >= self.starNumber- Frame
1
- Frame
0
A.43 Show The Next Stage
Built in Chapter 7, Winning.
The card's last line, the number and name of the next stage: shown with the card when there is a next stage.
Any Object- Visible
No
- Visible
No
$stage < dataCount("Stages")- Visible
Yes
A.44 Show With The Card
Built in Chapter 7, Winning.
A part of the card that shows when a stage is won: hidden until then.
Any Object- Visible
No
- Visible
Yes
- Visible
No
A.45 Start The Stage Again
Built in Chapter 7, Winning.
The Restart button: starts the stage being played again from the beginning (with a new call).
Any Object- Sound
Sound Click
A.46 Tell How It Was Found
Built in Chapter 7, Winning.
The card's message: how the called note was found, by how many wrong notes came first.
Any Object- Type
Text- Name
wordsBefore
- Type
Text- Name
wordsAfter
$wrongNotes <= 1- Text
data("Found Words", $wrongNotes, "words")
- Variable
wordsBefore- Value
data("Found Words", 2, "words")
- Variable
wordsAfter- Value
data("Found Words", 2, "wordsAfterNumber")
- Text
text(wordsBefore, " ", $wrongNotes, " ", wordsAfter)
A.47 Win The Stage
Built in Chapter 7, Winning.
Finding the called note wins the stage: the game is Stage Won, and the stage earns stars for listening. The Stages table keeps the best stars of each stage.
Any Object- Game State
Playing
- Input Context
Field
- Input Context
Card- Active
No
- Input Context
Menus- Active
No
- Game State
Stage Won
$wrongNotes == 0- Variable
$starsWon- Value
3
$wrongNotes <= @self.twoStarWrongNotes- Variable
$starsWon- Value
2
- Variable
$starsWon- Value
1
$starsWon > data("Stages", $stage - 1, "stars")- Table
Stages- Row
$stage - 1- Column
"stars"- Value
$starsWon
- Custom Event
starsCounted
A.48 Belong To A Place
Built in Chapter 8, The Title and the Maps.
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.
Any Objectself.mapSpot- Name
rowBefore- Value
0
- Component Value
self.mapSpot.placeIndex- Value
self.mapSpot.cardIndex
- Variable
rowBefore- Value
self.mapSpot.placeIndex * $stagesPerPlace - 1
self.mapSpot.placeIndex == 0 || data("Stages", rowBefore, "stars") > 0- Component Value
self.mapSpot.isOpen- Value
true
- Component Value
self.mapSpot.isOpen- Value
false
A.49 Belong To A Stage
Built in Chapter 8, The Title and the Maps.
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.
Any Objectself.mapSpot- Name
firstStage- Value
1
- Variable
firstStage- Value
floor(($stage - 1) / $stagesPerPlace) * $stagesPerPlace + 1
- Component Value
self.mapSpot.stageNumber- Value
firstStage + self.mapSpot.cardIndex
self.mapSpot.stageNumber == 1 || data("Stages", self.mapSpot.stageNumber - 2, "stars") > 0- Component Value
self.mapSpot.isOpen- Value
true
- Component Value
self.mapSpot.isOpen- Value
false
A.50 Choose The Next Stage
Built in Chapter 8, The Title and the Maps.
When a map opens, $nextStage is the stage to play next: the first stage without stars, or the last stage when every stage has some (the maps highlight it). On the Place Map it also becomes $stage, so the map shows its place.
Any Object- Name
rowWithoutStars- Value
-1
- Variable
rowWithoutStars- Value
dataFind("Stages", "stars", 0)
rowWithoutStars >= 0- Variable
$nextStage- Value
rowWithoutStars + 1
- Variable
$nextStage- Value
dataCount("Stages")
self.selectIt == true- Variable
$stage- Value
$nextStage
A.51 Count The Place’s Stars
How many of a place’s stars (3 for each of its $stagesPerPlace stages) have been earned, shown on its card (“
Built in Chapter 8, The Title and the Maps.
How many of a place's stars (3 for each of its $stagesPerPlace stages) have been earned, shown on its card ("<n> of 30"). It reads placeIndex (its Map Spot), set by Belong To A Place, attached first.
Any Objectself.mapSpot- Name
stageRow- Value
0
- Component Value
self.mapSpot.starsEarned- Value
0
$stagesPerPlacetimes- Variable
stageRow- Value
self.mapSpot.placeIndex * $stagesPerPlace + local.index
- Component Value
self.mapSpot.starsEarned- Operator
+=- Value
data("Stages", stageRow, "stars")
A.52 Go Back
Built in Chapter 8, The Title and the Maps.
The back arrow and the Map button (and Escape): go back one screen (Field to Stage Map, Stage Map to Place Map, Place Map to Title).
Any Object- Custom Event
goBack
- Custom Event
goBack
- Sound
Sound Click
A.53 Lay Out A Place Card
Built in Chapter 8, The Title and the Maps.
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.
Any Objectself.mapSpot- Object to Create
@self.placePicture- X
self.transform.position.x- Y
self.transform.position.y + @self.pictureAbove- Variable Name
newPicture
- Variable
newPicture.cardIndex- Value
self.mapSpot.cardIndex
- Applies to
newPicture- Custom Event
placed
- Object to Create
@self.placeLock- X
self.transform.position.x- Y
self.transform.position.y + @self.pictureAbove- Variable Name
newLock
- Variable
newLock.cardIndex- Value
self.mapSpot.cardIndex
- Applies to
newLock- Custom Event
placed
- Object to Create
@self.placeRing- X
self.transform.position.x- Y
self.transform.position.y- Variable Name
newRing
- Variable
newRing.cardIndex- Value
self.mapSpot.cardIndex
- Applies to
newRing- Custom Event
placed
- Object to Create
@self.placeName- X
0- Y
0- Variable Name
newName
- Applies to
newName- X
self.transform.position.x- Y
self.transform.position.y - @self.nameBelow
- Variable
newName.cardIndex- Value
self.mapSpot.cardIndex
- Applies to
newName- Custom Event
placed
- Object to Create
@self.placeStar- X
self.transform.position.x - @self.starLeft- Y
self.transform.position.y - @self.starsBelow- Variable Name
newStar
- Object to Create
@self.placeStars- X
0- Y
0- Variable Name
newStarCount
- Applies to
newStarCount- X
self.transform.position.x + @self.countRight- Y
self.transform.position.y - @self.starsBelow
- Variable
newStarCount.cardIndex- Value
self.mapSpot.cardIndex
- Applies to
newStarCount- Custom Event
placed
A.54 Lay Out A Stage Card
Built in Chapter 8, The Title and the Maps.
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.
Any Objectself.mapSpot- Object to Create
@self.numberLabel- X
0- Y
0- Variable Name
newNumber
- Applies to
newNumber- X
self.transform.position.x- Y
self.transform.position.y + @self.numberAbove
- Variable
newNumber.cardIndex- Value
self.mapSpot.cardIndex
- Applies to
newNumber- Custom Event
placed
- Object to Create
@self.nameLabel- X
0- Y
0- Variable Name
newName
- Applies to
newName- X
self.transform.position.x- Y
self.transform.position.y - @self.nameBelow
- Variable
newName.cardIndex- Value
self.mapSpot.cardIndex
- Applies to
newName- Custom Event
placed
- Object to Create
@self.stageLock- X
self.transform.position.x- Y
self.transform.position.y - @self.starsBelow- Variable Name
newLock
- Variable
newLock.cardIndex- Value
self.mapSpot.cardIndex
- Applies to
newLock- Custom Event
placed
- Object to Create
@self.stageRing- X
self.transform.position.x- Y
self.transform.position.y- Variable Name
newRing
- Variable
newRing.cardIndex- Value
self.mapSpot.cardIndex
- Applies to
newRing- Custom Event
placed
3times- 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
- Variable
newStar.cardIndex- Value
self.mapSpot.cardIndex
- Variable
newStar.starNumber- Value
local.index + 1
- Applies to
newStar- Custom Event
placed
A.55 Lay Out The Places
Built in Chapter 8, The Title and the Maps.
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.
Any Objectself.mapGrid- Name
cardX- Value
0
- Name
cardY- Value
0
- Component Value
self.mapGrid.cardCount- Value
dataCount("Places")
- Component Value
self.mapGrid.cardsInARow- Value
@self.columns
dataCount("Places")times- Variable
cardX- Value
@self.firstCardX + mod(local.index, @self.columns) * @self.across
- Variable
cardY- Value
@self.firstCardY - floor(local.index / @self.columns) * @self.down
- Object to Create
@self.placeCard- X
cardX- Y
cardY- Variable Name
newCard
- Variable
newCard.cardIndex- Value
local.index
- Applies to
newCard- Custom Event
placed
A.56 Lay Out The Stages
Built in Chapter 8, The Title and the Maps.
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.
Any Objectself.mapGrid- Name
cardX- Value
0
- Name
cardY- Value
0
- Component Value
self.mapGrid.cardCount- Value
$stagesPerPlace
- Component Value
self.mapGrid.cardsInARow- Value
@self.columns
$stagesPerPlacetimes- Variable
cardX- Value
@self.firstCardX + mod(local.index, @self.columns) * @self.across
- Variable
cardY- Value
@self.firstCardY - floor(local.index / @self.columns) * @self.down
- Object to Create
@self.stageCard- X
cardX- Y
cardY- Variable Name
newCard
- Variable
newCard.cardIndex- Value
local.index
- Applies to
newCard- Custom Event
placed
A.57 Light A Stage Star
Built in Chapter 8, The Title and the Maps.
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).
Any Objectself.mapSpotself.mapSpot.isOpen == false- Visible
No
data("Stages", self.mapSpot.stageNumber - 1, "stars") >= self.mapSpot.starNumber- Frame
1
- Frame
0
A.58 Open A Place
Built in Chapter 8, The Title and the Maps.
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).
Any Objectself.mapSpotself.mapSpot.isOpen == truefloor(($nextStage - 1) / $stagesPerPlace) == self.mapSpot.placeIndex- Variable
$selectedCard- Value
self.mapSpot.cardIndex
- Frame
1
- Frame
0
- Frame
2
- Custom Event
chosen
self.mapSpot.cardIndex == $selectedCard- Custom Event
chosen
self.mapSpot.isOpen == true- Sound
Sound Click
- Variable
$stage- Value
self.mapSpot.placeIndex * $stagesPerPlace + 1
- Scene
Stage Map- Transition
Fade- Transition Seconds
@self.fadeSeconds
A.59 Open A Stage
Built in Chapter 8, The Title and the Maps.
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).
Any Objectself.mapSpotself.mapSpot.isOpen == trueself.mapSpot.stageNumber == $nextStage- Variable
$selectedCard- Value
self.mapSpot.cardIndex
- Frame
1
- Frame
0
- Frame
2
- Custom Event
chosen
self.mapSpot.cardIndex == $selectedCard- Custom Event
chosen
self.mapSpot.isOpen == true- Sound
Sound Click
- Variable
$stage- Value
self.mapSpot.stageNumber
- Scene
Field- Transition
Fade- Transition Seconds
@self.fadeSeconds
A.60 Open The Places
Built in Chapter 8, The Title and the Maps.
The Play button, and Enter or Space on the Title (the Open Command): goes to the Place Map.
Any Object- Custom Event
opened
- Custom Event
opened
- Sound
Sound Click
- Scene
Place Map- Transition
Fade- Transition Seconds
@self.fadeSeconds
A.61 Play The Title Tune
Built in Chapter 8, The Title and the Maps.
When the Title starts, the title tune plays at the game's music level, and the menu keys work.
Any Object- Input Context
Menus
- Input Context
Field- Active
No
- Input Context
Card- Active
No
- Audio Bus
Music- Volume
$musicLevel
- Operation
Crossfade Music- Sound
Music Title- Crossfade Seconds
@self.crossfadeSeconds
A.62 Show The Place Picture
Built in Chapter 8, The Title and the Maps.
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.
Any Objectself.mapSpot- Frame
self.mapSpot.placeIndex
self.mapSpot.isOpen == false- Alpha
@self.lockedAlpha
A.63 Choose With The Keys
Built in Chapter 9, Locks and Keys.
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.
Any Objectself.mapGrid- Variable
$selectedCard- Value
0
- Variable
$isChoosing- Value
false
- Variable
$selectedCard- Value
max(0, $selectedCard - 1)
- Custom Event
moved
- Variable
$selectedCard- Value
min(self.mapGrid.cardCount - 1, $selectedCard + 1)
- Custom Event
moved
$selectedCard >= self.mapGrid.cardsInARow- Variable
$selectedCard- Operator
-=- Value
self.mapGrid.cardsInARow
- Custom Event
moved
($selectedCard + self.mapGrid.cardsInARow) < self.mapGrid.cardCount- Variable
$selectedCard- Operator
+=- Value
self.mapGrid.cardsInARow
- Custom Event
moved
- Variable
$isChoosing- Value
true
- Sound
Sound Click
A.64 Dim When Locked
Built in Chapter 9, Locks and Keys.
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.
Any Objectself.mapSpotself.mapSpot.isOpen == false- Alpha
@self.lockedAlpha
A.65 Show A Lock
Built in Chapter 9, Locks and Keys.
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.
Any Objectself.mapSpotself.mapSpot.isOpen == false- Visible
Yes
- Visible
No
A.66 Show The Ring
Built in Chapter 9, Locks and Keys.
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.
Any Objectself.mapSpot- Visible
No
- Custom Event
placeRing
- Custom Event
placeRing
$isChoosing == true && self.mapSpot.cardIndex == $selectedCard- Visible
Yes
- Visible
No
A.67 Close How To Play
Built in Chapter 10, Remembering, Settings and Finish.
The Got it button (and Enter or Space): closes the How to play card for good on this device, and the stage begins.
Any Object$howToPlaySeen == false- Input Context
Field- Active
No
- Input Context
Menus
- Custom Event
gotIt
- Custom Event
gotIt
$howToPlaySeen == false- Sound
Sound Click
- Variable
$howToPlaySeen- Value
true
- Action Name
howToPlayKept- Key
"howToPlaySeen"- Value
1
- Input Context
Menus- Active
No
- Input Context
Field
- Custom Event
howToPlayClosed
A.68 Count All The Stars
Built in Chapter 10, Remembering, Settings and Finish.
Counts the stars of every stage (the Stages table) for the finale: the text reads starsInAll.
Any Objectself.finaleStars- Component Value
self.finaleStars.starsInAll- Value
0
dataCount("Stages")times- Component Value
self.finaleStars.starsInAll- Operator
+=- Value
data("Stages", local.index, "stars")
A.69 Keep The Stars
Built in Chapter 10, Remembering, Settings and Finish.
When a stage is won, keeps its place's stars on the device (one number per place), so they survive closing the game.
Any Object- Name
place- Value
0
- Name
packed- Value
0
- Name
stageRow- Value
0
- Variable
place- Value
floor(($stage - 1) / $stagesPerPlace)
- Variable
packed- Value
0
$stagesPerPlacetimes- Variable
stageRow- Value
place * $stagesPerPlace + local.index
- Variable
packed- Operator
+=- Value
data("Stages", stageRow, "stars") * pow(4, local.index)
- Action Name
starsKept- Key
data("Places", place, "starsKey")- Value
packed
A.70 Read Back What Was Kept
Built in Chapter 10, Remembering, Settings and Finish.
When the game opens, reads back once what this device kept: the stars (into the Stages table) and whether How to play was seen.
Any ObjectdataCount("Places")times- Action Name
keptStars- Key
data("Places", local.index, "starsKey")- Default
0
- place
local.index- packed
keptStars.value
- Action Name
keptHowToPlay- Key
"howToPlaySeen"- Default
0
keptHowToPlay.value == 1- Variable
$howToPlaySeen- Value
true
- Variable
$howToPlaySeen- Value
false
- Action Name
keptSound- Key
"soundOff"- Default
0
keptSound.value == 1- Variable
$soundOff- Value
true
- Variable
$soundOff- Value
false
- Action Name
keptMotion- Key
"calmMotion"- Default
0
keptMotion.value == 1- Variable
$calmMotion- Value
true
- Variable
$calmMotion- Value
false
A.71 Show How To Play
Built in Chapter 10, Remembering, Settings and Finish.
A part of the How to play card: shown only the very first time a stage is played on this device, until "Got it".
Any Object$howToPlaySeen == true- Visible
No
- Visible
Yes
- Visible
No
A.72 Show The Choice (Function)
Built in Chapter 10, Remembering, Settings and Finish.
Shows a choice on its button's icon: frame 1 when the choice is on, frame 0 when it is off.
isOn == true- Applies to
button- Frame
1
- Applies to
button- Frame
0
A.73 Show With The Finale
Built in Chapter 10, Remembering, Settings and Finish.
A part of the finale: hidden until the last stage is won.
Any Object- Visible
No
- Visible
Yes
A.74 Sing The Finale
Built in Chapter 10, Remembering, Settings and Finish.
After the last stage: every note of that stage sings once from low to high, then all of them together.
Any Objectself.singTheFinaleData- Component Value
self.singTheFinaleData.turn- Value
0
- Component Value
self.singTheFinaleData.firstNote- Value
data("Stages", $stage - 1, "firstNote")
- Timer Name
"finaleNote"- Repeat Every (s)
@self.secondsBetweenNotes- First Delay (s)
@self.firstNoteSeconds
self.singTheFinaleData.turn < data("Stages", $stage - 1, "noteCount")- pitch
data("Notes", self.singTheFinaleData.firstNote + self.singTheFinaleData.turn, "midi")
- Component Value
self.singTheFinaleData.turn- Operator
+=- Value
1
data("Stages", $stage - 1, "noteCount")times- pitch
data("Notes", self.singTheFinaleData.firstNote + local.index, "midi")
- Timer Name
"finaleNote"
A.75 Turn Calm Motion On And Off
Built in Chapter 10, Remembering, Settings and Finish.
The Motion button: turns calm motion on or off (no slow motion, camera shake, bobbing or flying bits); its icon shows which (frame 1 is calm), and the choice is kept on the device.
Any Object- Custom Event
showChoice
$calmMotion == true- Variable
$calmMotion- Value
false
- Action Name
keptNo- Key
"calmMotion"- Value
0
- Variable
$calmMotion- Value
true
- Action Name
keptYes- Key
"calmMotion"- Value
1
- Sound
Sound Click
- Custom Event
showChoice
- isOn
$calmMotion- button
self
A.76 Turn The Sound On And Off
Built in Chapter 10, Remembering, Settings and Finish.
The Sound button: turns all sound off or on; its icon shows which (frame 1 is off), and the choice is kept on the device.
Any Object- Custom Event
showChoice
$soundOff == true- Variable
$soundOff- Value
false
- Action Name
keptNo- Key
"soundOff"- Value
0
- Variable
$soundOff- Value
true
- Action Name
keptYes- Key
"soundOff"- Value
1
- Sound
Sound Click
- Custom Event
showChoice
- isOn
$soundOff- button
self
$soundOff == true- Volume
0
- Volume
1
A.77 Unpack A Place’s Stars (Function)
Built in Chapter 10, Remembering, Settings and Finish.
Writes the stars of a place's stages ($stagesPerPlace of them) into the Stages table from one number kept on the device (base 4: the place's stage k is digit k).
$stagesPerPlacetimes- Table
Stages- Row
place * $stagesPerPlace + blockLocal("index")- Column
"stars"- Value
mod(floor(packed / pow(4, blockLocal("index"))), 4)
