- Learn
- Build a Game
- Crystal Cascade
- 9 Countdown and Pause
9 Countdown and Pause
Give your well a breath before play begins, and a pause whenever you need one.
Click the game, then press Enter. Choose a mode, watch the countdown, and press Escape or P to pause.
Use this project for comparison.
To open it, right-click the downloaded file, choose Extract All... and then Extract. Start Myth Engine, choose File › Open Project... and pick the .mythproj file in the new folder. Nunito-OFL.txt beside it comes with the game.
9.1 The Idea
The glass well waits. READY sits above it, and a number fills its middle. The count falls from three to one, with a chime on each beat. GO! A piece falls.
Until now, entering Gameplay started its clocks and invited the first piece at once. This time the Scene can arrive before play begins. One message, playStarted, opens that gate for the piece and its clocks.
The other quiet moment comes under your hand. Press Escape and the crystals stop where they are. A glass panel covers the well, offering RESUME, RESTART and MAIN MENU.
This is the engine’s pause. Timers wait with the piece, while the menu can still listen. The clock keeps its place too. Think of a bookmark held between two stretches of play.
Zen finally gets its way home. Earn a score above its saved best. If the well fills, Zen clears it and that score keeps growing. RESTART discards this attempt’s score and begins again. MAIN MENU keeps that better score as your record, ready for the next time you play. It returns you to the choices over the sky.
9.2 The Plan
- Count Down holds Play’s controls -> playStarted lets Deal Pieces send the first piece.
- The same message starts Time The Game and Ultra’s finishing timer. The countdown pictures give way to GO!.
- Pause The Game asks Myth to pause -> the panel opens and Menus keeps listening.
- RESUME returns to the waiting piece. RESTART begins this mode again; MAIN MENU leaves it, giving Zen a chance to save.
9.3 Set Up
Continue your completed Chapter 8 project, or open Chapter 8 finished. This is the starting project, with its menu already working. Keep its choosing Logic, prepared panel declarations, Fade Out Message and game clocks. This chapter uses those pieces again.
Check for Panel State, Choose Panel Choice, Panel Choices, Panel Choice and Show When Panel Choice. Their reference below gives their jobs and complete cards. For now, check that all five resources exist. Leave the complete cards as a reference unless a piece is missing. Missing any of them? Open Chapter 8 finished before continuing, keeping its existing resources together. That download also brings the earlier Functions and messages these cards call, including the Main Menu’s help responses.
These are existing resources to compare, rather than another set to add. Keep one of each. The pause will give their choosing work a new home.
9.3.1 Panel State
A panel remembers whether it is open and which button has the glow. Panel State keeps that memory. Its chosen field counts from 0, the first choice. isOpen keeps closed panels from answering keys. Each button adds itself to choiceCount when created, so navigation knows where to wrap.
What a panel of choices keeps: chosen, the choice chosen now (0 = the top one); isOpen, the panel is open and its choices can be chosen. choiceCount: how many choices it has (each choice adds itself when created).
9.3.2 Choose Panel Choice
Moving the glow needs one shared announcement. Choose Panel Choice changes the remembered choice and tells the pictures to look again. Its panel Parameter identifies the panel carrying that memory.
Makes choice the chosen choice of a panel (its Panel State chosen) and tells the highlights. The only writer of chosen.
panelStateData StructurePanel State- Component Value
panel.panelState.chosen- Value
choice
- Custom Event
panelChoiceChanged
9.3.3 Panel Choices
The panel opens and closes on messages. While open, it lets Up and Down move the choice around. Panel Choices finds that memory through self.panelState, the component on its own Object. Give Pause Panel that component before attaching this Logic below. Closing resets the choice.
A panel of choices: opens on its chosen choice when told (panelOpened; the top one unless the Logic that opens it chose another), closes when told (panelClosed), going back to its top choice, and while open Up / Down choose the choice above or below, going round at either end, with Menu Bubble.
Any Objectself.panelState- Component Value
self.panelState.isOpen- Value
true
- panel
self- choice
self.panelState.chosen
- Component Value
self.panelState.isOpen- Value
false
- Component Value
self.panelState.chosen- Value
0
- Custom Event
panelChoiceChanged
self.panelState.isOpen == true- panel
self- choice
mod(self.panelState.chosen - 1 + self.panelState.choiceCount, self.panelState.choiceCount)
- Sound
Menu Bubble
self.panelState.isOpen == true- panel
self- choice
mod(self.panelState.chosen + 1, self.panelState.choiceCount)
- Sound
Menu Bubble
- Event
When Menu Navigate Up Is Pressed- Mode
While Help Is Open
- Event
When Menu Navigate Down Is Pressed- Mode
While Help Is Open
- Event
When Menu Navigate Up Is Pressed- Mode
Choose The One Above
- Event
When Menu Navigate Down Is Pressed- Mode
Choose The One Below
9.3.4 Panel Choice
Each button needs to know which panel it belongs to. Its Shared Variable panel points there. The other Shared Variable, choice, identifies this button within that panel. Panel Choice lets the keyboard and mouse choose the same button. Confirm sends choiceRun to the button.
One choice of a panel: while the panel is open, Confirm runs it when it is the chosen choice; the mouse over it chooses it, and a click on it runs it. Running it plays Menu Select and tells its own button (choiceRun), whose other Logic does the work of the choice. While the How to Play panel covers the Main Menu, the choices do nothing, and Confirm on the chosen one closes it.
Any ObjectObjects with Panel State- Component Value
@self.panel.panelState.choiceCount- Operator
+=- Value
1
@self.panel.panelState.isOpen == true && @self.panel.panelState.chosen == @self.choice- Sound
Menu Select
- Custom Event
choiceRun
@self.panel.panelState.chosen != @self.choice- panel
@self.panel- choice
@self.choice
- Sound
Menu Bubble
- panel
@self.panel- choice
@self.choice
- Sound
Menu Select
- Custom Event
choiceRun
- Event
When Confirm Is Pressed- Mode
While Help Is Open
- Event
On Mouse Enter- Mode
While Help Is Open
- Event
When Left Is Clicked- Mode
While Help Is Open
- Event
When Confirm Is Pressed- Mode
Run If Chosen
- Event
On Mouse Enter- Mode
Choose This One
- Event
When Left Is Clicked- Mode
Run This One
@self.panel.panelState.chosen == @self.choice9.3.5 Show When Panel Choice
The brighter picture listens for a changed choice. Show When Panel Choice compares its Per Instance Variable choice with the panel’s memory. Both must match. The panel must be open too. Its Shared Variable panel points to the same panel as the button underneath. The button keeps choice on its Object, while each brighter picture placement can carry its own choice override.
The highlight over one choice of a panel: shown while its panel is open and its choice is the chosen one, hidden otherwise.
Any ObjectObjects with Panel State- Custom Event
panelChoiceChanged
@self.panel.panelState.isOpen == true && @self.panel.panelState.chosen == self.choice- Visible
Yes
- Visible
No
Chapter 8 finished includes all these declarations and the behavior that makes its existing menus work. Keep the prepared panel references: they expose Panel State’s fields. If rebuilding earlier chapters, Chapter 6’s panel passage supplies the declaration pack and its installation. The pack prepares declarations only; these cards give the behavior. Keep your finished choosing Logic.
The extra help Modes belong to the Main Menu you already made. Leave them in place. The pause sends panelOpened and panelClosed, so it uses the ordinary choosing responses.
Add Pause as a Button Command in its new Pause context. The card gives that Command two keys, so either can ask the well to wait. Leave that context Inactive at Start; Gameplay will activate it.
Menus needs another permission. Turn its Works While Paused switch On, so its Commands can reach the panel while the rest of play waits. Keep Play and Pause without that permission. Selecting a context for editing still doesn’t activate it.
Add countdown to Globals. Its text will read the number directly. The placement list has two groups: the countdown first, then the pause panel. Make each Object before returning to place it.
Escape, PPauseOn9.4 A Well That Waits
The first piece has to wait for its invitation.
9.4.1 Count Down
Count Down owns the wait. It sets the opening number, keeps Play’s controls off, and starts a beat that lowers the number each second. The first beep waits for the first frame, so loading the Scene doesn’t stretch that first beat.
The count starts at 3. Each ring takes one away. While a number remains, another beep sounds; at zero, the timer stops and the invitation goes out. Nothing else needs its own countdown.
Make this Logic and attach it to Game Rules after Count Pieces. Its shared countdownSeconds keeps the starting count. Its card supplies the exact Events and Actions that turn those waiting seconds into a beginning.
Counts down before play: $countdown from countdownSeconds to 1, one a second, each with Countdown Beep; then Countdown Go, the play controls on, and playStarted to everyone.
Any Object- Input Context
Play- Active
No
- Variable
$countdown- Value
@self.countdownSeconds
- Timer Name
"countdownBegins"- First Delay (s)
0- Ring Once
Yes
- Sound
Countdown Beep
- Timer Name
"countdownTick"
- Variable
$countdown- Operator
-=- Value
1
$countdown > 0- Sound
Countdown Beep
- Timer Name
"countdownTick"
- Sound
Countdown Go
- Input Context
Play
- Custom Event
playStarted
9.4.2 Deal Pieces
The queue shuffles ahead. Remove nextPieceDue from When Created and send it from On Play Started instead. The bags wait, ready. Only When Created and On Play Started change here. Keep the other Events.
Keeps the Queue table full of pieces from shuffled bags of seven: deals two bags at the start, takes the first piece off whenever one is dealt, and adds a bag whenever fewer than seven are left.
Any Objectself.dealPiecesData- Table
Queue
- Component Value
self.dealPiecesData.queueLength- Value
0
2times- firstPlace
self.dealPiecesData.queueLength
- Component Value
self.dealPiecesData.queueLength- Operator
+=- Value
dataCount('Piece Kinds')
- Custom Event
nextPieceDue
- Name
placeRow- Value
0
- Variable
placeRow- Value
0
placeRow < (self.dealPiecesData.queueLength - 1)- Name
placeKind- Value
data('Queue', placeRow + 1, 'piece')
- Table
Queue- Row
placeRow- Column
"piece"- Value
placeKind
- Variable
placeRow- Operator
+=- Value
1
- Table
Queue- Row
placeRow- Column
"piece"
- Component Value
self.dealPiecesData.queueLength- Operator
-=- Value
1
self.dealPiecesData.queueLength < dataCount('Piece Kinds')- firstPlace
self.dealPiecesData.queueLength
- Component Value
self.dealPiecesData.queueLength- Operator
+=- Value
dataCount('Piece Kinds')
- Custom Event
queueChanged
- Custom Event
nextPieceDue
9.4.3 Show Piece Crystal
Before the invitation, no falling crystal should be waiting in the middle of the screen. The new Create Event hides both the piece’s crystals and its ghost. pieceMoved will place them. Only the marked Create Event is new here. Leave the remaining Events in place; they still draw and dim the moving crystals.
One crystal of the falling piece: whenever the piece moves, it goes to its cell (or, with showsLanding, to its cell in the landing row: the ghost) and shows the piece's color; it hides in the two hidden rows, and the piece's own crystals fade while it rests before locking.
Any ObjectFalling Piece- Which
Value- Value
self.transform.opacity
- Action Name
thisCrystal- kind
@self.piece.piece.kind- rotation
@self.piece.piece.rotation- crystal
self.crystal
- Name
cellColumn- Value
@self.piece.piece.column + thisCrystal.column
- Name
cellRow- Value
@self.piece.piece.row + thisCrystal.row
self.showsLanding == true- Variable
cellRow- Value
@self.piece.piece.landingRow + thisCrystal.row
- Action Name
thisCellMiddle- column
cellColumn- row
cellRow
- X
thisCellMiddle.x- Y
thisCellMiddle.y
- Frame
data('Piece Kinds', @self.piece.piece.kind - 1, 'frame')
cellRow < data('Well Layout', 0, 'visibleRows')- Visible
Yes
- Visible
No
self.showsLanding == false- Action Name
roomBelowDimmingPiece- piece
@self.piece- columnShift
0- rowShift
-1
roomBelowDimmingPiece.value == false- Value
self.transform.opacity- Target
@self.dimmedAlpha- Duration
@self.piece.piece.lockDelaySeconds
- Visible
No
- Visible
No
The game now has a beginning it can wait for. Give that wait its words.
9.5 READY, Then GO!
Now the wait has words that the player can watch above the empty glass well.
9.5.1 Show During Countdown
READY gives the changing number a place to belong. Their shared Logic keeps that little announcement together, until GO! takes its place. The number follows countdown through its text template; it needs no updating Event.
A text of the countdown (READY, the number): shown from the start of the game until play begins (playStarted).
Any Object- Visible
Yes
- Visible
No
Window / UITop CenterUIX 128, Y 48READYNunito51Bold#BFEAFF1.5CenterWrap to Width450Window / UICenterUIX 128, Y 48{$countdown}Nunito165Bold1.5CenterWrap to Width4509.5.2 Show Go
The last beep becomes a different chime. Show Go asks the familiar Fade Out Message to reveal GO!, then let it fade. Its short life belongs to that placement, leaving other announcements alone.
Shows "GO!" when play begins (Fade Out Message on the same text hides it again).
Any Object- Custom Event
messageShown
Window / UICenterUIX 128, Y 48GO!Nunito165Bold#FFF3B01.5CenterWrap to Width600Place Ready, Countdown and Go from the first group in Set up. Keep their anchors as well as their offsets. GO! stays for 0.7 seconds and fades over its final 0.4 seconds, a brief welcome to the falling piece.
Wait to test this beginning until Open Results is updated below. Play still has a competing activation. The clocks also start early. We’ll remove that competing activation and give the clocks the same invitation.
9.6 Time Belongs to Play
The countdown shouldn’t spend any of Ultra’s time.
9.6.1 Time The Game
At Scene Start the clock is held at zero. playStarted begins the first live stretch. Later, pausing stores that stretch in clockHeld and turns clockOn off. Resuming starts a new stretch and keeps the stored time, and the clock adds them together. Changing clockStart marks the new beginning; it leaves clockHeld alone.
The first pause needs care. You can pause before the count finishes, when no playing time exists yet. The empty Clock Not Running Modes protect that beginning. Make both responses for each pause Event before choosing them in On Play Started.
Keep Scoring State on Game Rules named scoring. This Logic still reads that same component; its ending calculation stays in place. Change the marked Scene Start Actions and add the new listeners from the card.
Times the game: the clock the stats panel shows ($clockStart, $clockOn, $clockHeld: the time played is ($playTime - $clockStart) x $clockOn + $clockHeld, standing still while the game is paused and after the end) and the time played kept for the results.
Any Objectself.scoring- Variable
$clockStart- Value
$playTime
- Variable
$clockOn- Value
0- Value
1
- Variable
$clockHeld- Value
0
- Action Name
playedAtTheEnd
- Component Value
self.scoring.playedSeconds- Value
playedAtTheEnd.value
data('Modes', global('mode') - 1, 'timeLimit') > 0 && self.scoring.playedSeconds > data('Modes', global('mode') - 1, 'timeLimit')- Component Value
self.scoring.playedSeconds- Value
data('Modes', global('mode') - 1, 'timeLimit')
- Variable
$clockHeld- Value
self.scoring.playedSeconds
- Variable
$clockOn- Value
0
- Variable
$clockStart- Value
$playTime
- Variable
$clockOn- Value
1
- Event
On Game Paused- Mode
Stop The Clock
- Event
On Game Resumed- Mode
Start The Clock Again
- Action Name
playedBeforeThePause
- Variable
$clockHeld- Value
playedBeforeThePause.value
- Variable
$clockOn- Value
0
- Variable
$clockStart- Value
$playTime
- Variable
$clockOn- Value
1
9.6.2 Finish The Mode
Ultra’s deadline needs the same beginning as its visible clock. Its Actions stay. Change the starting Event to playStarted, so the deadline begins with the first piece. Pause holds that timer too.
Finishes the mode at its goal lines or when its time limit is up (Modes): Game Over, Victory Jingle, Crystal Fountain and Sparkle Shower, modeFinished and gameOver.
Any ObjectGlass Welldata('Modes', global('mode') - 1, 'timeLimit') > 0- Timer Name
"timeUp"- Repeat Every (s)
data('Modes', global('mode') - 1, 'timeLimit')- Ring Once
Yes
data('Modes', global('mode') - 1, 'goalLines') > 0 && $lines >= data('Modes', global('mode') - 1, 'goalLines')- Custom Event
goalReached
- Custom Event
goalReached
- Applies to
@self.well- Custom Event
settleClear
- Game State
Game Over
- Sound
Victory Jingle
- Action Name
finishMiddle- column
(data('Well Layout', 0, 'columns') - 1) / 2- row
(data('Well Layout', 0, 'visibleRows') - 1) / 2
- Particles
Sparkle Shower- Position Relative To
World- X
finishMiddle.x- Y
finishMiddle.y- Count
@self.sparkleCount- Z Index Offset
7
- Action Name
finishFloor- column
(data('Well Layout', 0, 'columns') - 1) / 2- row
@self.fountainRow
- Particles
Crystal Fountain- Position Relative To
World- X
finishFloor.x- Y
finishFloor.y- Count
@self.fountainCount- Z Index Offset
7
- Custom Event
modeFinished
- Custom Event
gameOver
- Logic Component
Finish The Mode- State
Disable
The number on the panel and the deadline now count the same play. Neither spends the countdown.
9.7 A Panel Over the Well
The waiting piece remains where you left it, behind a panel with three ways onward.
9.7.1 Show While Paused
The veil leaves the well faintly visible behind glass. The title and buttons stay bright. Show While Paused gives them one shared opening and closing, with shownAlpha deciding how much each picture shows.
Declare shownAlpha as the Per Instance Variable on its card. It starts at 1. The veil’s placement changes only its own value, so the words keep their full brightness.
One part of the pause panel: hidden while the game is played, shown at shownAlpha while it is paused.
Any Object- Visible
No
- Alpha
self.shownAlpha
- Visible
Yes
- Visible
No
Window / UICenterUIX 128, Y 128160White Pixel#03213FX 1920, Y 1080Window / UICenterUIX 128, Y 128161Info Glass PanelX 690, Y 570Panel StateWindow / UITop CenterUIX 128, Y 48PAUSEDNunito78Bold1.5CenterWrap to Width600Give Pause Panel one plain Panel State component. Keep its component name as Panel State, whose expression name is panelState. Panel Choices goes second. Its existing choosing work will serve this new panel.
Place Pause Veil, Pause Panel and Pause Title from Set up. The veil’s Shown Alpha is 0.6, enough to leave the stopped well behind it. The pictures stay hidden for now.
9.7.2 Resume The Game
Resuming should return your keys to the well. This Function closes the menu’s input context and ends the engine’s pause. Myth then announces gameResumed to the waiting listeners.
Make the Function before building the responses that call it. Its Actions give both Escape and the RESUME button the same return.
Goes on from the pause: the menu controls go off and Set Game Paused ends the pause (the engine then sends gameResumed).
- Input Context
Menus- Active
false
- Paused (1 pause / 0 resume)
0
9.7.3 Pause The Game
Escape has two jobs now. During play it opens the panel; while paused it resumes. Separate input contexts keep those jobs apart, and Back’s Modes keep this Logic silent outside the pause.
Declare pausePanel as a Shared Variable: Type Object, Kind Constant. The card permits Objects with Panel State; choose the concrete Pause Panel as Object Kind here. That broader card wording describes which Objects qualify. Pause Panel is your editor choice; this Logic only sends it messages. Choose its value on Game Rules later.
Make both Back Modes before the Switch Mode Actions. While Playing starts empty. gamePaused chooses Resume and opens the panel, while gameResumed closes it and restores the empty response. The ending disables Pause.
Pauses the game with Set Game Paused when Pause is pressed (during the countdown or play, not after the end), with Pause Chime and the menu controls; Back resumes it.
Any ObjectObjects with Panel State- Input Context
Pause
- Sound
Pause Chime
- Input Context
Menus
- Event
When Back Is Pressed- Mode
Resume
- Applies to
@self.pausePanel- Custom Event
panelOpened
- Event
When Back Is Pressed- Mode
While Playing
- Applies to
@self.pausePanel- Custom Event
panelClosed
- Sound
Menu Select
- Input Context
Pause- Active
No
Attach Pause The Game after Count Down on Game Rules. Set pausePanel to Pause Panel in its Shared Variables. Keep its other references and components in place; the Changes card shows what joins them.
Scoring StateCount LevelCount Level DataGlass WellFalling PieceResults PanelPause Panel9.7.4 Open Results
Both panels use Back, but only one should answer it. Open Results now starts with an empty While The Results Are Closed Mode. The results-delay timer selects Back To The Menu only when those results open.
Make both Modes before changing the timer’s Switch Mode. Remove its old Scene Start activation of Play too. Count Down now owns that opening, so the results Logic must leave it waiting.
Opens the results panel resultsDelaySeconds after the game ends (resultsShown).
Any ObjectObjects with Panel State- Input Context
Play
- Input Context
Menus- Active
No
- Timer Name
"resultsDelay"- Repeat Every (s)
@self.resultsDelaySeconds- Ring Once
Yes
- Input Context
Play- Active
No
- Event
When Back Is Pressed- Mode
Back To The Menu
- Input Context
Menus
- Input Context
Play- Active
No
- Applies to
@self.resultsPanel- Custom Event
panelOpened
- Custom Event
resultsShown
- Sound
Menu Back
Escape can now open and close the pause. The panel still needs its choices.
9.8 Three Ways Onward
The first choice returns to the piece exactly where it waited.
9.8.1 Go On Playing
RESUME uses the same Function as Back. Panel Choice supplies choiceRun when the selected button is confirmed or clicked. Go On Playing gives that choice its meaning.
What the RESUME choice does: goes on from the pause (Resume The Game).
Any ObjectWindow / UICenterUIX 128, Y 128166Aero ButtonX 492, Y 86.4SensorX 468, Y 65.4Pause PanelWindow / UICenterUIX 128, Y 48RESUMENunito42Bold1.5CenterWrap to Width492Reuse the prepared Panel Choice declaration from earlier chapters. Point panel at Pause Panel, whose existing choosing Logic will keep these new buttons together. RESUME keeps choice at its starting value, while the later buttons choose their own numbers. Their Collider sensors hear the mouse beneath the labels.
9.8.2 Restart The Mode
The next countdown needs a running Scene. End the pause first. Then the new Scene can count before inviting its first piece. Your chosen mode stays the same.
What the RESTART choice does: starts the same mode again from the pause: ends the pause, then starts a new game (Start A New Game).
Any Object- Paused (1 pause / 0 resume)
0
Window / UICenterUIX 128, Y 128166Aero ButtonX 492, Y 86.4SensorX 468, Y 65.4Pause Panel1Window / UICenterUIX 128, Y 48RESTARTNunito42Bold1.5CenterWrap to Width4929.8.4 Keep Bests
Zen’s well never has to end. Its record therefore needs this deliberate departure. Move the Keep A Zen Best Mode from On Game Over to On Game Left, keeping its score comparison and persistent write together.
On Game Left starts in the empty Nothing To Keep Mode. Make that Mode too, then update When Created to select Keep A Zen Best for Zen. The other modes leave this Event silent. No new-best notice is needed on a panel you’re leaving.
Each mode's best: reads the four kept bests when a game begins (Read The Bests) and keeps a new best of the mode played: the highest score (Marathon and Ultra when the game ends, Zen when it is left) or the fastest finished time (Sprint 40).
Any Objectself.scoringdata('Modes', global('mode') - 1, 'bestKey') == "bestMarathon"- Event
On Game Over- Mode
Keep A Marathon Best
data('Modes', global('mode') - 1, 'bestKey') == "bestSprint"- Event
On Mode Finished- Mode
Keep A Sprint Best
data('Modes', global('mode') - 1, 'bestKey') == "bestUltra"- Event
On Game Over- Mode
Keep An Ultra Best
data('Modes', global('mode') - 1, 'bestKey') == "bestZen"- Event
On Game Left- Event
On Game Over- Mode
Keep A Zen Best
$score > $bestMarathonScore- Variable
$bestMarathonScore- Value
$score
- Action Name
bestMarathonWrite- Key
"bestMarathon"- Value
global('bestMarathonScore')
- Component Value
self.scoring.isNewBest- Value
true
$score > $bestUltraScore- Variable
$bestUltraScore- Value
$score
- Action Name
bestUltraWrite- Key
"bestUltra"- Value
global('bestUltraScore')
- Component Value
self.scoring.isNewBest- Value
true
$score > $bestZenScore- Variable
$bestZenScore- Value
$score
- Action Name
bestZenWrite- Key
"bestZen"- Value
global('bestZenScore')
- Component Value
self.scoring.isNewBest- Value
true
- Action Name
sprintTime
$bestSprintTime == 0 || sprintTime.value < $bestSprintTime- Variable
$bestSprintTime- Value
sprintTime.value
- Action Name
bestSprintWrite- Key
"bestSprint"- Value
global('bestSprintTime')
- Component Value
self.scoring.isNewBest- Value
true
$score > $bestZenScore- Variable
$bestZenScore- Value
$score
- Action Name
bestZenWrite- Key
"bestZen"- Value
global('bestZenScore')
Place each button and label from the setup list. The footer has familiar key pictures and words, with their own positions beside the screen edge. They share Show While Paused, but their Bottom Center anchors belong to the screen edge.
Window / UIBottom CenterUIX 128, Y 128165Key EnterX 77.52, Y 40.8Window / UIBottom CenterUIX 128, Y 48CONFIRMNunito24Bold1.5CenterWrap to Width144Window / UIBottom CenterUIX 128, Y 128165Key EscX 57.12, Y 40.8Window / UIBottom CenterUIX 128, Y 48RESUMENunito24Bold1.5CenterWrap to Width130.5The brighter button pictures reuse Show When Panel Choice. Set panel to Pause Panel on each brighter picture Object. Compare choice on each placement: it matches the button below, while the Sprite and depth stay the same.
Window / UICenterUIX 128, Y 128167Aero Button LitX 492, Y 86.4Pause PanelWindow / UICenterUIX 128, Y 128167Aero Button LitX 492, Y 86.4Pause PanelWindow / UICenterUIX 128, Y 128167Aero Button LitX 492, Y 86.4Pause PanelFinish the setup list with those bright pictures. Their placement choices select the glow, while each button’s Shared Variable selects its action. Keep both sets matched.
The panel has its ways onward. A held key needs one last kindness before returning to play.
9.9 Let the Keys Rest Too
A key may be released during the pause, when its ordinary listening context is asleep.
9.9.1 Read The Move Keys
An arrow held before pausing shouldn’t carry on moving after you return. gameResumed clears that memory. Your next press can make a fresh choice. Add On Game Resumed; leave the existing press and release Events in place.
Hears Move Left and Move Right: keeps the piece's moveDirection (the key pressed last wins) and asks for one move (moveOnce) at a press and again and again while the key is held (auto-repeat). It stays on between pieces, so a key let go then is heard too.
Any Objectself.pieceself.readTheMoveKeysData- Component Value
self.readTheMoveKeysData.isLeftHeld- Value
true
- Component Value
self.piece.moveDirection- Value
-1
- Custom Event
moveOnce
- Timer Name
"autoRepeat"- Repeat Every (s)
@self.autoRepeatSeconds- First Delay (s)
@self.autoRepeatDelaySeconds
- Component Value
self.readTheMoveKeysData.isRightHeld- Value
true
- Component Value
self.piece.moveDirection- Value
1
- Custom Event
moveOnce
- Timer Name
"autoRepeat"- Repeat Every (s)
@self.autoRepeatSeconds- First Delay (s)
@self.autoRepeatDelaySeconds
- Component Value
self.readTheMoveKeysData.isLeftHeld- Value
false
self.piece.moveDirection == (-1) && self.readTheMoveKeysData.isRightHeld == true- Component Value
self.piece.moveDirection- Value
1
- Timer Name
"autoRepeat"- Repeat Every (s)
@self.autoRepeatSeconds- First Delay (s)
@self.autoRepeatDelaySeconds
self.piece.moveDirection == (-1)- Component Value
self.piece.moveDirection- Value
0
- Timer Name
"autoRepeat"
- Component Value
self.readTheMoveKeysData.isRightHeld- Value
false
self.piece.moveDirection == 1 && self.readTheMoveKeysData.isLeftHeld == true- Component Value
self.piece.moveDirection- Value
-1
- Timer Name
"autoRepeat"- Repeat Every (s)
@self.autoRepeatSeconds- First Delay (s)
@self.autoRepeatDelaySeconds
self.piece.moveDirection == 1- Component Value
self.piece.moveDirection- Value
0
- Timer Name
"autoRepeat"
- Custom Event
moveOnce
- Component Value
self.readTheMoveKeysData.isLeftHeld- Value
false
- Component Value
self.readTheMoveKeysData.isRightHeld- Value
false
- Component Value
self.piece.moveDirection- Value
0
- Timer Name
"autoRepeat"
9.9.2 Soft Drop Piece
Down needs that kindness too, because it can be released while ordinary input is asleep. If soft drop was held, gameResumed asks for fallNormally. Gravity returns to its ordinary pace until you press Down again.
While Soft Drop is held, the falling piece falls speedUp times faster (at least one row every slowestSeconds); letting go returns it to its normal fall.
Any Objectself.pieceself.softDropPieceData- Component Value
self.softDropPieceData.isSoftDropping- Value
true
- Custom Event
fallFaster
- Custom Event
fallNormally
- Component Value
self.softDropPieceData.isSoftDropping- Value
false
- Timer Name
"gravity"- Repeat Every (s)
self.piece.fallSeconds
self.softDropPieceData.isSoftDropping == true- Custom Event
fallFaster
- Name
fasterSeconds- Value
0
- Variable
fasterSeconds- Value
self.piece.fallSeconds / @self.speedUp
fasterSeconds > @self.slowestSeconds- Variable
fasterSeconds- Value
@self.slowestSeconds
- Timer Name
"gravity"- Repeat Every (s)
fasterSeconds
self.softDropPieceData.isSoftDropping == true- Custom Event
softDropRow
self.softDropPieceData.isSoftDropping == true- Custom Event
fallNormally
Run your game again. The piece waits when you ask, and moves when you choose.
9.10 Play It!
- Enter Gameplay from the menu. Watch READY and the count, with no falling piece before GO!. The elapsed clock begins with play.
- Pause during the countdown, wait, then resume with Escape. The count continues.
- Hold an arrow, pause with P, release the arrow, then resume. It stays at that column. Repeat that hold, pause and release with Down, watching whether gravity returns at its ordinary pace.
- Pause during Ultra. Compare TIME LEFT before and after waiting; the pause spends none of its remaining time.
- Move through RESUME, RESTART and MAIN MENU with Up and Down. The glow wraps, Enter runs the choice, and reopening selects RESUME.
- Hover each pause button and click it. RESTART returns to READY in the same mode; MAIN MENU returns to the six choices.
- In Zen, earn a score above its saved best, pause, and choose MAIN MENU. Its PERSONAL BEST now shows that score. Start again and compare the saved best beside the well with the record you left on the menu.
- Top out in a score mode. The ending keeps Pause closed, even when Escape is pressed before its results arrive. Once results appear, Back returns to the Main Menu.
9.11 How It Works
The Scene arrives. The count finishes. One message starts the piece and the clocks together. A pause holds their work while its own controls keep listening.
Resuming keeps this attempt. Restarting begins again from the countdown, while leaving tells the record before changing Scenes. Those different intentions have different messages, even when the same panel offers them together.
9.12 If It Didn’t Work
The first piece arrives under READY? Check Deal Pieces for the removed nextPieceDue in When Created. Move the invitation to On Play Started, where the finished count can reach it. Let the count invite the piece.
The pause opens but its keys do nothing? Compare the Menus context’s Works While Paused switch with the new setting on the setup card. Pause The Game also activates that context when pausing. Restore both settings and resume.
The clock includes the countdown? Compare Scene Start with On Play Started in Time The Game. Their jobs differ. Restore those separate beginnings and watch another count.
Escape leaves the waiting piece behind? Check Open Results starts Back in While The Results Are Closed. Its timer makes the switch later. Restore the empty starting response, then pause during play and use Escape to resume that same piece.
The panel opens without a glow? Compare panel on the buttons and bright pictures with Pause Panel. Keep the existing prepared declarations. Then check the placement’s choice against its button and reopen the panel.
Zen’s best disappears after leaving? Look in Keep Bests, at When Created and its Zen Switch Mode. It chooses On Game Left’s saving Mode. Leave For The Menu must send gameLeft before changing Scenes. Restore those connections, earn a higher score, and return through MAIN MENU again.
Still stuck? Search the manual, or ask in the Myth Engine Discord (opens a new tab).
9.13 Challenge
What would your well offer while it waits? Try your own countdown words, a different pause layout, or another choice you’d like to build. Keep a working copy beside the experiment. The next game can begin with your idea.
In the first chapter, the well was an empty glass box. Now it catches crystals, shatters lines, keeps your records and waits for your return. Play it from your Title screen. This is the game you built.
Free demo
Free
- No time limit
- Build, save and playtest your games
- Follow every game guide and build its game
Publishing needs the full version.
Try the free demoFull version
$84.99 USD, once
No subscription, no paid upgrades, every update included.
Everything in the free demo, plus:
- Publish your game as one HTML file, a web folder, or desktop and mobile projects you build and sign
- Share it or sell it, with no royalties, however much it earns
- Let players build their own version of your game, within the parts you allow (Builder Mode)
Windows 10/11, 64-bit · One person, on computers you own or control · Checkout and downloads through itch.io · Made by 3D Mage
License agreementMac, refunds and other questionsWhy pay for Myth Engine when free engines exist?
