- Learn
- Build a Game
- Pitch Shot
- 3 Aiming
3 Aiming
By the end of this chapter, the happy note arrives in the band. Pull it back with the mouse, a finger or the arrow keys, and the band stretches from both prongs while a line of white dots shows where it would fly. Let go, and it springs back into the band. It can’t fly yet.
The game as it is at the end of this chapter. Click the game to play.
If your game and this chapter part ways, here is the chapter’s finished project. Unzip it first. Then open it and compare, or start Chapter 4 from it.
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.
3.1 The Idea
The opening sings, low to high. Listen… shows in the pill, and one note sings alone. And the slingshot stands there with nothing in it.
Now, as Listen… appears, a round blue note appears in the band, rosy cheeks and a wide smile, a little black flag on its head. That’s the happy note, the one you’ll fling.
Put the mouse near it, press, and pull back. The note comes with you. The band stretches from both prongs to hold it, and a curve of white dots runs out ahead of it, up and over toward the tower. Pull farther, and the dots reach farther. Let go, and the note springs back into the band.
Here’s the problem. The note hasn’t flown yet, and the dots already know where it will go. How?
Think of a flip-book. Each page is the same moment a little later, and flipping them shows the motion. The dots are the pages of a flight that hasn’t happened. The first dot is where the note will be a moment after you let go. The second is a moment after that, and so on, 33 moments in all. Each dot works out its own page from three things: where the note starts, how fast it will leave, and how the world pulls it down.
So the pull has to come up with two numbers. One is the aim, the spot you’ve pulled the note to. The other is the launch speed, how fast and which way the note would leave from there. Everything in this chapter reads those two.
3.2 The Plan
Here’s how the pieces work together. A name in bold is a piece you’ll make, and a name in plain text is a Custom Event.
- The opening ends -> openingFinished -> Load The Happy Note puts the Happy Note in the band -> happyNoteLoaded -> Band At Rest shows the band holding it.
- You press near the band, or press an arrow key -> Pull Back moves the note back -> pullStarted.
- Each time the pull moves -> Pull Back asks Aim At for the aim and the launch speed.
- Once pullStarted goes out -> each Band Piece stretches from its prong to the note, and each Aim Dot shows its moment of the flight.
- You let go -> Drop The Pull puts the note back -> pullEnded -> the band rests, and the dots hide.
- The slingshot is made -> Make The Aiming Dots makes 33 dots, each told its number.
- Repeat The Call hears pullStarted and pullEnded too, so the call never sings over your aim.
You’ll build it so it comes alive in that order: the note first, then the pull, the band and the dots.
3.3 Set Up
Left Arrow, ARight Arrow, DUp Arrow, WDown Arrow, SEnterHear It Again, Aim, Let GoART and SOUNDS name what the Starter Kit already brought: three pictures and Sound Stretch, the creak of the band.
COMMANDS has two new Commands. Aim is a 2D Axis Command, a direction rather than a single press, with two keys for each way: the arrows and W, A, S and D. Let Go is a Button, Enter. Keys: Commands and Input Contexts shows how. INPUT CONTEXTS marks Field (changed), because it’s the context you renamed in Chapter 2. It’s still Active at Start, and only its Commands are new. So select Field’s row first. A new 2D Axis Command comes with a row for each direction. For the second key of a direction, press Add Keybinding, pick that direction in the list at the front of the new row, and press the key.
GLOBAL VARIABLES has five. $aimX and $aimY are the aim, and $launchVX and $launchVY are the launch speed, across and up. They’re Globals because the note, the band and the dots all read them. $gravity starts at 9.8, the same pull your game’s world falls by. It’s the same number as your world’s Gravity Y field, -9.8, without the minus. That minus means down. The dots’ sum puts it back in by itself, as you’ll see in Show The Flight. If you ever change one, change the other. Make them from the Globals card, as you made $stage in Chapter 1, and give each the card’s Default.
PLACE THESE waits for the band, and the chapter comes back to it when the band is made.
3.4 A Note in the Band
First, the note itself.
X 0.65, Y 0.8940Happy Note ArtX 0.65, Y 0.89Pull BackShot SumsPull BackPull Back DataMake the Happy Note as an Empty Object, with its Sprite, Happy Note Art, and its sizes. Its Scene Depth Draw Order of 40 draws it in front of the band. Leave its Data Structure and Logic for later in the chapter. Like the singing notes, it isn’t placed. The slingshot makes it.
3.4.1 Load The Happy Note
When the opening ends, the slingshot puts a note in its band. Load The Happy Note hears openingFinished. It asks one question first: is there already a Happy Note? instanceCount counts the Objects of one kind in the game, so instanceCount("Happy Note") == 0 means none. Only then does Create Instance make one, and the game never has two waiting.
Where does it go? The band hangs a little above the slingshot’s middle. So the note goes at the slingshot’s own position, moved by bandOffsetX across and by bandOffsetY up. The second is 1.01 meters, and the first is almost nothing. Then it sends happyNoteLoaded.
Puts a happy note in the band when the opening is over, if none is waiting there.
Any ObjectinstanceCount("Happy Note") == 0- Object to Create
@self.happyNote- X
self.transform.position.x + @self.bandOffsetX- Y
self.transform.position.y + @self.bandOffsetY- Variable Name
newHappyNote
- Custom Event
happyNoteLoaded
Make it with Add > Logic Component. Its happyNote is a Shared Variable, an Object, like Build The Stage’s singingNote, and the Slingshot’s card sets it to Happy Note. The slingshot’s own x is self.transform.position.x, and it goes into Create Instance’s X box with the rest of the formula.
3.4.2 The Slingshot, Changed
X 1.52, Y 320Slingshot ArtX 1.52, Y 3Happy NoteAim DotThe slingshot gets two Logic Components this chapter. Attach Load The Happy Note now. Make The Aiming Dots comes with the dots, at the end.
Run the game. The opening sings, Listen… shows, and in the same moment the happy note appears in the band, smiling. It doesn’t move, and it can’t yet.
3.4.3 Band At Rest
The note needs something to sit in. The Band Rest is a short, straight strip of band, drawn from prong to prong behind the note.
X 0.8, Y 0.0938Band ArtX 0.8, Y 0.09The band has two pictures, and only one may show at a time. At rest, it’s this straight strip. Pulled, it’s two stretched pieces, which come later in the chapter. Band At Rest looks after the first. It keeps the strip hidden until a note arrives, and hides it again the moment a pull starts, with the creak of Sound Stretch. When the pull ends, the strip is back.
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
Make the Band Rest the way you made the Happy Note, and then Band At Rest, and attach it. Its Set Visible blocks have the Yes or No list, as Show The Message’s did. Pick the card’s. Control Sound plays, as in Play Piano Note, and its Sound list takes Sound Stretch.
Now PLACE THESE. Drag the Band Rest onto the Field, and type its X and Y, 2.99 and 3.93.
Run the game. The note arrives, and the band is there behind it, straight across the prongs.
3.5 The Pull
Now the hand on the band.
3.5.1 Shot Sums
Aim At, coming next, is a Function, and a Function has no Object of its own. Remember Place A Block’s builder? Aim At works the same way. It’s handed the happy note, and it keeps its working numbers on that note, in a Data Structure called Shot Sums.
The working values of the Functions that aim the happy note: the pull (Aim At).
Make it, four Numbers.
3.5.2 Aim At
Picture the pull. Home is where the note sits in the band. The pointer is somewhere behind it. The pull is the line from home to the pointer: pullX across, pullY up. Its length is pullLength, worked out by hypot, which finds a line’s length from its two sides.
A pull can’t go on forever. The longest is maxPull, 1.75 meters, a little more than the slingshot is wide. So pullScale says how much of the pull counts. It’s 1, all of it, while the pull is short enough, and less once it’s longer. A formula gets the smaller of two numbers with min. So the card’s min never lets pullScale go over 1, however far you pull. The aim is home, plus the pull times pullScale. Pull far past the limit, and the note stops at 1.75 meters, in the same direction you’re pulling.
Last comes the launch speed. A slingshot throws the opposite way from the pull, and farther back means faster. So $launchVX and $launchVY are the line from the aim back to home, times launchPower, 9.2. Each meter of pull adds 9.2 meters a second.
Look on the card for happyNote, which needs a Shot Sums under the Slot Name shotSums. And look at the paths: happyNote.shotSums.pullX is the note, its Shot Sums, the field pullX.
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
Make it with Add > Function. Its happyNote is the Object at the very end of the Type list, like builder. Then it needs Shot Sums under its Required Components, and A Function card shows where they are: the pencil beside happyNote, on the Start block. Its Compatibility Mode starts at Structural, as the card shows, so leave it there. Steps 1 to 4 are Change Component Value, through happyNote, so their paths go in as the card spells them. Steps 5 to 8 set Globals, so their Variable box takes $aimX and the rest, $ and all.
3.5.3 Drop The Pull
Drop The Pull is the small one. It puts the note back at home, and sends pullEnded, so the band and the dots can rest.
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
Make it the same way. Its happyNote is an Object like Aim At’s, with nothing listed under it. That’s why the card leaves its last column blank. Set Position’s Applies To is a list, so pick happyNote.
3.5.4 Pull Back
Pull Back is the longest card in the chapter, because there are three ways to pull, and two ways a pull can be cut short. Take it one Event at a time.
When the note is made, it remembers home, its own x and y.
With the mouse, or a finger. You press. Pull Back reads where, from the Event, with eventValue("position.x", 0). Is the press near the note, within reach, 2.6 meters? Or anywhere in the left part of the screen, left of 7 meters across? Either one is in reach, and that’s what the If with an Or asks. One more thing: the press must be below aimAreaTop, 8.8 meters up, because the top of the screen belongs to buttons such as Hear it again. Then the pull begins. A key pull, if one was going, stops, and the mouse takes over. Now isPulled is true, Aim At works out the aim, Set Position moves the note there, and pullStarted goes out.
While you hold, Mouse Held does the same each moment, so the note follows your hand. When you let go, Mouse Release calls Drop The Pull, and the note springs home.
With the keys. The arrows don’t give a spot on the screen, so the keys aim by an angle and a length. Aim’s Event brings axisVector, the way the keys are pressing. Its y is 1 for Up and -1 for Down, and its x is 1 for Right and -1 for Left. So turnKeys holds Up and Down. And pullKeys holds Right and Left. The first press starts at startAngle, 40 degrees above level, with three quarters of the longest pull. Hold Up or Down, and the angle turns 50 degrees a second, from -10 up to 80. Hold Right, and the pull grows. Hold Left, and it shrinks. A timer, steerAim, moves them every 0.02 seconds, and clamp keeps each one between its limits. Then the angle and the length become a point behind home, and Aim At takes it from there, as it does for the mouse. Enter lets go.
Cut short. Two Events run by themselves, with nobody pressing anything. Focus Lost comes when you switch to another window in the middle of a pull, and the mouse button is let go over there, where the game never hears it. Touch Cancelled comes when the device cuts a touch off. Both drop the pull, so no note is left hanging in a stretched band.
Lets the player pull the waiting happy note back from the band, with the mouse (or a finger) or with the keys. Letting go puts it back for now; step 04 makes it fly. 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- 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
self.pullBackData.isPulled == true- Component Value
self.pullBackData.isPulled- Value
false
- homeX
self.pullBackData.homeX- homeY
self.pullBackData.homeY- happyNote
self
The card’s description says step 04 makes it fly, and that’s Chapter 4 of this book.
Pull Back keeps nine things from one Event to the next: where home is, whether a pull is going, whether a key is held, and the keys’ angle and length. They live in its own Data Structure, Pull Back Data. The values of one moment, such as pointerX, are Declare Variables at the top of their Event.
Object Data of Logic "Pull Back" (its state that lasts between Events).
Make Pull Back Data first. Three of its fields are Booleans, and keyAngle and keyPull start at 40 and 0.75. Then make the Logic with Add > Logic Component. Its Data Structures card takes two: Shot Sums and Pull Back Data. Its fourteen Shared Variables are Constant Numbers.
The When bars are in Events: the When bars, in the paragraph that begins From Chapter 3, and eventValue is at the end of Values, quote marks and all. A few more things are new:
- An If’s condition is one box. The press’s second If joins two tests with
&&, and both go into that one box, as the card spells them. - On Aim At’s block, happyNote is a list, so pick self. The keys’ pointX and pointY are the longest formulas in the chapter. Type them as the card spells them. cos and sin turn an angle into across and up, and degtorad turns degrees into the measure they use.
- Two headings, Aim 2D Axis Input and When Letgo Is Pressed, are Myth’s own names, as in Chapter 2.
- The last three Events that drop the pull hold the same few steps each. They go quickly once the first is done.
Pull Back is long, so here’s a place to stop and try it. Once When Created, the press, the hold and the release are built, attach Pull Back, as the next part shows, and run the game. The note follows the mouse. Then come back for the keys and the last two Events.
3.5.5 The Happy Note, Changed
Now the note can take its Logic. Its card is the one at the top of this chapter, with the Data Structure and the Logic you left for later. Open the Happy Note, switch to Logic, and click Pull Back under Logic Toolbox. It brings both its Data Structures with it, the two blocks on the note’s card.
Run the game. When the note arrives, press on it and pull back. It follows you, and it won’t go farther than 1.75 meters, however far you pull. You’ll hear the band creak. Let go, and it’s back in the band. Now press Right, and the note jumps back at an angle. Hold Up and watch it swing around. Press Enter, and it springs home.
The band behind it is gone while you pull, and nothing stretches. That’s next.
3.6 The Band Stretches
Each side of the band is one Band Piece, a short stub of band picture, 0.08 meters across.
X 0.08, Y 0.1338Band ArtX 0.08, Y 0.13Stretch The BandStretch The Band Data3.6.1 Stretch The Band
From the Band Piece’s point of view, there’s one job. Reach from my prong to the note. It’s placed on a prong, so it remembers that spot as its prong when it’s made. Then, while you pull, it does three things every moment. It moves halfway between the prong and the aim. It turns to face the aim. And it stretches sideways until it’s as long as the gap. That’s the gap divided by its own 0.08 across, the stub’s X size, which the card calls bandThickness: the band’s thickness before it’s stretched.
That “every moment” is a Step Event, which runs on every frame of the game. But the band should only stretch during a pull. So its Step has two Modes: Slack, which does nothing, and Stretched, which does the three things. pullStarted switches to Stretched, and pullEnded back to Slack. Most of the time, the Band Piece costs nothing at all.
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
The band remembers where its prong is. That takes a small Data Structure of its own, Stretch The Band Data.
Object Data of Logic "Stretch The Band" (its state that lasts between Events).
Make the Band Piece, then Stretch The Band Data, two Numbers, then Stretch The Band, and attach it. Modes shows how to make the two Modes and the Switch Mode that switches them. Name Mode 1 Slack, because it’s the one the Step starts with. The card lists On Pull Started above the Step, but build the Step and its two Modes first. Then Stretched is there to pick when you make the two Custom Events. The card draws the Step twice, once for each Mode, but it’s one Event, so add Step once. The function atan2 turns a gap into an angle, and radtodeg turns that angle into degrees, which Set Rotation takes.
Back to PLACE THESE. Drag the Band Piece onto the Field twice, once for each prong. The left one goes at 2.59 and 3.93, the right one at 3.39 and 3.93.
Run the game, and pull. Two red bands reach from the prongs to the note and follow it wherever it goes. One Object, placed twice, is both sides of the band.
3.7 Where It Would Fly
Now the flip-book. Each page is an Aim Dot, a small white circle, 0.16 meters across. Its Scene Depth Draw Order of 50 draws it in front of the note and the band, so no dot hides behind them.
X 0.16, Y 0.1650Aim Dot ArtX 0.16, Y 0.16Show The FlightDot StateMake it as an Empty Object, with its Sprite, Aim Dot Art, and its sizes, the way you made the Happy Note. Like the note, it isn’t placed. Leave its Data Structure and Logic for now, because Show The Flight brings both.
3.7.1 Dot State
Each dot needs to know one thing, which dot it is. Dot 1 is nearest the band. That number is the dot’s own, so it lives on the dot, in Dot State.
What one aiming dot knows: which dot it is, 1 for the dot nearest the band.
Make it, one Number that starts at 1. Show The Flight brings it to the dot.
3.7.2 Show The Flight
Dot number n shows where the note will be n times secondsBetweenDots after you let go. That’s 0.055 seconds a page. So t, the dot’s own moment, is its dotNumber times 0.055.
Across is simple. The note will have gone the launch speed across times t, from the aim. Up is that too, minus what the world has pulled it down by then: $gravity / 2 * t * t. That’s why the dots curve. The fall grows faster than the climb, and the line bends down.
A dot that would sit under the grass, past the right side of the screen, or far above it, hides. The rest show, each at its own point.
Each dot is a little smaller than the one before, so the curve fades out as it goes. That size is worked out once, on placed, from the dot’s number. Create runs while the dot is being made, before it’s told its number, so the size waits for placed, as a note’s pitch did in Chapter 2.
The Step works like the band’s. Hidden does nothing, and Shown places the dot.
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
Make Show The Flight, with Dot State on its Data Structures card and its seven Shared Variables. Its Step’s Modes are Hidden, first, and Shown, and as with the band, the Step comes before the Events that switch it. Set Scale has two boxes, Horizontal Scale and Vertical Scale, and both take dotScale. Set Visible is the Yes or No list again.
Then attach it to the Aim Dot, and it brings Dot State with it.
3.7.3 Make The Aiming Dots
Thirty-three dots, each with its own number. By hand, that would be 33 placements and 33 numbers typed. So the slingshot makes them.
Picture the slingshot counting them out as it’s made, one, two, three, all the way to dotCount. Each new dot starts hidden, sitting on the slingshot, and it’s told two things: its number, and that it’s in place. The number comes from the Repeat’s count, plus 1, because the dots count from 1 and local.index counts from 0.
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
This works like the second half of Build The Stage. You’ve built this before. aimDot is a Shared Variable, an Object, and the Slingshot’s card sets it to Aim Dot. The Variable box takes newDot.dotNumber, the new dot’s name, a dot, and the field, as newNote.noteRow did. There’s no dotState in the middle, and that’s not a typo. Change Variable reaches a new Object’s one Data Structure by the field’s plain name, as Chapter 2 showed. Show The Flight reads the number through self, so its path has dotState in it. Then attach it to the Slingshot, under Load The Happy Note.
Run the game, and pull. A curve of white dots runs out from the note, each a little smaller, arcing up and falling toward the tower. Pull a little farther, and the curve stretches. Turn with the keys, and watch it rise and fall as the angle changes under your hands. The dots stop where they’d reach the grass.
3.8 The Call Waits for You
One thing is still rough, and you can hear it. Pull and hold, and wait. After 8 quiet seconds, the call sings, right in the middle of your aim. A call is meant to be listened to, not talked over.
3.8.1 Repeat The Call, Changed
Plays the call whenever it is asked for, 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$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
- pitch
$calledPitch
- Component Value
self.repeatTheCallData.repeatsLeft- Operator
+=- Value
-1
self.repeatTheCallData.repeatsLeft <= 0self.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
Repeat The Call now keeps one Boolean, isNoteWaiting, in Repeat The Call Data beside repeatsLeft. It’s true while a note waits in the band. Two messages make it true, happyNoteLoaded and pullEnded, and pullStarted makes it false.
When the quiet spell is over, it looks. If a note is waiting, the call plays, as before. If not, it doesn’t play. It starts its timer again, with the first ring only waitSeconds away, 1 second, and it looks again then. So the call holds its breath while you aim, and sings a second after you let go.
In the timer’s Event, every old step changes. The new ones sit inside an If. So delete the four old steps, and build the Event again from the card, top to bottom. The Else at step 6 belongs to the first If, so right-click that If when you add it. Then add the three new Events. The Boolean goes into Repeat The Call Data with Add Field, and waitSeconds onto the Logic’s Shared Variables card.
Object Data of Logic "Repeat The Call" (its state that lasts between Events).
Run the game. Wait for the call, then pull and hold, and count slowly to ten. No call comes. Let go, and a moment later, it sings.
Watch, and listen, for each of these.
- As Listen… shows, the happy note appears in the band, with the straight band behind it.
- Press on the note and pull back. The band creaks, the straight band goes, and two bands stretch from the prongs to the note.
- Pull far, much farther than the slingshot. The note stops 1.75 meters from the band and keeps the direction you pull.
- The white dots arc out ahead of the note, each a little smaller than the last. No dot shows under the grass.
- Pull straight down and back, and the dots climb steeply. Pull level, and they run out low.
- Let go. The note springs back into the band, and the dots and the stretched bands vanish.
- Press an arrow key. The note jumps back at 40 degrees. Hold Up and it swings higher, up to 80. Hold Right and Left, and the pull grows and shrinks. Enter puts it back.
- Press high in the sky above the slingshot. No pull starts, because that part of the screen is kept for buttons.
- Hold a pull through a quiet spell. The call waits, and sings about a second after you let go.
The slingshot loads a note when the opening ends. You pull, and Aim At turns your pull into two things: the aim, and the launch speed. Three pieces read them. The note sits at the aim, and each half of the band stretches to it. Each dot works out its own moment of the flight.
Underneath it is one idea: the dots don’t follow the note. Nothing moves along the curve. Each dot asks, on its own, where will the note be at my moment, and goes there. Thirty-three pages of a flight, each drawn by itself.
When the note flies in Chapter 4, it will follow the curve the dots have been showing all along.
3.9 If It Didn’t Work
This chapter’s slips are mostly about who hears what. A message nobody listens for, a list left on the wrong Object, a Mode that never switches. Watch what the game does, and you’ll find it.
The note never arrives? Perhaps Load The Happy Note isn’t on the Slingshot, or its happyNote box is empty. Look at its Attached Logic. Or maybe its If reads instanceCount("Happy note"), with a small n. The name must match the Object’s exactly.
Pressing does nothing? Is Pull Back on the Happy Note? Are you pressing too high, above 8.8 meters, where the buttons live? Press right on the note.
The note follows, but it won’t stop at the limit? Look at Aim At’s step 4. Its formula is min(1, maxPull / happyNote.shotSums.pullLength), with min, not max.
No bands, or bands from the wrong place? Each Band Piece remembers where it’s placed, so look at their two placements, 2.59 and 3.39. And look at Stretch The Band’s Step. Does On Pull Started’s Switch Mode pick Stretched, in its Mode list?
The bands stretch the wrong way, short and fat? Look at Set Scale. Its Horizontal Scale takes the long formula, and its Vertical Scale stays 1.
No dots? Perhaps Make The Aiming Dots isn’t attached, or Show The Flight’s Shown Mode never comes. Or perhaps all 33 dots are there, the same size, sitting at the slingshot. Then the size never came, so look at step 4 of Make The Aiming Dots, which sends placed to newDot.
The dots curve up instead of down? Look at dotY. It ends - $gravity / 2 * t * t, a minus. And is $gravity 9.8?
The keys turn the wrong way? Look at the 2D Axis Command’s rows, where each key needs the direction the card gives it.
Each of these is one small fix. Make it, run the game, and pull again. And if you’d like to compare, the catch-up download in the Goal is this chapter’s game, finished.
The aim is yours to tune. On the Aim Dot, change secondsBetweenDots in Show The Flight from 0.055 to 0.03, and the curve grows short and close. On the Slingshot, change dotCount to 12, and only the start of the flight shows. Or on the Happy Note, change maxPull in Pull Back to 2.5, and pull deeper. Which feels best in your hand? Put everything back before Chapter 4.
Still stuck? Search the manual, or ask in the Myth Engine Discord (opens a new tab).
The note waits in the band, and the dots know the way. In Chapter 4, it flies.
