- Learn
- Build a Game
- Shatterfield
- 9 Screens
9 Screens
Until now, your game started the moment you ran it, and it never really ended. By the end of this chapter, it opens on a title over drifting rocks, with PRESS ENTER TO START blinking. Enter starts a game, Esc holds it under PAUSED, and the last Ship lost brings GAME OVER with your final score. Then the title comes back, and your high score is kept for next time.
The game as it is at the end of this chapter. Click the game, then press Enter to start.
If your game and this chapter part ways, here is the chapter’s finished project. Open it and compare, or start Chapter 10 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. Beside it, OFL.txt is the license of the project’s font, Press Start 2P.
9.1 The Idea
Six Large rocks drift across a dark screen. Over them, in tall white letters that nearly span the screen from side to side, it says SHATTERFIELD. Under that, in cyan, CLEAR THE FIELD. SURVIVE THE SAUCERS. Music plays. Lower down, PRESS ENTER TO START blinks in gold, on and off, on and off.
Press Enter. The rocks are gone at once, without a spark. A short sound plays, your Ship appears in the middle, and WAVE 1 comes up.
That’s the front door. The game has a way home too. In Chapter 5, after your last crash, the rocks drifted on alone and nothing said it was over. Now GAME OVER comes up in pink-red, with your final score under it. A little later the game offers you another try, and if you don’t take it, the title comes back.
All of this rests on a new idea. The game is always in exactly one Game State, like a traffic light that’s always one color. This game has four: Title, Playing, Game Over and Play Again. Logic can change the Game State, and whenever it changes, every piece of Logic listening hears it, the way every driver at the crossing sees the light change.
The second idea follows from the first. Some Logic only makes sense during play: the waves, the lives, the saucers. So that Logic gets switched off when no game is being played, and switched on when one starts. Switched-off Logic hears nothing at all. One new Logic Component, Play Switch, does the switching.
This is the longest chapter in the book, though most of its pieces are ones your hands know: words on the screen, messages, timers, Ifs. Take it a part at a time, and run the game at the end of each.
9.2 The Plan
Here’s how the pieces work together, read from left to right. Most of the names are new, and the parts below make them one at a time. Come back to this list whenever you lose your place.
- The game opens on the Title Game State -> Title Screen sends itself showTitle -> space is cleared, six Title Asteroids drift in, the title shows, the prompt blinks, the music plays.
- Enter is pressed on the title -> Start Game clears space and sets the Game State to Playing.
- The Game State changes to Playing -> Play Switch switches on Lives and Respawn, Waves, Extra Ships, Saucer Spawner and Pause -> each one starts its part of a new game.
- Esc is pressed -> Pause tells the whole game gamePaused and sends showPausedMenu -> Menu Pause Lifecycle shows PAUSED and holds the game.
- Esc or Enter on PAUSED -> the menu sends gameResumed -> Pause sends hideMenu, and the game goes on.
- The last Ship is lost -> Lives and Respawn sets the Game State to Game Over -> Play Switch switches them all off and sends playStopped.
- The Game State changes to Game Over -> Game Over Screen shows GAME OVER and the final score, and Score saves the high score.
- Two seconds later -> Play Again. Twelve seconds after that -> Title again.
9.3 Set Up
This chapter adds two sounds, two Commands, a second Input Context and the Game States. Space Theme is the title’s music. The sound called Start is the short one a game begins with. One of the Commands is named Start too, so this chapter always says which one it means.
The Commands go into the Input Manager as before, with one new step. The card lists them first, with Start on top. Build them in the order below instead. The Start Command goes into an Input Context you haven’t made yet.
The Input Manager’s Input Contexts list already holds one, Default, with its switch on Active at Start. A new Command goes into the context selected in that list, and Default is selected when you open it. So add the Pause Command there.
The Pause Command takes two keys, Escape and P, and Escape needs a small trick. On a key row, a single Escape cancels the recording. So click the row and press Escape twice, quickly, and it reads Escape. Add Keybinding gives a second row, for P.
Next, press Add Input Context, and type Menus into the window that asks for its name. The new context arrives selected, and its switch reads Inactive at Start. Click it. Now it reads Active at Start, like Default’s. Each row has a second switch, Works While Paused. Switched on, it lets that context’s Commands reach your Logic while the game is held. Leave it off on both. PAUSED doesn’t need it. While it’s up, the menu listens for its own two Commands, the ones you’ll pick in its fields later in this chapter. Then add the Start Command here, in Menus, with Enter and Space.
Why a second Input Context? A key can feed only one Command in each Input Context, and Space is already Fire. In Menus, Space can be Start too.
On the card, (changed) beside Default means its list of Commands changed, now that Pause is in it. Its switch stays as it was. (new) beside Menus is the context you made.
The Game States are in Game Settings, on the General page, in its Game State section. Available Game States starts with one, Playing, marked Initial. Press Add Game State, type Title into its window, and press the window’s own Add Game State button. Do the same for Game Over and Play Again. Your list keeps Playing first, and that’s fine, since the order is only how the list reads. Last, pick Title in Initial Game State, and the Initial mark moves to it.
Leave the card’s three SCENE blocks for now. Each word goes into Space as soon as you’ve made it. The Ship’s placement comes out once something else can bring the Ship.
Enter, SpaceEscape, PRotate-and-thrust Controls, Fire, Hyperspace, PauseStartTitle, Playing, Game Over, Play AgainTitleRun the game now, and nothing looks different. It opens on Title, but nothing listens for that yet.
9.4 A Field That Can Be Emptied
First, space learns to empty itself.
9.4.1 Leave When Cleared
When a game starts, or the title comes back, whatever is out there has to go: rocks, saucers, shots of every kind. But not by breaking. A broken rock leaves smaller rocks, sparks and points. Here, things need to leave and take nothing with them.
So there’s a new message, clearField. Leave When Cleared listens for it, and its one Action is Destroy Instance. No sparks, no points, nothing left behind.
This Object leaves when space is cleared for a new game or the title screen.
Any ObjectMake it with Add > Logic Component, as an Empty Logic Component. Its message, clearField, is new, so make its Event with Add Custom Event…, the way you made hit in Chapter 4. Destroy Instance goes in from Mode 1’s right-click and joins the line the usual way.
Attach it to eight Objects now. Its card names a ninth, Title Asteroid, which comes in the next part as a copy and brings Leave When Cleared along.
A new attachment joins the bottom of an Object’s Attached Logic, and that’s where every card here has it. Each card below is the whole Object. Look for the one green line at the bottom of each.
X 0.8125, Y 0.8125Circle0.156Collide Only WithTagged Asteroid, Tagged Saucer15Shot SpriteX 0.8125, Y 0.8125-90X 3.875, Y 3.875OnSensorCircle1.510Asteroid StandardX 3.875, Y 3.875AsteroidAsteroid MediumExpression$waveX 2.0625, Y 2.0625OnSensorCircle0.78110Asteroid StandardX 2.0625, Y 2.0625Asteroid50220.006ExplosionSmallAsteroid SmallExpression$wave2.54.219X 1.125, Y 1.125OnSensorCircle0.40610Asteroid StandardX 1.125, Y 1.125Asteroid100140Asteroid BreakAsteroid Small0Expression$wave3.756.094X 1.625, Y 1.625Circle0.313Collide Only WithShip, Tagged Asteroid15Saucer Orb SpriteX 1.625, Y 1.625Saucer ShotShipX 2.375, Y 1.1875Circle0.234Collide Only WithShip, Tagged Asteroid15Saucer Lance SpriteX 2.375, Y 1.1875Saucer ShotShipYesX 3, Y 3SensorX 2.5, Y 1.125Collide Only WithShip, Shot12Saucer Large SpriteX 3, Y 3SaucerSaucer FlightSaucer Flight DataSaucer OrbX 1.875, Y 1.875SensorX 1.5, Y 0.75Collide Only WithShip, Shot12Saucer Small SpriteX 1.875, Y 1.875SaucerSaucer FlightSaucer Flight Data5.156Saucer Lance0.951000A saucer cleared this way still stops its siren. Saucer Flight’s When Destroyed runs however a saucer goes: shot down, flown off the far side, and now cleared away.
Nothing sends clearField yet. The title will.
9.5 The Front Door
Now the title, its rocks, and the gold line that blinks under it.
9.5.1 Title Asteroid
Chapter 6 made a promise: the rocks drifting behind the title would set their wave to 1. Here they are.
A Title Asteroid looks like an Asteroid Large and drifts like one. Two things set it apart. Its wave is always 1, never $wave. So it always looks and moves like a rock of the first wave, whatever wave the last game reached. And it has no Break Apart. Nothing can hit it on the title, so there’s nothing to break.
X 3.875, Y 3.875OnSensorCircle1.510Asteroid StandardX 3.875, Y 3.875AsteroidIt starts as a copy. In the Resources, right-click Asteroid Large and choose Duplicate. The copy, Asteroid Large2, keeps the Tag Asteroid and every Logic Component with its values. Leave When Cleared comes along too. Rename the copy Title Asteroid, with F2 or the Rename line in that same menu.
Open it in Logic mode. Each row of its Attached Logic has a trash button. Press the one on Break Apart’s row. Break Apart goes at once, and its Variables go with it.
Then switch back to Components. Under Variables, the copy’s wave row still reads Expression in its Kind list, with $wave. Pick Constant there. The Value under it is 1, the Starting Value of the Logic itself. That’s why the card has no line for wave at all.
Nothing makes a Title Asteroid yet. Title Screen will.
9.5.2 Blink
PRESS ENTER TO START doesn’t blink all the time. It blinks while the title is up, and it’s gone the rest of the time. So Blink waits to be told.
When startBlinking arrives, it notes that the text is showing, shows it, and starts a blink timer. The first ring comes after firstDelaySeconds, 0.6 seconds, and after that it rings every blinkSeconds, 0.55 seconds.
Each ring flips the text. If it’s showing, the ring hides it. Hidden? Show it. Blink keeps which it is now in a small form of its own, Blink Data, with one Yes or No field, isShown.
When stopBlinking arrives, the timer stops and the text hides.
Object Data of Logic "Blink" (its state that lasts between Events).
This text blinks while its screen is up: it is shown and hidden in turn every blinkSeconds.
Any Objectself.blinkData- Component Value
self.blinkData.isShown- Value
true
- Visible
Yes
- Timer Name
blink- Repeat Every (s)
@self.blinkSeconds- First Delay (s)
@self.firstDelaySeconds
- Timer Name
blink
- Visible
No
self.blinkData.isShown == true- Visible
No
- Component Value
self.blinkData.isShown- Value
false
- Visible
Yes
- Component Value
self.blinkData.isShown- Value
true
Make Blink Data first, with Add > Data Structure, as you made Ship Shield Data in Chapter 5. Its one field, isShown, is a Boolean. The card’s default is true, so switch its Value to Yes.
Then make Blink. Its two SHARED VARIABLES are Numbers, both Constant. Press the + on its Data Structures card, and pick Blink Data under Existing Data Structures. Its row reads self.blinkData. startBlinking and stopBlinking are new messages, so make their Events with Add Custom Event…. The blink timer’s Event is a Recurring Timer, named blink.
Each Change Component Value takes the path typed, self.blinkData.isShown, then Enter. An = and a Value reading false appear, and where the card says true, you type it over the false. Set Visible’s Visible is a Yes / No list. Start Recurring Timer’s Timer Name takes blink, bare. Type @self.blinkSeconds into Repeat Every (s), and @self.firstDelaySeconds into First Delay (s). Ring Once stays No, because this timer keeps ringing.
The If’s condition is self.blinkData.isShown == true, in its one box. Its Set Visible and Change Component Value go on the True line with Add inside Then, as No and false. Then right-click the If and choose Add Else. The Else’s two come from Add inside Else, and both of those say Yes and true.
9.5.3 Title, Title Tagline, Title Prompt, Title High Score and Title Controls
These are Screen UI Objects. You made three like them for the score in Chapter 7, so your hands know them now.
Four of them share a Group, title. It’s a box in their UI Interaction, and you type the name into it. Logic can then show or hide the whole group at once, by that name.
Title Prompt is the one left out of the group. Blink shows and hides it instead. In this game, a word that blinks stays out of every group, and the last part of this chapter shows what goes wrong when one doesn’t. Title High Score reads {$highScore}, so it always shows the best score so far.
Window / UICenterUIX 32, Y 32TexttitleSHATTERFIELDArcade HUD Font64#F2FBFF6CenterWindow / UICenterUIX 32, Y 32TexttitleCLEAR THE FIELD. SURVIVE THE SAUCERS.Arcade HUD Font12#62DCFF2CenterWindow / UICenterUIX 32, Y 32TextPRESS ENTER TO STARTArcade HUD Font18#FFD1662CenterBlinkBlink DataWindow / UICenterUIX 32, Y 32TexttitleHIGH SCORE {$highScore}Arcade HUD Font12#9FB4D8CenterWindow / UIBottom CenterUIX 32, Y 32TexttitleARROWS/WASD TURN+THRUST SPACE FIRE SHIFT HYPERSPACE ESC PAUSEArcade HUD Font10#7B8AA81CenterMind the spaces in two of these Texts. HIGH SCORE has two before its brace. Title Controls has three between each of its four groups, and it’s all one line. Where the card wraps it, keep typing on the same line.
Element Type is Text on all five, and each Bounding Box > Size is already X 32 and Y 32, as the Wave Banner’s was. Title Prompt also carries Blink, so attach it in Logic mode. Blink Data comes along with it, as the card’s Data Structure lines show. Now place them from the Set up card’s PLACE THESE lines, near the top of this page, the way you placed the Wave Banner. Title Controls is anchored at Bottom Center, so click near the bottom middle of the preview for it. The other four go near the middle. Type each Screen Offset (px), and turn off Visible at Game Start for Title Prompt. Blink shows it when it’s wanted.
9.5.4 Title Screen
Title Screen goes on Game Rules. It has three Events, and the first is the game opening.
Here’s a small puzzle. The game opens already on Title, its Initial Game State. Nothing changed, so Game State Changed doesn’t run. That’s why Title Screen also has Game Start, and all it does is send showTitle to itself.
The middle Event runs when the Game State changes. This kind of Event can’t be told which Game State to wait for. So it asks. Check Game State keeps the answer as isOnTitle.
Back on Title? It sends showTitle again. Anything else, and the title goes away: the title group hides, the prompt stops blinking, the music stops, and the hud group shows.
The last Event, showTitle, does the real work. First it sends clearField to everything, so space is empty of rocks, saucers and shots. Then it calls Create Asteroids Along Edges with titleAsteroid and asteroidsPerBand, 3. That makes six rocks in all. Three come in along the top and bottom edges, and three along the sides. Before its rocks, Waves sets $wave. Title Screen never touches it, and doesn’t need to, since a Title Asteroid’s wave is always 1.
Then the words. Set UI Group Visibility hides the hud group and shows the title group. The hud group is the numbers along the top, and they join it later in this chapter. The prompt gets startBlinking, and Space Theme starts to loop.
The title screen: its words, its music, and six drifting Title Asteroids, whenever the game is on the title.
Any Object- Custom Event
showTitle
- Action Name
isOnTitle- Game State
Title
isOnTitle.value == true- Custom Event
showTitle
- UI Group
title- Visible
No
- Applies To
@self.prompt- Custom Event
stopBlinking
- Operation
Stop- Sound
"Space Theme"
- UI Group
hud
- Custom Event
clearField
- creator
self- asteroid
@self.titleAsteroid- perBand
@self.asteroidsPerBand- edgeBand
@self.edgeBand- sideBand
@self.sideBand
- UI Group
hud- Visible
No
- UI Group
title
- Applies To
@self.prompt- Custom Event
startBlinking
- Operation
Loop- Sound
"Space Theme"
Its five SHARED VARIABLES come first, all Constant. prompt and titleAsteroid are Objects, each with its None button, and three Numbers follow. Two of those, edgeBand and sideBand, share their names with two of Waves’ values, so on Game Rules each pair will share one row under Variables.
Game Start has one Action, a Trigger Custom Event on Object. Its Applies To starts on Self. So the message comes back to Game Rules, the Object that sent it, and Title Screen hears it there. Type showTitle into its box.
For the middle Event, type Game State into the Add Event window’s filter, and pick Game State Changed. It takes no second window. Check Game State’s Action Name reads gameStateResult, so type isOnTitle over it. Its Game State list already shows Title · Initial, and Title is the one you want here.
The If’s condition is isOnTitle.value == true, in its one box. The Trigger Custom Event on Object goes on its True line with Add inside Then. Then right-click the If and choose Add Else. The Else’s four steps come from Add inside Else, one at a time. The first is a Set UI Group Visibility. Type title into its UI Group, bare, and pick No in its Visible list.
The Trigger Custom Event on Object needs @self.prompt in Applies To. Control Sound goes to Stop. Its Sound list gives Space Theme. The last Set UI Group Visibility takes hud, and its Visible stays Yes, as it starts.
Game Start sends showTitle now, so type its name into the Add Event filter, and it’s there. Its Trigger Custom Event, the one for everyone, takes clearField.
The call is in the Functions group of the Action List. Its creator list starts on self, which is what the card wants, so leave it. Pick @self.titleAsteroid in its asteroid list, and type the card’s three values into the number boxes, @self.asteroidsPerBand and the rest. The others follow the card, with Control Sound on Loop this time.
Attach Title Screen to Game Rules. Under Variables, the Values of prompt and titleAsteroid are buttons that read None. Press the first and pick Title Prompt. The second gets Title Asteroid. The three numbers keep the Starting Values you gave them in the Logic.
Run the game. The title is there, with its six rocks and its music, and the prompt blinks. But your old game runs underneath it: the Ship, the score, WAVE 1 and its rocks. Press Enter, and nothing happens yet. The next parts sort that out, one Logic Component at a time.
9.6 A Breath
Before a game can start properly, it needs a way to stop for a moment.
9.6.1 Paused and Paused Help
PAUSED is more than words. It’s a menu, a piece of the screen that takes over the keys while it’s up.
Paused leaves its Element Type as it starts, on Button. Its Group is pause. Four more fields make it a menu. Its Confirm Command is Start, so Enter or Space confirms it. Its Cancel Command is Pause, so Esc or P closes it. Either way it sends gameResumed, which is in both its Event and its Cancel Event. However the menu closes, the game hears the same news.
Paused Help is the small line under it, PRESS ESC TO RESUME, plain Text in the same group.
Window / UICenterUIX 32, Y 32pausegameResumedStartPausegameResumedPAUSEDArcade HUD Font44#DFF6FF6CenterWindow / UICenterUIX 32, Y 32TextpausePRESS ESC TO RESUMEArcade HUD Font12#9FB4D82CenterGroup, Event and Cancel Event are boxes you type into. Confirm Command and Cancel Command are lists of your Commands. Place both words from the Set up card’s PLACE THESE lines, near the middle, and turn off Visible at Game Start on each. The menu shows them when it opens.
9.6.3 Pause
Pause listens for the Pause Command, Esc or P.
You might expect it to open the menu every time. While PAUSED is up, though, the game is held, and Esc belongs to the menu: it closes it. Pause asks first anyway, as a guard. If PAUSED were ever already open when Pause heard its Command, Pause would do nothing, rather than open the menu twice. Check Menu Open looks for Paused, and keeps the answer as isPauseMenuOpen. Only when it’s false does Pause go on.
Next come two messages, each to the whole game at once, the way Waves sends nextWave. The first, gamePaused, is for anyone who needs to know. The second, showPausedMenu, reaches Menu Pause Lifecycle on Game Rules, which shows PAUSED and holds the game.
When the menu closes, it sends gameResumed, and Pause answers with hideMenu. Menu Pause Lifecycle hides PAUSED, and the game goes on.
Pause’s last Event is On Disable. It runs once when Pause is switched off, as a game ends, and it sends hideMenu too. Press Esc in the very moment your last Ship goes, and PAUSED could open over the end of the game. This Event closes it, so GAME OVER is never left under a menu.
Pause (Esc or P) during play holds the game under the PAUSED menu and lets it go on when the menu reports gameResumed; a menu opened as the game ends is closed.
Any Object- Action Name
isPauseMenuOpen- Menu Element
"Paused"
isPauseMenuOpen.value == false- Custom Event
gamePaused
- Custom Event
showPausedMenu
- Custom Event
hideMenu
- Custom Event
hideMenu
Pause has no SHARED VARIABLES, so start with its Event, Command Pressed, and pick Pause in the window that asks for the Command. Check Menu Open’s Action Name reads menuOpenResult. Type isPauseMenuOpen over it. Its Menu Element is a list of the words on your screens, starting on (None). Pick Paused.
The If’s condition is isPauseMenuOpen.value == false. Both Trigger Custom Events go on its True line with Add inside Then, and each message’s name goes in as it is, with no quotes.
Type gameResumed into the Add Event filter, and if nothing comes up, add it with Add Custom Event…. The last Event is On Disable. Type Disable into the filter, and pick On Disable.
Attach Menu Pause Lifecycle and Pause to Game Rules, in that order. Under Variables, the Value of menuElement is a button, the menu this Logic shows and hides. Press it, and pick Paused, the word your menu shows.
9.6.4 Thrust Feedback
Who needs gamePaused? The hum, from Chapter 1. Holding the game doesn’t stop a looping sound. So hold Up, press Esc, and the engine would go on humming over PAUSED. Thrust Feedback’s new gamePaused Event stops Thrust.
gameResumed matters too. You might let go of Up while the game is held, or press it. So when the game goes on, Thrust Feedback starts over from the plain Ship: frame 0, and the two-sided shop sign from Chapter 1 turned back to its Coasting side. If Up is still held, Coasting lights the flame and starts the hum on the very next step.
While Up is held the Ship shows its thrust flame and the thrust sound loops.
Any Object- Clip
"Ship Sprite/Thrust"
- Operation
Loop- Sound
"Thrust"
- Event
While Command Rotate and Thrust Controls Up Is Held- Mode
Thrusting
- Frame
0
- Operation
Stop- Sound
"Thrust"
- Event
While Command Rotate and Thrust Controls Up Is Held- Mode
Coasting
- Operation
Stop- Sound
"Thrust"
- Operation
Stop- Sound
"Thrust"
- Frame
0
- Event
While Command Rotate and Thrust Controls Up Is Held- Mode
Coasting
Both messages are in the project now, so type each name into the Add Event filter. Set Frame’s Frame starts at 0, the card’s. Switch Mode’s two lists are the ones from Chapter 1: the Event with Up Is Held in its name, then Coasting.
9.6.5 Saucer Flight
A saucer’s siren is a looping sound too. Saucer Flight gets three new Events. gamePaused stops the siren, and gameResumed starts it looping again, since the saucer is still flying. The third, playStopped, stops it for good when a game ends while a saucer is out. Nothing sends playStopped yet. Play Switch will.
Its card is the whole Saucer Flight from Chapter 8, so it’s long. The three new Events wait at the bottom, in green.
A saucer enters beyond a random side at a random height, crosses at its speed while weaving up and down, and leaves at the far side.
Any Objectself.saucerFlightData- Action Name
sideRoll- Maximum
1
sideRoll.value == 0- Component Value
self.saucerFlightData.direction- Value
1
- Component Value
self.saucerFlightData.startX- Value
-@self.margin
- Component Value
self.saucerFlightData.direction- Value
-1
- Component Value
self.saucerFlightData.startX- Value
$areaWidth + @self.margin
- Action Name
depthBelowTop- Minimum
@self.minDepth- Maximum
@self.maxDepth
- X
self.saucerFlightData.startX- Y
$areaHeight - depthBelowTop.value
- X Velocity
self.saucerFlightData.direction * @self.speed- Y Velocity
0
- Operation
Loop- Sound
"Saucer Siren"
- Timer Name
nextWeave- Repeat Every (s)
@self.firstWeaveSeconds- Ring Once
Yes
- Timer Name
crossing- Repeat Every (s)
($areaWidth + 2 * @self.margin) / @self.speed- Ring Once
Yes
- Action Name
weaveRoll- Minimum
-1- Maximum
1
- Y Velocity
weaveRoll.value * @self.weaveSpeed
- Action Name
weaveSeconds- Minimum
@self.weaveMinSeconds- Maximum
@self.weaveMaxSeconds
- Timer Name
nextWeave- Repeat Every (s)
weaveSeconds.value- Ring Once
Yes
self.transform.position.y > $areaHeight- X
self.transform.position.x- Y
self.transform.position.y - $areaHeight
self.transform.position.y < 0- X
self.transform.position.x- Y
self.transform.position.y + $areaHeight
- Operation
Stop- Sound
"Saucer Siren"
- Operation
Stop- Sound
"Saucer Siren"
- Operation
Loop- Sound
"Saucer Siren"
- Operation
Stop- Sound
"Saucer Siren"
gamePaused and gameResumed are in the Add Event filter. playStopped is new, so add it with Add Custom Event…. Each Control Sound takes its Operation and Saucer Siren from its lists.
Run the game, and press Esc. PAUSED comes up. The rocks stop where they are, and so does everything else. Press Esc again.
They all go on.
9.7 Press Enter
Now the title and the game take turns.
9.7.1 Start Game
Start Game listens for the Start Command, which is Enter or Space.
It only works in two places: on the title, and when Play Again is offered. So it checks both, isOnTitle and isOfferingPlayAgain, and an If with Or asks whether either is true.
When one is, Start plays, and clearField empties space. Last, Set Game State makes it Playing.
The order matters here. When Waves sees a field with no rocks, it starts the next wave. If the game were Playing first, the title’s rocks would vanish under a game in progress, and Waves would count that as a cleared field. Emptied first, they go before anyone is counting.
Start (Enter or Space) on the title or after a game over clears space and starts a game.
Any Object- Action Name
isOnTitle- Game State
Title
- Action Name
isOfferingPlayAgain- Game State
Play Again
isOnTitle.value == true || isOfferingPlayAgain.value == true- Sound
"Start"
- Custom Event
clearField
- Game State
Playing
Start Game has no SHARED VARIABLES, so begin with Command Pressed, and pick Start in its second window. Each Check Game State arrives on Title · Initial. The first, isOnTitle, keeps it, and the second, isOfferingPlayAgain, needs Play Again picked.
The If’s one box takes both tests, joined by ||, which means or: isOnTitle.value == true || isOfferingPlayAgain.value == true. On the True line, Control Sound plays Start, from its Sound list. Trigger Custom Event takes clearField. Set Game State needs Playing picked in its list.
Attach Start Game to Game Rules.
9.7.2 Lives and Respawn
Four pieces of Logic on Game Rules used to start at Game Start: Lives and Respawn, Waves, Extra Ships and Saucer Spawner. Now they start whenever a game does. Their new Event is On Enable. It runs once, each time the Logic is switched on.
You don’t build the Event again. Right-click the Game Start block and choose Change Event…. Type Enable into the window’s filter, pick On Enable, and press OK. Myth Engine asks to be sure: it will change “When the game starts” to “When this Logic is enabled”, and 1 Mode and its Actions will be kept. Press Change Event. On the card, that’s the struck Game Start line with On Enable in green above it.
Lives and Respawn changes most. Its new Event, spawnShip, makes a Ship in the middle. On Enable sends it, so every game begins with a Ship, and the respawnDelay timer sends it for each Ship after a crash.
The last change is the ending. When lives run out, the If’s new Else sets the Game State to Game Over.
The game starts with startLives; each lost Ship costs one, and a new Ship comes after respawnSeconds while lives are left.
Any Object- Variable
$lives- Value
@self.startLives
- Custom Event
spawnShip
- Variable
$lives- Operator
-=- Value
1
$lives > 0- Timer Name
respawnDelay- Repeat Every (s)
@self.respawnSeconds- Ring Once
Yes
- Game State
Game Over
- Custom Event
spawnShip
- Object to Create
@self.ship- X
$areaWidth / 2- Y
$areaHeight / 2- Created As
newShip
- Sound
"Ship Respawn"
First, On Enable’s Trigger Custom Event on Object. Add it from Mode 1’s right-click, type spawnShip into its box, and Connect to sequence joins it after Change Variable. Now that something sends spawnShip, add its Event: type spawnShip into the Add Event filter, and there it is.
Then the move. The Create Instance and Control Sound in the respawnDelay Event go to spawnShip, and you don’t build them again. On the card, they sit plain under On Spawn Ship, because they aren’t new. Nothing is struck where they were. Click Create Instance, then Shift+click Control Sound to select both. Right-click either one and choose Cut 2 blocks. Then right-click the empty spot close beside On Spawn Ship’s Mode 1, on its right, and choose Paste, as you did for breakUp in Chapter 8. The two arrive loose. Connect to sequence on Create Instance joins them both.
Back in the respawnDelay Event, a Trigger Custom Event on Object takes their place. Add it from that Event’s Mode 1, and type spawnShip.
Last, right-click the If in the shipDestroyed Event and choose Add Else. Right-click the Else, choose Add inside Else, and pick Set Game State. It arrives with Title · Initial in its list. Pick Game Over. Connect to sequence joins it to the False line.
9.7.3 Waves, Extra Ships and Saucer Spawner
The other three change the same way.
Waves and Saucer Spawner also get On Disable, as Pause did. On Disable is for tidying up. A switched-off Logic hears nothing, so it can’t tidy up later. But its timers keep counting, on into the next game, and a banner it showed stays up. So On Disable runs once, as the Logic is switched off, and stops what play started. Waves stops its bannerTime and sectorJump timers and hides the banner. Saucer Spawner stops its saucerCheck timer.
On these three cards, look at the When bar at the top of each. On Disable, where there is one, is at the bottom. The steps between are ones you built before.
Each wave announces itself with the banner, then brings its Large Asteroids; clearing every Asteroid starts the sector jump and then the next wave.
Any Object- Variable
$wave- Value
0
- Custom Event
nextWave
- Variable
$wave- Operator
+=- Value
1
- Applies To
@self.banner- Visible
Yes
- Timer Name
bannerTime- Repeat Every (s)
@self.bannerSeconds- Ring Once
Yes
- Name
perBandThisWave- Value
1
- Applies To
@self.banner- Visible
No
- Variable
perBandThisWave- Value
$wave + 1
perBandThisWave > @self.maxAsteroidsPerBand- Variable
perBandThisWave- Value
@self.maxAsteroidsPerBand
- creator
self- asteroid
@self.asteroid- perBand
perBandThisWave- edgeBand
@self.edgeBand- sideBand
@self.sideBand
- Sound
"Sector Clear"
- Sound
"Hyper"
- Timer Name
sectorJump- Repeat Every (s)
@self.jumpSeconds- Ring Once
Yes
- Custom Event
nextWave
- Timer Name
bannerTime
- Timer Name
sectorJump
- Applies To
@self.banner- Visible
No
Each time the score passes another extraShipEvery points, the player gains a life, with a sound and an "EXTRA SHIP" popup.
Any Objectself.extraShipsData- Component Value
self.extraShipsData.nextExtraShipAt- Value
@self.extraShipEvery
$score >= self.extraShipsData.nextExtraShipAt- Variable
$lives- Operator
+=- Value
1
- Component Value
self.extraShipsData.nextExtraShipAt- Operator
+=- Value
@self.extraShipEvery
- Sound
"ExtraLife"
- Text
EXTRA SHIP- Color
@self.popupColor- Size
@self.popupSize- Rise
@self.popupRise- Seconds
@self.popupSeconds- Position Relative To
World- X
$areaWidth / 2- Y
$areaHeight / 2 + @self.popupAboveCenter
The first saucer comes firstSeconds into the game. After that, a saucer check comes a random number of seconds later (fewer in later waves) and sends a saucer when none is flying; the Small one comes more often in later waves and always at high scores.
Any Object- Timer Name
saucerCheck- Repeat Every (s)
@self.firstSeconds- Ring Once
Yes
- Name
gapMax- Value
0
- Name
gapMin- Value
0
- Action Name
isSaucerFlying- Object
tag:Saucer- Operator
>- Value
0
isSaucerFlying.value == false- Action Name
saucerRoll
$score >= @self.smallAlwaysScore || saucerRoll.value < (@self.smallChance + @self.smallChancePerWave * $wave)- Object to Create
@self.smallSaucer- Created As
newSmallSaucer
- Object to Create
@self.largeSaucer- Created As
newLargeSaucer
- Variable
gapMin- Value
@self.gapMinStart - $wave
gapMin < @self.gapMinFloor- Variable
gapMin- Value
@self.gapMinFloor
- Variable
gapMax- Value
@self.gapMaxStart - $wave
gapMax < @self.gapMaxFloor- Variable
gapMax- Value
@self.gapMaxFloor
- Action Name
checkSeconds- Minimum
gapMin- Maximum
gapMax
- Timer Name
saucerCheck- Repeat Every (s)
checkSeconds.value- Ring Once
Yes
- Timer Name
saucerCheck
Each On Disable comes from the Add Event filter, as Pause’s did. Each Stop Recurring Timer takes its timer’s name bare, bannerTime and the rest. Waves’ Set Visible picks @self.banner in its Applies To, and No in its Visible list.
9.7.4 Saucer Gun
A saucer in flight isn’t on Game Rules, so nothing switches it. It hears the game end another way. Play Switch sends a message to everything, playStopped, when a game is over. Saucer Flight already listens for it. Now Saucer Gun does too, and stops its saucerFire timer.
The saucer drifts on across, silent.
A saucer fires its own shot every fireEvery seconds, with the pulse sound.
Any Object- Timer Name
saucerFire- Repeat Every (s)
@self.fireEvery
- Object to Create
@self.shot- Position Relative To
Self- Created As
newShot
- Sound
"Saucer Pulse"
- Timer Name
saucerFire
playStopped is in the Add Event filter now, because Saucer Flight listens for it.
9.7.5 Play Switch
Play Switch is the piece the others wait for.
It listens for Game State Changed and asks one question: is it Playing now? If it is, Set Logic State switches on five Logic Components, one Action each: Lives and Respawn, Waves, Extra Ships, Saucer Spawner and Pause. Each one’s On Enable runs, and a game begins.
Anything else, and the Else switches the same five off, with State Disable, and sends playStopped. Remember the message Saucer Flight was waiting for? This is who sends it.
Set Logic State has no Applies To line, so it switches them on its own Object, Game Rules.
Switches the Logic that only makes sense during play on when a game starts, and off when it ends.
Any Object- Action Name
isPlaying- Game State
Playing
isPlaying.value == true- Logic Component
"Lives and Respawn"
- Logic Component
"Waves"
- Logic Component
"Extra Ships"
- Logic Component
"Saucer Spawner"
- Logic Component
"Pause"
- Logic Component
"Lives and Respawn"- State
Disable
- Logic Component
"Waves"- State
Disable
- Logic Component
"Extra Ships"- State
Disable
- Logic Component
"Saucer Spawner"- State
Disable
- Logic Component
"Pause"- State
Disable
- Custom Event
playStopped
Play Switch has no SHARED VARIABLES. Check Game State’s list needs Playing picked. Each Set Logic State’s Logic Component is a list of your Logic Components, so pick the card’s, such as Lives and Respawn. The five on the True line keep State on Enable.
Add Else gives the Else, and Add inside Else gives each of its six steps. Their State list goes to Disable, and the Trigger Custom Event, playStopped, comes last.
Attach Play Switch to Game Rules, last. Now turn off the switch beside five names in the Attached Logic: Lives and Respawn, Waves, Extra Ships, Saucer Spawner and Pause. On the Game Rules card at the end of this chapter, each one says (turned off). They start the game switched off, because the game starts on the title.
Why not let each one check the Game State for itself? Without Play Switch, sixteen Events in this game would each start by asking whether a game is on. Switched-off Logic doesn’t need to ask.
Last, do the Set up card’s REMOVE THESE PLACEMENTS block. Click the Ship in Space’s Scene Explorer and press Delete. spawnShip makes every Ship now, the first one included.
Run the game. The title waits, with nothing else going on. Press Enter. The rocks vanish, Start sounds, a Ship appears in the middle, and WAVE 1 comes up. Esc pauses. On the title, it does nothing.
Lose all your Ships. Everything stops. No new Ship, no waves, no saucers. The rocks drift on, and Enter does nothing. It’s the Game Over Game State, but nothing on the screen says so yet.
9.8 Only During Play
The numbers at the top still show over the title. They belong to play.
9.8.1 Score Display, High Score Display and Wave Display
Give each one the Group hud. Then do the Set up card’s CHANGE THESE PLACEMENTS block: turn off Visible at Game Start on each of their placements. Title Screen already hides and shows the hud group, so they come and go with the game.
Window / UIUIX 32, Y 32Texthud{$score}Arcade HUD Font24#F2FBFFWrap to Width260Window / UITop CenterUIX 32, Y 32TexthudHI {$highScore}Arcade HUD Font12#9FB4D8CenterWindow / UITop RightUIX 32, Y 32TexthudWAVE {$wave}Arcade HUD Font12#9FB4D8RightWrap to Width180The tiny Ships in the corner need nothing new. Each Life Icon shows only while $lives reaches its slot. Over the title, $lives is still 0, where Chapter 5’s setup card starts it. When a game begins, Lives and Respawn sets it to three, and the icons appear.
Run it. The title is clean now. Start a game, and the score, the high score, the wave and three tiny Ships appear.
9.9 The End of a Game
Last, the game learns to say it’s over, and to keep your best.
9.9.1 Game Over, Final Score and Play Again Prompt
GAME OVER is big and pink-red, and FINAL SCORE reads {$score}, with two spaces before the brace, as HIGH SCORE has. They share the Group gameOver.
Play Again Prompt blinks, like Title Prompt, and like it, it’s in no group. Here’s why. A group looks like a box that keeps its words hidden. It isn’t. Set UI Group Visibility flips each word’s own switch, the same one Blink’s Set Visible flips, and the last flip wins. In the gameOver group, PRESS ENTER TO PLAY AGAIN would show the moment GAME OVER does, two seconds before Enter works. Out of any group, only Blink shows it, and Game Over Screen tells Blink when.
Window / UICenterUIX 32, Y 32TextgameOverGAME OVERArcade HUD Font48#FF6B8B6CenterWindow / UICenterUIX 32, Y 32TextgameOverFINAL SCORE {$score}Arcade HUD Font16#DFF6FFCenterWindow / UICenterUIX 32, Y 32TextPRESS ENTER TO PLAY AGAINArcade HUD Font16#FFD1662CenterBlinkBlink DataPlay Again Prompt carries Blink, as Title Prompt does, and Blink Data comes with it. Place all three near the middle, from the Set up card’s PLACE THESE lines, and turn off Visible at Game Start on each.
9.9.2 Game Over Screen
Game Over Screen goes on Game Rules. Most of its card is one idea. Every time the Game State changes, it clears the stage first, then sets it.
So the Game State Changed Event opens with a clean sweep. Its two timers stop, playAgainDelay and returnToTitle, and the gameOver group goes dark, and so does the blinking prompt. Then it asks which Game State this is. Each of the two it knows gets its words and its timer.
Count the beats. The last Ship goes, and GAME OVER comes up. Two seconds. Enter does nothing yet. When playAgainDelay rings, its Event sets the Game State to Play Again. PRESS ENTER TO PLAY AGAIN blinks. Twelve seconds. Then returnToTitle rings, and its Event sets the Game State back to Title.
Every change stops both timers first. So a timer can never ring in the wrong Game State. Press Enter during Play Again, and returnToTitle is stopped before it can send you anywhere.
After the last Ship: GAME OVER and the final score; playAgainSeconds later, the offer to play again; returnSeconds after that, the title.
Any Object- Timer Name
playAgainDelay
- Timer Name
returnToTitle
- UI Group
gameOver- Visible
No
- Applies To
@self.playAgainPrompt- Custom Event
stopBlinking
- Action Name
isGameOver- Game State
Game Over
isGameOver.value == true- UI Group
gameOver
- Timer Name
playAgainDelay- Repeat Every (s)
@self.playAgainSeconds- Ring Once
Yes
- Action Name
isOfferingPlayAgain- Game State
Play Again
isOfferingPlayAgain.value == true- UI Group
gameOver
- Applies To
@self.playAgainPrompt- Custom Event
startBlinking
- Timer Name
returnToTitle- Repeat Every (s)
@self.returnSeconds- Ring Once
Yes
- Game State
Play Again
- Game State
Title
Its three SHARED VARIABLES come first, all Constant: playAgainPrompt, an Object with its None button, then two Numbers. The Stop Recurring Timers take their names bare. The Trigger Custom Event on Object picks @self.playAgainPrompt in Applies To. Check Game State arrives on Title · Initial. Pick Game Over for isGameOver. The first If’s two steps go on its True line with Add inside Then.
The second Check Game State goes on the main line, below the first If, where Connect to sequence puts it. It takes Play Again, and its If gets the last three steps. Each timer’s own Event is a Recurring Timer, named as the card names it.
Attach Game Over Screen to Game Rules. Under Variables, press the None button of playAgainPrompt and pick Play Again Prompt.
9.9.3 Score
Remember Score’s Game Start, from Chapter 7? It set $score to 0, for the day a new game could begin without the whole program starting over. That day is here, so the 0 moves. A new Game State Changed Event sets it when the game becomes Playing.
The same Event saves your best. When the Game State is Game Over, Save Persistent Value stores $highScore under the key highScore. A persistent value stays on this computer after the game is closed.
Game Start does the other half. Load Persistent Value reads the key back, as savedHighScore, with 0 if nothing was saved yet. If it’s higher than $highScore, it becomes the high score.
The score starts at 0 each game; the high score follows it whenever the score passes it.
Any Object- Variable
$score- Value
0
- Action Name
savedHighScore- Key
"highScore"- Default
0
savedHighScore.value > $highScore- Variable
$highScore- Value
savedHighScore.value
- Action Name
isPlaying- Game State
Playing
isPlaying.value == true- Variable
$score- Value
0
- Action Name
isGameOver- Game State
Game Over
isGameOver.value == true- Action Name
persistentWriteResult- Key
"highScore"- Value
$highScore
$score > $highScore- Variable
$highScore- Value
$score
In Game Start, right-click the old Change Variable and choose Delete. The three new steps join the usual way. The Change Variable goes in with Add inside Then. Load Persistent Value’s Action Name reads persistentValueResult, so type savedHighScore over it. Its Key takes "highScore", quotes and all. Its Default is 0. Save Persistent Value’s Action Name already reads persistentWriteResult. Nothing in the game reads that answer, so leave the name as it is.
The new Event is a Game State Changed, built like Game Over Screen’s: two Check Game States, each followed by its If. The second Check Game State joins the main line below the first If, as Connect to sequence puts it.
9.9.4 Break Apart and Saucer Explodes
A Shot fired a moment before the last crash can still be flying when the game ends. It still breaks what it hits, but it shouldn’t score.
So both pieces ask Check Game State whether it’s Playing, and only then count the points. The three scoring steps from Chapters 7 and 8 now sit on an If’s True line.
An Asteroid hit by the player scores and shows its points; any Asteroid that breaks up bursts into sparks, plays its break sound, leaves its fragments and is destroyed.
Any Object- Variable
$score- Operator
+=- Value
@self.points
- Custom Event
scored
- Text
text(@self.points)- Color
@self.popupColor- Size
@self.popupSize- Rise
@self.popupRise- Seconds
@self.popupSeconds
- Action Name
isPlaying- Game State
Playing
isPlaying.value == true- Variable
$score- Operator
+=- Value
@self.points
- Custom Event
scored
- Text
text(@self.points)- Color
@self.popupColor- Size
@self.popupSize- Rise
@self.popupRise- Seconds
@self.popupSeconds
- Custom Event
breakUp
- Particles
"Impact Sparks"- Count
@self.sparkCount
- Sound
@self.breakSound
@self.shake > 0- Intensity
@self.shake- Seconds
@self.shakeSeconds
@self.fragmentstimes- Object to Create
@self.fragment- Position Relative To
Self- Created As
newFragment
A saucer that is hit gives the player its points, shows them, explodes and is destroyed.
Any Object- Variable
$score- Operator
+=- Value
@self.points
- Custom Event
scored
- Text
text(@self.points)- Color
@self.popupColor- Size
@self.popupSize- Rise
@self.popupRise- Seconds
@self.popupSeconds
- Action Name
isPlaying- Game State
Playing
isPlaying.value == true- Variable
$score- Operator
+=- Value
@self.points
- Custom Event
scored
- Text
text(@self.points)- Color
@self.popupColor- Size
@self.popupSize- Rise
@self.popupRise- Seconds
@self.popupSeconds
- Particles
"Ship Explosion"- Count
@self.explosionCount
- Sound
"ExplosionLarge"
- Intensity
@self.shake- Seconds
@self.shakeSeconds
In Break Apart’s hit Event, two new blocks go first. Add Check Game State and the If from Mode 1’s right-click, and join them with the round handles, as in Chapter 7. Click the handle at the bottom of Mode 1, then the one at the top of Check Game State. Then click the bottom of Check Game State, and the top of the If. Check Game State takes isPlaying and Playing, and the If’s condition is isPlaying.value == true.
Now the three scoring steps move. They go onto the If’s True line, with Cut and Paste. An empty True line gives Paste nowhere to land, and Paste on the If itself would put them beside it, not inside. So give the True line a block for a moment. Right-click the If, choose Add inside Then, and pick Destroy Instance. Then click Change Variable, Shift+click Popup Text, right-click, and choose Cut 3 blocks. Right-click the new Destroy Instance and choose Paste. The three arrive loose, inside the If. Delete that Destroy Instance, and Connect to sequence on Change Variable joins all three to the True line.
The card shows the three struck at the top, where they stood, and new on the True line. The move does both. The Trigger Custom Event on Object that sends breakUp now follows the If.
Saucer Explodes changes the same way, and its three sit above Burst Particles. Its line ends with a Destroy Instance of its own, so delete only the loose one you added.
9.9.5 Game Rules
Here’s Game Rules with everything this chapter attached. Four of its rows show only (turned off) in green: Lives and Respawn, Waves, Extra Ships and Saucer Spawner. Each is a Logic Component you attached long ago, and only its switch changes. Keep it, with its boxes, and make sure its switch is off. Pause is new, and switched off too.
Its order isn’t quite the order you made them in, and the game plays the same either way. If you’d like yours to match the card, drag the rows by their grips, or click a grip and use Alt with the arrows.
Extra ShipsExtra Ships DataShipAsteroid LargeWave BannerSaucer LargeSaucer SmallTitle PromptTitle AsteroidPlay Again PromptPausedRun the game, and play it through. Lose your last Ship, and GAME OVER comes up with your score. Wait. PRESS ENTER TO PLAY AGAIN starts to blink. Press it, and a new game starts at 0, with your high score at the top. Or wait twelve seconds, and the title comes back, with HIGH SCORE showing your best.
Watch for each of these.
- The game opens on the title: SHATTERFIELD, the tagline, the controls line, HIGH SCORE, and six Large rocks drifting. The music plays.
- PRESS ENTER TO START blinks, about half a second on and half a second off.
- No score, no wave and no tiny Ships on the title.
- Press Enter. The rocks vanish without a spark, Start plays, and a Ship appears in the middle with WAVE 1.
- Press Enter again during play. Nothing happens.
- Esc or P shows PAUSED and PRESS ESC TO RESUME, and everything stops. Esc, P, Enter or Space goes on.
- Hold Up and press Esc, and the engine hum stops. Keep Up held as the game goes on, and the flame and the hum come back.
- A saucer’s siren stops under PAUSED and starts again when the game goes on.
- Lose your last Ship. GAME OVER and FINAL SCORE come up, and the saucer siren stops.
- For two seconds Enter does nothing. Then PRESS ENTER TO PLAY AGAIN blinks, and Enter starts a new game at 0.
- Wait instead, and the title comes back about 14 seconds after GAME OVER, with your best as HIGH SCORE. Its rocks are Standard and slow again, however far you got.
- Stop the game and run it again. HIGH SCORE still shows your best.
The title shows, a game starts, a game ends, and the title comes back. Each of those is a change of Game State. Title Screen, Game Over Screen, Score and Play Switch all hear every change, and each asks the same question: what is it now?
Underneath them is one idea. Don’t make every piece of Logic check whether a game is on. Switch it off when it isn’t needed. Play Switch turns the play-only Logic on with the game and off after it, and On Enable and On Disable let each one start and tidy up for itself.
9.10 If It Didn’t Work
Something may be a little off the first time, and that’s normal. Run the game, play it through to GAME OVER, and watch.
The game starts playing behind the title? Look at Game Rules’ Attached Logic. Five switches need to be off: Lives and Respawn, Waves, Extra Ships, Saucer Spawner and Pause.
Enter does nothing on the title? Perhaps Menus still reads Inactive at Start in the Input Manager, so click it. Or look at the Start Command itself, in Menus. Its two rows should read Enter and Space.
P pauses, but Esc doesn’t? The Pause Command’s first row may still read No Input Assigned. Click it and press Escape twice, quickly.
No Ship after Enter? Lives and Respawn’s On Enable needs the Trigger Custom Event on Object, sending spawnShip. And check that the Value of ship, under Game Rules’ Variables, still says Ship.
WAVE 2 comes straight after WAVE 1? Perhaps Start Game sets Playing before clearField. Set Game State has to be last, so move it below Trigger Custom Event with the handles.
PRESS ENTER TO PLAY AGAIN shows the moment GAME OVER does? Play Again Prompt may have a Group, typed in by habit. Empty its Group box.
PAUSED never closes? Look at Paused’s UI Interaction: Confirm Command Start, Cancel Command Pause, and gameResumed in both Event and Cancel Event. And Pause’s gameResumed Event should send hideMenu.
The engine hums on under PAUSED? Thrust Feedback’s gamePaused Event needs its Control Sound on Stop, with Thrust.
Esc pauses on the title? Pause needs its switch off on Game Rules, and its two lines in Play Switch.
GAME OVER never comes? Lives and Respawn’s If needs its Else, with Set Game State on Game Over. Its list starts on Title, so check it.
Every rock scores twice? The scoring steps may have been copied, not cut, so the old three still sit below the If in Break Apart. Delete those three.
No points rise off a broken rock at all? Perhaps the three scoring steps landed beside the If, with no arrow into them. Cut them again, and paste them on a block inside the If, as above.
The title’s rocks wear a later wave’s material? Title Asteroid’s wave row may still read Expression in its Kind list. Pick Constant, and it reads 1.
The high score is gone the next time? Score’s Save Persistent Value and Load Persistent Value need the same Key, "highScore".
Each of these is a small fix. Make it, run the game again, and you’re back with the chapter. The catch-up download in the Goal is this chapter, finished, if you’d like to compare.
What would your title say? Change the tagline to your own words, or give SHATTERFIELD a new color. Try playAgainSeconds at 5, under Game Rules’ Variables. Or set asteroidsPerBand to 6, and fill the whole title with drifting rocks. Chapter 10 is written for the card’s numbers. Set them back before you go on, and write yours down if you’d like to keep them.
Still stuck? Search the manual, or ask in the Myth Engine Discord (opens a new tab).
Your game has a front door now, and a way home. In Chapter 10, the field gets a heartbeat.
