- Learn
- Build a Game
- Pacific Wings
- 12 Rounds and Mission Complete
12 Rounds and Mission Complete
The mission becomes three rounds, each under its own sky: a clear day, then dusk orange, then night blue. After each Command Bomber the screen fades, and the route begins again, harder. Shoot down the third, and the screen says MISSION COMPLETE. Pacific Wings is complete.
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. It’s the whole game, finished.
To open it, start Myth Engine, choose File › Open Project... and pick the downloaded file.
12.1 The Idea
The Command Bomber goes up in the biggest explosion in the game. The red bar is gone. The sky is quiet, and your Fighter flies on alone, over a sea with nothing left to fight.
Right now, that’s where Pacific Wings stops.
After this chapter, the quiet lasts a few seconds. The screen fades out and back in, and the carrier is below you again, at the very start of the route. But the light has changed. The whole sea wears a warm orange tint, as if the day were ending. The enemies come faster. They fire sooner. At the end, another Command Bomber waits, and it takes more hits.
Bring that one down, and the route begins a third time, under a night blue sky. Bring the third down, and the screen says MISSION COMPLETE, with your final score.
Each flight of the route is a round. Pacific Wings has three.
Here’s the hard idea. A new round is the route’s Scene, started again from the beginning. Think of a play performed a second time on the same stage. The set goes back to how it was. Every actor returns to their mark. Only what you carry in your pockets comes with you.
In Myth, your pockets are the Globals. Your score is one, and so are your reserve planes and your weapon level. They ride across into the next round untouched. Everything placed in the Scene comes back new: the Fighter, the enemies, the scenery, even Game Rules.
PLAY AGAIN is another matter. Since Chapter 5, it has used Restart Game, and Restart Game empties the pockets too. Every Global goes back to where it started. So a new mission always begins at round 1, with a score of 0.
So most of this chapter is about two questions. What should carry over from round to round? And what should start again? The answers fit in one new Global, one small table and a few resets.
12.2 The Plan
Here’s how the pieces work together.
- The Command Bomber is shot down -> Score adds 2000, then sends commandBomberScored.
- Rounds hears it -> with rounds left, its roundBreather timer waits 3.5 seconds; after the last round, the Game State becomes Mission Complete.
- The breather ends -> $roundRow goes up by one, Rounds sends roundOver, and Go to Scene starts the route again with a fade.
- On roundOver -> Lost on Hit and Pause turn themselves off for the fade.
- The route begins -> Rounds starts the kill chain and the scenery afresh, and from round 2 shows the flight HUD and the Round Sky. Round Sky Color tints the sky for this round.
- The Game State becomes Mission Complete -> a second later, MISSION COMPLETE shows, and Best Score keeps your score.
12.3 Set Up
One picture from the Starter Kit joins the game, the Round Sky. It’s in your project already.
Title, Playing, Mission Failed, Mission CompleteThe new Global, $roundRow, says which round this is. Like a table’s rows, it counts from 0. So round 1 is row 0. Make it from a Globals card, as you made $score.
Add Mission Complete to the Game States, as you added Mission Failed in Chapter 4. Your Logic reads it as "mission-complete", in lower case with a hyphen. Leave REMOVED and PLACE THESE for now. REMOVED waits until Mission Failed Screen’s job has moved, and PLACE THESE until its pieces exist.
12.4 A Table for Three Rounds
First, the numbers that make a round harder, all of them in one table.
12.4.1 Round Settings
One row of the "Round Settings" Data Table.
11#07123d00.851.1#ff7a360.180.71.2#07123d0.42Each row is a round. Read across a row, and you can see how hard it is. Every number in the first three columns scales something the game already has. Above 1, the bomber’s health and the enemies’ speed grow. Below 1, a wait shrinks. So the enemies fire sooner. Round 1 is all 1s: the game you’ve been playing, with nothing scaled at all.
The last two columns are the sky. Its skyTint is the color, and skyAlpha is how strongly it shows. A clear day is 0, no tint at all. Dusk is a light orange at 0.18, and night is the deep blue at 0.42.
Make it as you made Command Bomber Phases. The table makes Round Settings Entry, and its fields are the columns. Set the defaults first, and Round 1 needs nothing of its own. Like damageTint, skyTint is a Color.
Every harder thing in the game reads this table. It always reads row $roundRow. So when $roundRow goes up by one, the whole game moves down a row with it, from the enemies’ guns to the color of the sky.
12.5 The Round Is Over
Now the rounds themselves. A new Logic Component keeps them, and three that you built before learn to listen to it.
12.5.1 Score
Adds the points of every enemy shot down (times the kill-chain multiplier), of every pickup collected, and of every hit on and the shoot-down of the Command Bomber, to $score, until the mission ends.
Any Object- Name
multiplier- Value
1
- Variable
multiplier- Value
data('Kill Chain Multipliers', $chainRow, 'multiplier')
- Variable
$score- Operator
+=- Value
other.enemyStats.points * multiplier
- Custom Event
shotDownScored
event.current == "mission-failed"event.current == "mission-failed" || event.current == "mission-complete"- Logic Component
Score- State
Disable
- Variable
$score- Operator
+=- Value
@self.wingCannonsPoints
- Variable
$score- Operator
+=- Value
@self.repairCratePoints
- Variable
$score- Operator
+=- Value
@self.commandBomberHitPoints
- Variable
$score- Operator
+=- Value
@self.commandBomberPoints
- Custom Event
commandBomberScored
The bonus comes first. When the Command Bomber goes down, Score adds its 2000 and then tells Game Rules, with commandBomberScored. Trigger Custom Event on Object starts on Self, as in Chapter 9, and Rounds will listen there. Add that step at the end of On Command Bomber Shot Down.
Why not let the rounds listen for the shoot-down itself? Think about the last round. The mission ends there, and Best Score keeps whatever the score is at that moment. If the mission could end before Score counted the bonus, your best score would be 2000 short. Listening to Score makes the order sure.
The other change is for that ending too. Since Chapter 4, Score has stopped counting the moment a mission fails, and it should stop when a mission is complete as well. Click the condition of the If in On Game State Changed, and type the rest of the card’s line after it. || means or: either state stops the count.
12.5.2 Rounds
When the Command Bomber is shot down: if rounds are left, waits breatherSeconds and flies the route again in the next round; after the last, the mission is complete. When a round is over it sends roundOver. Each round starts with no scenery moved ahead and the kill chain at x1.
Any Object- Action Name
stillPlaying- Game State
Playing
stillPlaying.value == true$roundRow < (dataCount('Round Settings') - 1)- Timer Name
"roundBreather"- Repeat Every (s)
@self.breatherSeconds- Ring Once
Yes
- Game State
Mission Complete
- Custom Event
roundOver
- Action Name
playingAfterBreather- Game State
Playing
playingAfterBreather.value == true- Variable
$roundRow- Operator
+=- Value
1
- Custom Event
roundOver
- Scene
Route- Transition
Fade- Transition Seconds
@self.fadeSeconds
- Variable
$furthestSceneryY- Value
0
- Variable
$chainRow- Value
0
- Action Name
isPlaying- Game State
Playing
isPlaying.value == true- UI Group
"flight"
- UI Group
"sky"
Rounds sits on Game Rules and keeps $roundRow. It has three Events.
When commandBomberScored arrives, Rounds first asks whether the mission is still being played. Tracers already in the air can finish the bomber after your last plane is lost, and a failed mission shouldn’t win too. Next it looks at the table. Is this the last row? If not, it starts a timer, roundBreather, to ring once after 3.5 seconds. That’s the breather. It’s a few seconds of quiet sky, with nothing left to shoot, before the screen fades.
On the last row, the mission is complete instead. Rounds sets the Game State to Mission Complete, and sends roundOver.
When the breather ends, Rounds asks again. It looks like asking twice. But a tracer can still reach your last plane during the breather, and then the mission has failed for good. If the mission is still being played, $roundRow goes up by one, and roundOver goes out. Last, Go to Scene starts the Route again. Its Transition is Fade, and the fade takes fadeSeconds, 0.8 of a second. The screen comes back on a new round.
The third Event is Scene Start, which you met in Chapter 7, and it runs each time the route begins. Here it puts two Globals back to 0. $furthestSceneryY goes back, so the scenery starts again from the carrier. $chainRow goes back, so the kill chain starts at x1.
The other Globals look after themselves. Since Chapter 7, Stages has set $stage to 1 each time the route begins. And $bomberLaneMeters went back to 0 when the bomber fell.
Why not reset them before the fade? Because the old round goes on while the screen fades, and a shoot-down in that moment would set $chainRow again. So they’re reset as the new route begins, when the old one is truly over.
Last, it shows two UI Groups. Remember that everything placed comes back as it was placed. The first group, flight, is your HUD, the score and the reserve planes at the top of the screen. Both were placed hidden. So in round 2 they’d start hidden. Show the Flight HUD can’t help, because the Game State never changes between rounds. So Rounds shows them again.
The second group, sky, holds one Object you’ll make later in this chapter, the Round Sky. It’s a tinted pane laid over the whole sea, and it’s placed hidden too. Round 1 has a clear sky and needs no pane. From round 2, Rounds shows it.
Rounds shows both only while a mission is being played. Round 1 starts from the title, where they stay out of sight.
Make it as an Empty Logic Component. It has two Shared Variables. The first Event’s If holds a second If inside it, and that one has an Else of its own, for the last round. Add Inside Then on the first If adds the inner If, and the inner If’s own menu fills its True and False lines.
The message roundOver is new. Trigger Custom Event sends it to every Object, and once Rounds sends it, it’s in the Add Event list. Go to Scene’s Scene and Transition are lists on the block: pick Route and Fade. The two Set UI Group Visibility steps take "flight" and "sky", with their quote marks, as in Show the Flight HUD. Attach it to Game Rules. It joins the bottom of Attached Logic.
12.5.3 Lost on Hit
When a Fighter Hazard touches the Fighter, the Fighter is lost: it explodes and reports fighterLost (before the Command Bomber's stage the screen also flashes). When its round is over (roundOver, from Rounds), it turns itself off, so nothing can lose the Fighter after the win or while the screen fades to the next round.
Any Object- Custom Event
fighterLost
- Sound
Fighter Lost
- Intensity
@self.shakeIntensity- Seconds
@self.shakeSeconds
$stage < @self.flashBeforeStage- Color
@self.flashColor- Seconds
@self.flashSeconds
- Particles
Plane Explosion- Count
@self.explosionParticles- Z Index Offset
2
- Logic Component
Lost on Hit- State
Disable
The round is over, but the sky isn’t empty. A tracer the bomber fired before it fell can still reach the Fighter. During the breather, the round is still being flown, and a hit costs a plane as always. Once roundOver goes out and the screen fades, it shouldn’t.
So when roundOver arrives, Lost on Hit turns itself off, the way Set Logic State turned off Score in Chapter 4. Pick Lost on Hit in its Logic Component slot, and pick Disable.
Turning it off for good might sound risky. It isn’t. The next round’s Fighter is a new one, placed fresh, with its Lost on Hit on.
12.5.4 Pause
Esc pauses the world while a mission is being played; RESUME (or Esc, or Enter) carries on. When a round is over (roundOver, from Rounds), it turns itself off: the fade to the next round cannot be paused.
Any Object- Action Name
isPlaying- Game State
Playing
isPlaying.value == true- Menu Element
Pause Menu
- Menu Element
Pause Menu
- Menu Element
Pause Menu- Pause the World
No
- Operation
Hide- Menu Element
Pause Menu
- Custom Event
resumeMission
- Logic Component
Pause- State
Disable
Pause does the same, so nobody can pause the fade. But first it carries on, in case the world is paused right then. It sends resumeMission to itself, the message RESUME sends. Its own On Resume Mission hides PAUSED and lets the world run. After that, it turns itself off. Its Set Logic State picks Pause in the Logic Component slot. Every box takes what its card shows.
Both of these listen for roundOver. Add it from the Add Event list, where it waits now.
Save, and run the game. Fly the whole route and bring down the bomber. A few seconds of quiet sky, a fade, and the carrier is below you again, with your score still there. The sky looks the same, and the enemies feel the same. The next parts change that.
Bringing the bomber down takes a while. To see a round end sooner, open the Command Bomber, and under Variables give Command Bomber Health’s startingHealth a small Value, about a tenth of its 240. The bomber still fights its three phases, each a few hits long. Keep it while you test the skies, and put 240 back before the last run of the chapter.
12.6 Harder Each Round
Three pieces read the table now: the bomber, the enemies and the reinforcements. Each takes the number it had, and scales it.
12.6.1 Command Bomber Health
Starts the Command Bomber at startingHealth; each time a phase's share of the health is used up (Meter Threshold Reached) it moves to the next row of Command Bomber Phases, and after the last it is shot down.
Any Objectself.commandBomberState- Component Value
self.commandBomberState.maxHealth- Value
@self.startingHealth
- Component Value
self.commandBomberState.maxHealth- Operator
*=- Value
data('Round Settings', $roundRow, 'commandBomberHealthScale')
- Component Value
self.commandBomberState.maxHealth- Value
round(self.commandBomberState.maxHealth)
- Component Value
self.commandBomberState.phaseRow- Value
0
- Name
newPhaseRow- Value
0
- Component Value
self.commandBomberState.phaseRow- Operator
+=- Value
1
- Variable
newPhaseRow- Value
self.commandBomberState.phaseRow
- Custom Event
phaseStarted
- Intensity
data('Command Bomber Phases', newPhaseRow, 'startShake')- Seconds
data('Command Bomber Phases', newPhaseRow, 'startShakeSeconds')
- Particles
Flak Burst- Count
data('Command Bomber Phases', newPhaseRow, 'startFlakParticles')- Z Index Offset
2
data('Command Bomber Phases', newPhaseRow, 'dropsWingCannons') == true- Object to Create
@self.wingCannons- Position Relative To
Self
newPhaseRow == (dataCount('Command Bomber Phases') - 1)- Event
On Meter Threshold Reached · Meter With Thresholds Data.meter- Mode
Shot Down
- Custom Event
commandBomberShotDown
- Sound
Plane Break
- Intensity
@self.shotDownShake- Seconds
@self.shotDownShakeSeconds
- Particles
Plane Explosion- Count
@self.shotDownParticles- Z Index Offset
2
- UI Group
"commandBomber"- Visible
No
- Variable
$bomberLaneMeters- Value
0
When the bomber is made, its health is startingHealth, as before, multiplied now by this round’s commandBomberHealthScale. Then the round() in the third step rounds it off. So the bomber’s health stays a whole number of hits, whatever scale a row gives.
Remember the chalk line from Chapter 11? It’s the meter’s threshold, always one step ahead of the tally. It reads maxHealth, so the phases stretch with it. Round 2’s bomber still fights in thirds. Each third is longer.
Both new steps go between the first and the one that sets phaseRow. Right-click the phaseRow step, and choose Disconnect from Flow. Add the two Change Component Values, join them, and join the step back with Connect to Sequence. The first takes *= in its Operator.
12.6.2 The Three Enemies
X 2.48, Y 2.4830Enemy Fighter ArtX 2.48, Y 2.48Z -180EllipseX 1.453, Y 1.046Never Collide WithTagged Enemy AircraftEnemy StatsData TableEnemy TypesEnemy FighterGun MuzzleX 0, Y -0.94Enemy Aircraft, Fighter HazardEnemy TracerExpressionobjectComponentProperty("self","enemyStats","tracerSpeed")ExpressionobjectComponentProperty("self","enemyStats","firstShotSeconds") * data('Round Settings', $roundRow, 'enemyPace')ExpressionobjectComponentProperty("self","enemyStats","shotSecondsMin") * data('Round Settings', $roundRow, 'enemyPace')ExpressionobjectComponentProperty("self","enemyStats","shotSecondsMax") * data('Round Settings', $roundRow, 'enemyPace')FighterExpressionobjectComponentProperty("self","enemyStats","aimConeDegrees")Wing CannonsRepair CrateExpressionobjectComponentProperty("self","enemyStats","wingCannonsDropChance")ExpressionobjectComponentProperty("self","enemyStats","repairCrateDropChance")ExpressionobjectComponentProperty("self","enemyStats","speed") * data('Round Settings', $roundRow, 'enemySpeed')X 2.56, Y 2.5630Enemy Ace ArtX 2.56, Y 2.56Z -180EllipseX 1.6, Y 1.04Never Collide WithTagged Enemy AircraftGun MuzzleX 0, Y -0.94Enemy StatsData TableEnemy TypesEnemy AceWeaveWeave DataEnemy Aircraft, Fighter HazardEnemy TracerExpressionobjectComponentProperty("self","enemyStats","tracerSpeed")ExpressionobjectComponentProperty("self","enemyStats","firstShotSeconds") * data('Round Settings', $roundRow, 'enemyPace')ExpressionobjectComponentProperty("self","enemyStats","shotSecondsMin") * data('Round Settings', $roundRow, 'enemyPace')ExpressionobjectComponentProperty("self","enemyStats","shotSecondsMax") * data('Round Settings', $roundRow, 'enemyPace')FighterExpressionobjectComponentProperty("self","enemyStats","aimConeDegrees")ExpressionobjectComponentProperty("self","enemyStats","weaveSpeed")ExpressionobjectComponentProperty("self","enemyStats","weaveSeconds")ExpressionobjectComponentProperty("self","enemyStats","weaveAngle")Wing CannonsRepair CrateExpressionobjectComponentProperty("self","enemyStats","wingCannonsDropChance")ExpressionobjectComponentProperty("self","enemyStats","repairCrateDropChance")ExpressionobjectComponentProperty("self","enemyStats","speed") * data('Round Settings', $roundRow, 'enemySpeed')X 3.36, Y 3.3630Heavy Bomber ArtX 3.36, Y 3.36Z -180EllipseX 2.468, Y 1.733Never Collide WithTagged Enemy AircraftGun MuzzleX 0, Y -0.932Enemy StatsData TableEnemy TypesHeavy BomberWeaveWeave DataEnemy Aircraft, Fighter HazardEnemy TracerExpressionobjectComponentProperty("self","enemyStats","tracerSpeed")ExpressionobjectComponentProperty("self","enemyStats","firstShotSeconds") * data('Round Settings', $roundRow, 'enemyPace')ExpressionobjectComponentProperty("self","enemyStats","shotSecondsMin") * data('Round Settings', $roundRow, 'enemyPace')ExpressionobjectComponentProperty("self","enemyStats","shotSecondsMax") * data('Round Settings', $roundRow, 'enemyPace')FighterExpressionobjectComponentProperty("self","enemyStats","aimConeDegrees")ExpressionobjectComponentProperty("self","enemyStats","weaveSpeed")ExpressionobjectComponentProperty("self","enemyStats","weaveSeconds")ExpressionobjectComponentProperty("self","enemyStats","weaveAngle")Wing CannonsRepair CrateExpressionobjectComponentProperty("self","enemyStats","wingCannonsDropChance")ExpressionobjectComponentProperty("self","enemyStats","repairCrateDropChance")ExpressionobjectComponentProperty("self","enemyStats","speed") * data('Round Settings', $roundRow, 'enemySpeed')Each enemy has read its own row through Expressions since Chapter 3. Now four of those Expressions also read the round’s number. Look at the speed line, and the three shot timings, near the end of each card.
Open the Enemy Fighter, and look under Variables. Its speed Expression ends where the plane’s speed is read from Enemy Stats. Add the round’s part to its end, as the card shows: * data('Round Settings', $roundRow, 'enemySpeed'). Do the same for the three shot timings, with enemyPace. Then give the Enemy Ace and the Heavy Bomber the same four endings.
A wait multiplied by 0.85 is shorter. So in round 2 the enemies fire sooner, and in round 3 sooner still.
12.6.3 Reinforcements
Sends one enemy kind in from above the view on the reinforcements timer, from the stage in its Reinforcement Orders row until the Command Bomber approaches; each one only while fewer than cap of that kind are alive.
Any Objectself.reinforcementsData$stage == data('Reinforcement Orders', self.kind, 'fromStage')- Timer Name
"reinforcements"- Repeat Every (s)
data('Reinforcement Orders', self.kind, 'firstSeconds')- Ring Once
Yes
- Name
waitSeconds- Value
0
data('Reinforcement Orders', self.kind, 'perWave')times- Action Name
roomForMore- Object
self.kind- Operator
<- Value
data('Reinforcement Orders', self.kind, 'cap')
roomForMore.value == true- Action Name
laneRoll- Minimum
data('Reinforcement Orders', self.kind, 'xMin')- Maximum
data('Reinforcement Orders', self.kind, 'xMax')
- Component Value
self.reinforcementsData.laneX- Value
laneRoll.value
- Component Value
self.reinforcementsData.laneX- Operator
+=- Value
local.index * data('Reinforcement Orders', self.kind, 'laneStepMeters')
- Component Value
self.reinforcementsData.launchSpeed- Value
data('Enemy Types', self.kind, 'speed')
- Component Value
self.reinforcementsData.launchSpeed- Operator
*=- Value
data('Round Settings', $roundRow, 'enemySpeed')
- Object to Create
self.kind- X
self.reinforcementsData.laneX- Y
$viewMiddleY + @self.aboveCameraMeters- Launch Speed
self.reinforcementsData.launchSpeed- Launch Angle
-90
- Action Name
waitRoll- Minimum
data('Reinforcement Orders', self.kind, 'secondsMin')- Maximum
data('Reinforcement Orders', self.kind, 'secondsMax')
- Variable
waitSeconds- Value
waitRoll.value
- Variable
waitSeconds- Operator
*=- Value
data('Round Settings', $roundRow, 'enemyPace')
- Timer Name
"reinforcements"- Repeat Every (s)
waitSeconds- Ring Once
Yes
- Timer Name
"reinforcements"
The reinforcements arrive from above the view, launched south at their kind’s speed. That launch speed is scaled the same way, and so is the wait before the next group.
The first new step goes inside the If, right before Create Instance. Right-click Create Instance, and choose Disconnect from Flow. Next, right-click the If and choose Add Inside Then, then pick Change Component Value and join it. Join Create Instance back after it with Connect to Sequence.
The second goes on the main line, before the last step. Take Start Recurring Timer off the line the same way, add the Change Variable from the Action List, join it, and join the timer back.
12.7 Three Skies
Now the round can be seen as well as felt.
12.7.1 Round Sky
Window / UICenterUIX 32, Y 32Round SkyX 1400, Y 1000TextskymenuChoiceRound Sky is a picture as big as the whole screen, and bigger: 1400 by 1000 pixels, so no edge ever shows. It sits over the sea and everything flying above it, and under the score. That’s its Z-Index, 10000, two under the HUD’s.
It’s a Screen UI Object with a Sprite, made the way you made the Pause Dimmer in Chapter 5. Its UI Interaction is a Text element in the Group sky, the group Rounds shows from round 2. Its Event, menuChoice, never goes anywhere, as on Score Text. Its Logic, Round Sky Color, is the next card, so leave Logic empty for now.
12.7.2 Round Sky Color
Tints the sky for the current round, from the Round Settings table.
Any Object- Value
data('Round Settings', $roundRow, 'skyTint')
- Property
Mode- Value
"multiply"
- Property
Enabled- Value
true
- Alpha
data('Round Settings', $roundRow, 'skyAlpha')
Round Sky Color runs once, when the sky is made. The sky is placed in the Route, so that’s at the start of every round. The picture takes on the round’s color. Then its last step, Set Alpha, says how strongly the picture shows, from the row’s skyAlpha. At 0 it doesn’t show at all. At 0.42 it’s faint, and the sea shows through, as if through colored glass.
Its three Change Sprite Tint Property steps work as they did for Tint Sprite in Chapter 3. The first keeps Color in its Property list. Make it as an Empty Logic Component, and attach it to Round Sky.
Now place Round Sky from PLACE THESE, hidden, with its Z-Index. Round 1’s clear sky never needs it. From round 2, Rounds shows it, with its color already in place.
Save, and run the game. Round 1 looks as it always has. Bring down the bomber, and after the fade, the sea is warmer, its light low and orange. Round 3 is night.
12.8 Mission Complete
Last comes the end of the mission, and a screen that says so.
12.8.1 Show at Game State
When the Game State becomes gameState, waits delaySeconds, then shows menu and pauses the world behind it.
Any Objectevent.current == @self.gameState- Timer Name
"showScreen"- Repeat Every (s)
@self.delaySeconds- Ring Once
Yes
- Menu Element
@self.menu
- Menu Element
@self.menu
Since Chapter 4, Mission Failed Screen has waited for the mission to fail, then shown its menu. MISSION COMPLETE needs the same thing, with another state and another menu.
You could copy it, and change two names. But then there would be two Logic Components doing one job. So it becomes one Logic with three Shared Variables, and each screen says which state it waits for. Each screen’s menu carries it.
Make it as an Empty Logic Component, with its three Shared Variables. Its gameState is a Text, starting at mission-failed. Its menu is an Object, starting at None, because each screen picks its own. Its Control Menu and Set Menu Pause State take @self.menu. The rest is Mission Failed Screen’s, as you built it in Chapter 4, with the Shared Variables in place of the names. The If asks event.current == @self.gameState, and the timer waits @self.delaySeconds.
12.8.3 Game Rules
FighterMilestoneWing CannonsRepair CrateMission Failed Screen’s job has moved, so it goes, as the Set up card’s REMOVED asks. Right-click it in the Resources, and choose Delete. The window names Game Rules, which carries it, and says it comes off there too. Press Delete. The struck row on Game Rules’ card is that same Logic, and the delete has taken it off already.
Rounds is marked as added on this card too. The card compares Game Rules with Chapter 11, and Rounds is new since then. You attached it already, when you made Rounds, so there’s nothing more to do for it here.
12.8.4 MISSION COMPLETE
Window / UICenterUIX 32, Y 32MISSION COMPLETE38Bold#FFF1A8CenterWrap to Width560TextmissionCompletemenuChoiceWindow / UICenterUIX 32, Y 32FINAL SCORE {$score}22Bold#FFCA75CenterTextmissionCompletemenuChoiceWindow / UICenterUIX 268, Y 60-1Menu Button PanelX 268, Y 60PLAY AGAIN20Bold#8EEFFFCentermissionCompleteplayAgainMoveStart Missionmission-completeMission Complete MenuMISSION COMPLETE in pale gold, an amber FINAL SCORE under it, and PLAY AGAIN in pale blue on its panel. These three are the MISSION FAILED screen in new colors. Make them the way you made those in Chapter 4. You’ve built this screen once already. Their Group is missionComplete, and the panel is the Menu Button Panel, the one behind START MISSION. FINAL SCORE has two spaces before {$score}, as in Chapter 4.
The menu carries Show at Game State too, with its gameState typed as mission-complete, its menu picked as Mission Complete Menu, and the Logic’s delay of 1. That second lets the bomber’s explosion play out.
Place the three from PLACE THESE, hidden, each with its Z-Index.
12.8.5 Best Score
Keeps the best score on this device: shows it on the title screen and raises it when a mission ends.
Any Object- Action Name
savedBest- Key
"bestScore"- Default
0
- Variable
$bestScore- Value
savedBest.value
$bestScore > 0- UI Group
"best"
- UI Group
"best"- Visible
No
event.current == "mission-failed"event.current == "mission-failed" || event.current == "mission-complete"$score > $bestScore- Variable
$bestScore- Value
$score
- Action Name
bestSaved- Key
"bestScore"- Value
$bestScore
Best Score raises the best score when a mission fails. A complete mission counts too. Give its If the same || ending as Score’s.
Its two Set UI Group Visibility steps take "best", as Rounds’ take "flight" and "sky".
If you gave the bomber a small startingHealth, put 240 back now. Then save, and run the game.
This is the whole of Pacific Wings. Press Enter on your own title screen, the one you made in Chapter 5. Fly the route under a clear sky, and bring down the Command Bomber. The screen fades. Fly it again under dusk, and again under night, each time a little faster and a little fiercer. When the third bomber falls, the sky goes still. A second later comes MISSION COMPLETE, with your final score under it, and PLAY AGAIN.
Watch for each of these, one at a time.
- Round 1 looks as it always has: a clear sky, the same enemies, the same bomber.
- Bring down the bomber. The score jumps by 2000, the sky stays quiet for 3.5 seconds, and the screen fades.
- Round 2 begins at the carrier, under an orange dusk. Your score, your reserve planes and your weapon level are all still there.
- The kill chain starts round 2 at x1, and SCORE is cream again.
- The enemies come a little faster, and fire sooner. The bomber’s red bar takes longer to empty.
- Press Esc during the fade. Nothing pauses. Press it once round 2 has begun, and PAUSED shows as before.
- Round 3 is night blue.
- Bring down the third bomber. A second later, MISSION COMPLETE, with FINAL SCORE and PLAY AGAIN.
- Lose your last plane in any round, and MISSION FAILED shows, as it always has.
- Choose PLAY AGAIN. The title comes back, and the next mission starts at round 1, under a clear sky.
A table holds three rounds, and each row makes the game a little harder. One Global says which row is now. Every harder thing reads that row. When a round ends, the Global moves down a row, and the route starts again.
Go to Scene builds the Scene again from the beginning, and the Globals cross over untouched. So a round is a choice about what to keep. Keep it in a Global, and it carries over. Place it in the Scene, and every round it starts new, as it was placed.
Restart Game goes one step further. It starts everything again, Globals and all: your score goes back to 0, and so does $roundRow. That’s why PLAY AGAIN always begins at round 1.
12.9 If It Didn’t Work
The changes here are small, and spread across the whole game. Start with what you can see.
The bomber goes down, and nothing more happens? Look at Score first. Its last Event should end with Trigger Custom Event on Object, commandBomberScored. And is Rounds on Game Rules?
The fade comes, but the route starts as round 1 again? Perhaps $roundRow never moves. Look at the Change Variable in On the Round Breather Timer, whose Operator should be +=.
Round 2 has no score and no reserve planes at the top? Look at Rounds’ Scene Start. Its two Set UI Group Visibility steps need flight and sky, spelled as the Groups are.
The sky never changes? Look for Round Sky in Route’s Scene Explorer, the list on the right, with its Z-Index of 10000, and at its Group, which should be sky, the name Rounds shows. Then look at Round Sky Color’s second step, whose Property should be Mode.
The last bomber falls, and nothing shows? Look at Game Settings, where Mission Complete should be one of the Game States. And on Mission Complete Menu, gameState should read mission-complete, with menu picked as Mission Complete Menu itself.
PLAY AGAIN after MISSION COMPLETE does nothing? Look at Mission Complete Menu’s Event, under UI Interaction. It should be playAgain, the message Play Again has listened for since Chapter 5.
Each of these is one fix. Make it, run the game again, and you’re back with the chapter. The catch-up download in the Goal is the finished game, if you’d like to compare.
Open Round Settings, and add a fourth row. Give it a sky of your own, a deep red, or a green no sea has ever been. Make the bomber tougher still, and the enemies quicker. Rounds counts the rows, so a fourth round works with no change to the Logic.
And then, make something of your own. Every piece of Pacific Wings is one you know now: an Object, a Logic Component, a table, a message, a Scene that starts again. What would you build with them? A different sky, a different enemy, a different game. Nobody has made it yet.
Still stuck? Search the manual, or ask in the Myth Engine Discord (opens a new tab).
In Chapter 1, one navy-blue Fighter flew alone over an empty sea. Now the carrier, the islands and three Command Bombers are waiting for it, and every one of them is yours.
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?
