- Learn
- Build a Game
- Sky Ace
- 4 Mission Failed
4 Mission Failed
The Zero Fighters shoot back. A round that gets through costs one of your three medkits, with a red flash and a shake. After it, the Fighter blinks, safe for a moment. Lose the last medkit, and the mission ends in GAME OVER. Press Enter, and you fly again. By the end of this chapter, a mission can be lost.
The game as it is at the end of this chapter. Click the game to play.
If the game shows Tap to play, it waits for you. Click it, and the mission starts. Its one V comes three seconds later.
Some browsers play the sound at once and show no Tap to play. There the game doesn’t wait for your click. Its mission starts as soon as the Myth Engine logo fades, and its one V comes three seconds after that. Missed it? Reload the page, and the V comes again.
This chapter builds on Chapter 3’s game. Starting here? The catch-up download in Chapter 3’s Goal is that game, finished, ready to start from.
If your game and this chapter part ways, here is the chapter’s finished project. Open it and compare, or start Chapter 5 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, Bebas Neue.
4.1 The Idea
The mission starts with music now. The Battle Theme plays, with the low drone of an engine under it. The Fighter blinks for a moment, dim and bright, then holds steady.
Three seconds in, the V comes down. But this time a spark winks at one plane’s nose, then at another’s, and small orange rounds come down the window. Some fall straight, and others lean toward wherever you are.
One gets through. The window flashes red, the picture shakes, fire bursts on the Fighter with a bang, and one of three white cases at the bottom left goes out. That case was a medkit. You start each mission with three.
For the next 2.4 seconds the Fighter blinks, and nothing can hurt it. Rounds break on it and do no harm. That’s its protection. It works like the fireRate cooldown of Chapter 2, a stopwatch that has to run down before the Fighter can be hurt again.
Lose the last medkit, and the Fighter goes up in fire and smoke. The music stops, and a short jingle plays. A moment later the window darkens behind a red banner: GAME OVER, YOUR SQUADRON FIGHTS ON WITHOUT YOU. Your final score sits under it, with the best score so far. Press Enter, and a new mission begins.
So the mission has a state now, one of two: it’s being played, or it has failed. That’s the Game State, one word the whole game shares. It works like the sign on a shop door. Anyone can read it, and when it turns from Playing to Mission Failed, every piece of Logic that cares hears it turn. The music stops. The Fighter falls, and the guns go quiet.
The best score is kept as a Persistent Value, a value Myth Engine keeps for your game between plays. Close the game and play again, and it’s still there.
The Zero Fighters’ guns need one more thing. An Event can answer in more than one way, and each way is a Mode, with a name and Actions of its own. When an Event is Combined, several of its Modes answer together. The game can even swap one for another while it runs. That swap is the whole difference between a pilot who aims and a pilot who doesn’t.
4.2 The Plan
Here’s how the pieces work together. Read each line from left to right. Most of these names are new now, so skim the list, and come back to it after each part. Once you’ve met the pieces, it reads like a map.
- The Scene starts -> Mission Start sets the Game State to Playing and fills the medkits -> Mission Music plays the Battle Theme and the Engine Drone.
- A Zero Fighter appears -> Zero Fighter Guns chooses its pilot and plans its first shot.
- The enemyFire timer rings -> the plane fires, if the mission is still on and the plane is in its firing band -> the timer is set again.
- An Enemy Round touches the Fighter -> Breaks on Fighter breaks it in sparks.
- A round or a plane touches the Fighter -> Hurt by Enemies calls Hurt the Fighter -> unless the Fighter is protected: protection, a flash, a shake, and fighterHit.
- The fighterHit message arrives -> Lose a Medkit takes a medkit and Lose a Gun Level a gun level -> Show Medkits hides an icon.
- The protectionStarted message arrives -> Protection Blink blinks the Fighter until its protection runs out.
- The last medkit goes -> Lose a Medkit sets the Game State to Mission Failed -> the Fighter explodes, the music stops, and High Score keeps a better score.
- 2.4 seconds later -> the Mission Failed Logic Component’s timer rings -> showResults brings up the result screen, and Fly Again is turned on.
- Enter or Space -> Fly Again -> Start a New Mission restarts the Scene.
4.3 Set Up
This chapter adds a key, two shared numbers and a second Game State. Its pictures and sounds came with the Starter Kit.
EnterPlaying, Mission FailedConfirm is a Button Command, the way Fire is, so press Add Command in the Input Manager and name it Confirm. Click its No Input Assigned row, and press Enter.
The card’s Game State line, Available Game States, names both states, Playing and Mission Failed. Your project already has Playing. To see it, open the Game Settings and choose General. Under Game State, Playing is marked Initial, and every mission starts in it.
Press the + under the list, Add Game State, and type Mission Failed in the window. Its own Add Game State button finishes it. The Set up card on Making what a card shows has this too.
The two Globals wait for the Logic Components that use them first. You’ll make $medkits in the first part, A mission of its own, and $highScore in The last medkit, each with the + on the Globals card. PLACE THESE comes as each Object is made. REMOVED comes at the end of Medkits, once nothing needs it.
One habit carries over from Chapters 2 and 3. When a piece’s blocks read its SHARED VARIABLES, make them first, with the + on the canvas’s Shared Variables card. Then each block finds them.
4.4 A Mission of Its Own
First, the mission gets a beginning.
Every time Gameplay starts, a fresh mission starts with it. The Game State says Playing, the score is 0, there are three medkits, and the gun level is 1. Nobody sees this happen. It’s over before the first picture is drawn.
4.4.1 Mission Start
Mission Start does all of that. Its one Event, When the Scene Starts, is a Scene Start Event. It runs once each time the Scene starts. The Scene’s Objects are placed by then, but none of them has run its When Created yet. So every When Created in the Scene finds the mission already set up.
Its two Shared Variables are numbers, startMedkits and startGunLevel, both Constants. They’re the mission’s starting medkits and gun level. So Game Rules could start a mission with five medkits by changing one box.
Set Game State starts on Playing, the Game State marked Initial. Leave it there. Then three Change Variables set the score, the medkits and the gun level. Make $medkits before them, with the Globals card’s New Global…, the way you made the score in Chapter 3: Name medkits, Type Number, Default 3.
Sets up a fresh mission each time the Gameplay Scene starts: Playing, score 0, startMedkits medkits, gun level startGunLevel.
Any Object- Game State
Playing
- Variable
$score- Value
0
- Variable
$medkits- Value
@self.startMedkits
- Variable
$gunLevel- Value
@self.startGunLevel
Attach Mission Start to Game Rules.
4.4.2 Mission Music
The mission has a sound of its own now. The Battle Theme plays over and over, with an engine’s low drone under it, until the mission fails. Then both stop, and the Game Over Jingle plays once.
Mission Music makes all of it. Its first Event, When the Scene Starts, starts the two loops.
A new Control Sound’s Operation list starts on Play, which plays a sound once. Pick Loop for both. Then each plays over and over until something stops it. The jingle keeps Play. That’s why its line on the card has no Operation.
The second Event, On Game State Changed, runs whenever the Game State changes. It doesn’t say which way, so the Logic asks. A new Check Game State starts on Playing, so pick Mission Failed in its list. Its Action Name starts as gameStateResult, so type missionFailed over it. The If does the rest.
Each Sound is a list. Where the card has “Battle Theme”, pick Battle Theme from your project’s sounds.
Nothing changes the Game State to Mission Failed yet. Lose a Medkit will, in the part named A round gets through, once a hit can cost something.
Plays the Battle Theme and the engine drone during the mission, and the Game Over Jingle when it fails.
Any Object- Operation
Loop- Sound
"Battle Theme"
- Operation
Loop- Sound
"Engine Drone"
- Action Name
missionFailed- Game State
Mission Failed
missionFailed.value == true- Operation
Stop- Sound
"Battle Theme"
- Operation
Stop- Sound
"Engine Drone"
- Sound
"Game Over Jingle"
Attach it to Game Rules too. Save your project with Ctrl+S, and run the game. The Battle Theme plays as the sea slides, with the engine’s drone under it. Nothing else has changed. With the game in front, Alt+F4 brings you back.
4.5 They Shoot Back
Now the Zero Fighters fire.
Their rounds are Enemy Rounds, small orange balls, bright at their edges. The Enemy Round is a 2D Object. Its picture is 3 meters across, like the MG Round’s, but the ball is only a small dot in its middle. The rest is clear. Its Physics Object switch stays on, as the MG Round’s does.
Like the Fighter’s rounds, it wears a Tag of its own: Enemy Fire. Attach Tags, and create Enemy Fire the way you made Fighter Round, in Two Tags, the first part of Chapter 3. Its Scene Depth Draw Order of 45 is above the Fighter’s 30, so a round passes over the Fighter, never under it.
Its Collider is a Sensor, about a third of a meter across. Collision has three buttons: Solid, Sensor and Off. A Sensor notices a touch but never pushes, and its collision Events still run. So a round never shoves the Fighter aside. Under Tags and Interactions, it may touch only the Fighter.
Its two Logic Components come last. One is Remove When Out of View, which you know, and the other is Breaks on Fighter, below.
X 3, Y 345Enemy Round ArtX 3, Y 3SensorX 0.313, Y 0.313Collide Only WithFighterEnemy Fire4.5.1 Breaks on Fighter
A round reaches the Fighter, throws off a little spray of sparks, and is gone.
Breaks on Fighter is Breaks on Hit turned around. The touch it waits for is the Fighter’s, so pick Fighter in Collision Target, in its Event’s Collision section. The Fighter is one Object, not a Tag, so pick it by its own name. Its hitSparksCount is a Constant Shared Variable, 6, like Breaks on Hit’s. The sparks burst from the round, so the round removes itself last.
It sends no message. Telling the Fighter it was hit is another piece’s job, in the next part.
An enemy round that hits the Fighter breaks with a small spark.
Any Object- Particles
"Hit Sparks"- Count
@self.hitSparksCount- Z Index Offset
2
Attach Remove When Out of View and Breaks on Fighter to the Enemy Round, in that order.
The Fighter needs one change now. Add Tagged Enemy Fire to its Collide Only With list, beside Tagged Enemy Aircraft, so a round can reach it. On its Changes card, that field shows twice. The line with both Tags is green, and the old one, with Enemy Aircraft alone, is struck under it. It’s still one list. The three green Logic Components at the bottom come later in this chapter, one by one.
X 3, Y 3Off30Fighter ArtX 3, Y 3X 0, Y -0.094X 0.656, Y 0.75Collide Only WithTagged Enemy Aircraft, Tagged Enemy FireTagged Enemy Aircraft10.3131.31321.1887.18830MG RoundNext, the guns get their flash. The Enemy Muzzle Flash is five sparks thrown downward from a plane’s nose, cream, orange and a deep orange-red. In about a tenth of a second they’re gone. It’s the Fighter’s own Muzzle Flash turned to point down, with one spark fewer than the Fighter’s six. After the Shot, in Zero Fighter Guns, bursts it at each plane’s nose as it fires.
05pointmin 60, max 140min 0.938, max 3.125min -110, max -70FX SparkMultiple Colors#FFF0D0, #FF9A3C, #FF5A1F1.2start 0.6, end 0Random Spin On4.5.2 Wait for the Firing Band
A Zero Fighter fires only inside its firing band. That’s the stretch of sky from bandTop, a little under the top of the window, down to bandBottom, low in the window. A plane appears above the window, so its first shot may come due before it’s in the band. It has to wait.
How long? That’s the one question Wait for the Firing Band answers. It starts by putting the delay the plane wants into wait. Next, it works out how long the plane needs to fly down to bandTop: its height above bandTop, divided by its speed. That’s secondsToBand. If secondsToBand is longer, wait takes it. So the answer is whichever is longer.
This is the first Function in the book that hands something back. Its RETURN TYPE is Number. Pick it in Logic Settings, the gear in the canvas’s toolbar, and the card’s last step, Return, hands back wait. A Function card shows both.
The Function makes wait and secondsToBand for itself, in its first two steps, with Declare Variable. Each is a Number that starts at 0. After that, the card names them plainly.
Caller comes first among its PARAMETERS, made as in Chapter 2, with its pencil. It takes whichever Object calls. The three numbers follow it.
How many seconds from now a plane may first fire: delay seconds, or longer if the plane, flying straight down at speed meters per second, has not yet reached bandTop, the top of its firing band.
- Name
wait- Value
0
- Name
secondsToBand- Value
0
- Variable
wait- Value
delay
- Variable
secondsToBand- Value
(Caller.transform.position.y - bandTop) / speed
secondsToBand > wait- Variable
wait- Value
secondsToBand
- Value
wait
In Chapter 7, two more guns ask it the same question.
4.5.3 Aim Down at the Fighter
An aimed round flies at the Fighter. But a pilot only ever fires downward, never sideways and never back up the window. Aim Down at the Fighter works out that direction, in degrees.
First, is the Fighter below the plane at all? If it isn’t, there’s nothing to aim at, and the first If’s Else gives straight down: 270. Right-click that If and choose Add Else, as in Chapter 2. If the Fighter is below, the Function measures across and up from the plane to the Fighter.
Then atan2 turns those two into an angle, and radtodeg puts it in degrees. Directions in Sky Ace count from pointing right. They turn counterclockwise as the number grows, as in Chapter 2, so 270 is straight down.
But below the plane, atan2 counts the other way round, so its numbers there are under 0. Straight down comes out as minus ninety. Adding 360 makes it 270, the game’s own straight down. Last, two Ifs hold it between aimMin and aimMax, 200 and 340, so no round flies out almost sideways.
Those two Ifs sit one after the other on the first If’s True line, steps 8 and 10. Step 9 sits inside step 8. Each If’s right-click menu has its own Add inside Then, and it adds to that If’s own line. So for step 10, right-click the first If, at step 4, not the one at step 8. Connect to sequence joins the new If at the end of that True line, after step 8’s.
Like Wait for the Firing Band, it declares its numbers first. It ends with a Return, here of aim. The fighter Parameter is its second Object Parameter, after Caller, made the same way with its pencil. It asks only for a Transform, so give it the card’s Required Component.
The direction from the caller to the Fighter in degrees, kept between aimMin and aimMax (downward only), or straight down (270) when the Fighter is not below.
transformTransform- Name
across- Value
0
- Name
up- Value
0
- Name
aim- Value
0
fighter.transform.position.y < Caller.transform.position.y- Variable
across- Value
fighter.transform.position.x - Caller.transform.position.x
- Variable
up- Value
fighter.transform.position.y - Caller.transform.position.y
- Variable
aim- Value
radtodeg(atan2(up, across)) + 360
aim < aimMin- Variable
aim- Value
aimMin
aim > aimMax- Variable
aim- Value
aimMax
- Variable
aim- Value
270
- Value
aim
4.5.4 Zero Fighter Guns
Here are the guns themselves, on the longest card yet. It comes in two pieces, one for each Event.
A Zero Fighter appears. In that moment it settles two things: what kind of pilot it has, and when it fires first. Each one is a Mode. Both answer When Created together.
Choose a Pilot rolls a whole number from 0 to 99, pilotRoll, and a roll below aimedChance, which is 50, makes a pilot who aims. For that pilot, Turn Off Mode takes Shoot Straight out of the timer’s Event, and Turn On Mode puts Shoot Aimed in its place. About half the pilots aim.
The second Mode has the Function’s name, Wait for the Firing Band, because calling that Function is its job. It picks a first delay at random, between 0.4 and 1.1 seconds, as firstShot. It hands that to the Function, with bandTop and the plane’s own speed from its Enemy Stats. The call’s Action Name is firstShotWait, so its answer, firstShotWait.value, becomes the First Delay of the enemyFire timer. The timer rings once.
The card shows an Event once for each of its Modes. So When Created is on it twice, and On the Enemy Fire Timer four times. Still, the Logic Component has two Events: When Created, with two Modes, and On the Enemy Fire Timer, with four.
Build it in an order that lets each list find what it names. First come its fifteen SHARED VARIABLES, all Constants. The first two, round and fighter, are of Type Object. Their Starting Value stays at None. The Zero Fighter’s card picks them later, under its own Shared Variables. Then the numbers, in the card’s order. Then press the + on the Data Structures card, and pick Enemy Stats under Existing Data Structures, as for Fly Down in Chapter 3.
Next come both Events and all their Modes. The Actions wait. Rename When Created’s Mode 1 to Choose a Pilot, and add Wait for the Firing Band with New Mode…. Then pick Combined in its Modes, and turn on On at start on both Mode blocks.
The timer’s Event is a Recurring Timer. Myth Engine asks which timer, so choose Type a timer name… and press OK. Then type enemyFire in the box that comes next. Its four Modes are on the card’s second piece, and three of them answer each ring, left to right. So make them in the card’s order: Still Firing?, Shoot Straight, Shoot Aimed, After the Shot. Pick Combined, and turn on On at start on every one but Shoot Aimed, which waits for Choose a Pilot to turn it on.
On the card, (Combined, On at start) marks every Mode whose switch is on. Two carry it under When Created, and three under the timer. Events: the When bars shows where each switch is.
The Actions come last. Each Mode has a line of its own, so give each one its blocks in turn. Turn Off Mode and Turn On Mode pick On the Enemy Fire Timer in their Event list, and then the card’s Mode.
Go by the card for the boxes. Each Timer Name takes enemyFire bare, and Ring Once is a list: Yes. The call to Wait for the Firing Band has fields named for the Function’s Parameters. Its caller list starts on self, as the card has it. Its bandTop, speed and delay are boxes, so type the card’s values into them.
Here’s the order once more: Shared Variables and Enemy Stats, Events and Modes, switches, Actions.
A Zero Fighter fires every couple of seconds while inside its firing band: half the pilots aim down at the Fighter, the rest fire straight down.
Any Objectself.enemyStats- Action Name
pilotRoll- Maximum
99
pilotRoll.value < @self.aimedChance- Event
On the Enemy Fire Timer- Mode
Shoot Straight
- Event
On the Enemy Fire Timer- Mode
Shoot Aimed
- Action Name
firstShot- Minimum
@self.firstShotMin- Maximum
@self.firstShotMax
- Action Name
firstShotWait- caller
self- bandTop
@self.bandTop- speed
self.enemyStats.speed- delay
firstShot.value
- Timer Name
enemyFire- First Delay (s)
firstShotWait.value- Ring Once
Yes
Still Firing? asks two things: is the mission still being played, and is the plane still above bandBottom? If either answer is no, Return ends this ring for the whole Event. There’s no shot, no flash, and no timer set again. That plane’s guns are done for good.
Its If’s condition is one box, with both questions joined by ||, or. Type it whole. Its Check Game State starts on Playing, the one it needs. Leave that list as it is.
Shoot Straight makes a round at muzzleY, a little over a meter below the plane’s middle. That’s its nose, since the plane flies nose down. The round turns to 270, straight down, and flies at straightSpeed, a little faster than the planes. Its Object to Create is @self.round, the round this plane carries.
Object to Create is a list. It holds self and this Logic’s Object Variables, so pick @self.round there.
Shoot Aimed asks Aim Down at the Fighter first, as fighterAim. The call’s fighter is a list too, and @self.fighter is in it, the Fighter this plane carries. Pick it.
Build Shoot Straight’s Actions before Shoot Aimed’s. Its Create Instance takes the name created, in Created As. When you add Shoot Aimed’s Create Instance, Myth names it created2 by itself, because this Logic Component already has a created. Set Direction and Set Speed after it start on created2. The round flies along fighterAim.value.
After the Shot is the flash and the sound: five sparks of the Enemy Muzzle Flash at the nose, and Enemy Guns. Last, it picks the next gap, between 1.7 and 2.5 seconds, and starts the timer again. So each plane keeps its own uneven beat.
- Action Name
stillPlaying- Game State
Playing
stillPlaying.value == false || self.transform.position.y <= @self.bandBottom- Object to Create
@self.round- Position Relative To
Self- Y
@self.muzzleY
- Applies To
created- Direction
270
- Applies To
created- Speed
@self.straightSpeed
- Action Name
fighterAim- caller
self- fighter
@self.fighter- aimMin
@self.aimMin- aimMax
@self.aimMax
- Object to Create
@self.round- Position Relative To
Self- Y
@self.muzzleY- Created As
created2
- Applies To
created2- Direction
fighterAim.value
- Applies To
created2- Speed
@self.aimedSpeed
- Particles
"Enemy Muzzle Flash"- Y
@self.muzzleY- Count
@self.enemyMuzzleFlashCount- Z Index Offset
2
- Sound
"Enemy Guns"
- Action Name
nextShot- Minimum
@self.shotGapMin- Maximum
@self.shotGapMax
- Timer Name
enemyFire- First Delay (s)
nextShot.value- Ring Once
Yes
Now give the Zero Fighter its guns. Attach Zero Fighter Guns, and switch the list back to Components. Their Values, under Shared Variables, read None. Press each one, and pick Enemy Round for round and Fighter for fighter.
X 3, Y 3Off20Zero Fighter ArtX 3, Y 3X 1.5, Y 1.125Collide Only WithFighter, Tagged Fighter RoundEnemy StatsData TableEnemy TypesEnemy AircraftExpressionobjectComponentProperty("self","dataStruct","health")ExpressionobjectComponentProperty("self","dataStruct","health")Enemy RoundFighterRun the game. The V comes down. As each plane drops into the window, a spark flashes at its nose and an orange round falls. Some fall straight, and some lean your way. A round that reaches the Fighter breaks in a spray of sparks, and for now, that’s all.
4.6 A Round Gets Through
Now a round can hurt.
4.6.1 Start Protection
After a hit, the Fighter blinks, and for a while nothing can hurt it. Every mission opens the same way. Start Protection begins that safe stretch, whoever asks for it.
It starts the Caller’s protection cooldown, which runs for as long as the Function’s seconds Parameter says. While it runs, Check Cooldown Ready says it isn’t ready, and that’s what protected means. Then it sends protectionStarted to the Caller alone.
Nothing listens for protectionStarted yet. At the end of this part, Protection Blink will.
In a Function, the Cooldown Key box reads a small formula, so the cooldown’s name goes in quotes there: "protection". Hurt the Fighter’s takes it the same way. Protection Blink, later in this part, is a Logic Component, and its box takes the name bare, as its card does. The message’s name goes in as it is.
Protects the caller for some seconds: starts its protection cooldown and its blinking.
- Applies To
Caller- Cooldown Key
"protection"- Seconds
seconds
- Applies To
Caller- Custom Event
protectionStarted
4.6.2 Hurt the Fighter
Hurt the Fighter is everything a hit does, from the first question to the last message, in one place. It opens with a question: is the Caller’s protection over? Check Cooldown Ready answers as canBeHurt. If the answer is false, the Fighter is protected, and nothing else happens.
If it’s true, the hit lands. Start Protection protects the Fighter for protectSeconds, 2.4 seconds. Thirty puffs of the Plane Explosion burst on the Fighter, and Fighter Hit plays. The camera shakes for 0.4 seconds, and a red flash covers the window for less than a fifth of a second. Last, Trigger Custom Event sends fighterHit.
Every block here works on Caller, the Function’s only Object Parameter, so each new block’s Applies To starts there. On Trigger Custom Event, that doesn’t narrow who hears it. Every Object that listens for fighterHit hears it, and Lose a Medkit, on Game Rules, will be listening. Caller only makes the Fighter its sender, as each plane was the sender of enemyShotDown in Chapter 3.
Why does fighterHit go last? It’s Chapter 3’s rule. A message is answered at once, and on the last medkit, fighterHit ends the mission then and there. By the end of this chapter, that removes the Fighter before the next Action. And an Action does nothing once its Object is gone. So the flash, the shake and the bang come first, and the news goes last.
Go by the card for the boxes. The Cooldown Key takes "protection" in its quotes, as in Start Protection. The call to Start Protection has a caller list, where you pick Caller, and a seconds box for protectSeconds. The flash’s Color is a swatch on its block. Click it, and type ff5a3c into the HEX box.
What happens when an enemy round or plane hits the Fighter: unless it is protected, it is protected for a while, the hit is seen and heard, and fighterHit tells Game Rules (a medkit and a gun level are lost there).
- Action Name
canBeHurt- Applies To
Caller- Cooldown Key
"protection"
canBeHurt.value == true- caller
Caller- seconds
protectSeconds
- Applies To
Caller- Particles
"Plane Explosion"- Count
planeExplosionCount- Z Index Offset
2
- Applies To
Caller- Sound
"Fighter Hit"
- Applies To
Caller- Intensity
shakeStrength- Seconds
shakeSeconds
- Applies To
Caller- Color
"#ff5a3c"- Seconds
flashSeconds
- Applies To
Caller- Custom Event
fighterHit
4.6.3 Hurt by Enemies
In Two Tags, the first part of Chapter 3, you added Tagged Enemy Aircraft to the Fighter’s Collide Only With list. This is what it was for. Hurt by Enemies goes on the Fighter, and it has three Events.
As the mission starts, it protects the Fighter for two seconds, so every mission opens with the Fighter blinking. And whenever the Fighter starts to touch an Enemy Fire round or an Enemy Aircraft plane, it calls Hurt the Fighter. A round breaks by itself, through its own Breaks on Fighter. A plane flies on.
Make its one Shared Variable first, startProtectSeconds, a Constant. The two touches are Collision Enter Events. Pick Tagged Enemy Fire in one’s Collision Target, and Tagged Enemy Aircraft in the other’s. In each call to Hurt the Fighter, caller starts on self. Leave its other boxes empty, as they start, and the Function uses its own Defaults.
An enemy round or an enemy plane that touches the Fighter hurts it (Hurt the Fighter); it starts every mission protected.
Any Object- caller
self- seconds
@self.startProtectSeconds
- caller
self
- caller
self
4.6.4 Lose a Medkit
Lose a Medkit is the first of two Logic Components on Game Rules that hear fighterHit. It takes one from $medkits. When none are left, it sets the Game State to Mission Failed.
This is Chapter 3’s idea again. The Fighter only says it was hit. Game Rules keeps the mission’s numbers, so Game Rules decides what a hit costs.
Hurt the Fighter sends fighterHit already, so the Add Event window knows it. Type fighterHit into its filter, and pick it. Set Game State starts on Playing, so pick Mission Failed there.
Each hit on the Fighter costs one medkit.
Any Object- Variable
$medkits- Operator
-=- Value
1
$medkits <= 0- Game State
Mission Failed
4.6.5 Lose a Gun Level
Lose a Gun Level takes one from $gunLevel, but only while it’s above 1. A hit never leaves the Fighter without guns. It hears fighterHit too.
Your gun level stays at 1 until the pickups of Chapter 8, so this piece has nothing to do yet. You can still watch it work. The next run shows how.
Each hit on the Fighter costs one gun level, but the gun level never goes below 1.
Any Object$gunLevel > 1- Variable
$gunLevel- Operator
-=- Value
1
Attach Hurt by Enemies to the Fighter, and both of these to Game Rules.
Run the game. Fly into a round, or into a plane. The window flashes red, the picture shakes, and fire bursts on the Fighter with a bang. For a little while after, rounds break on it and do nothing. That’s the protection, though you can’t see it yet.
A third hit already loses the mission. The music stops, a short jingle plays, and the planes’ guns go quiet. The Fighter stays, and nothing more happens. The rest of the chapter builds what comes after.
To watch Lose a Gun Level, open Game Rules, and look under Shared Variables in its Components view. Type 4 into startGunLevel’s Value. Now the mission starts with all four pips lit, and each hit puts one out. Put it back to 1 before you go on.
4.6.6 Protection Blink
Protection Blink makes the protection show. The Fighter turns dim, then bright, then dim, every twelfth of a second, until its protection runs out.
Its first Event listens for protectionStarted. Start Protection sends it, so the Add Event window knows it. The Event starts a timer named blink. The timer rings every blinkSeconds, a twelfth of a second, and its First Delay of 0 means the first ring comes at once.
The second Event, On the Blink Timer, is Combined, with three Modes. Myth Engine asks which timer, as before. Still Protected? and Go Dim have On at start on. Go Bright waits.
Go Dim and Go Bright take turns. Go Dim sets the Fighter’s alpha, how solidly it’s drawn, to dimAlpha, 0.3. Next, Turn Off Mode switches it off, and Turn On Mode switches Go Bright on. The swap counts from the next ring, so the next twelfth of a second belongs to Go Bright. Go Bright sets the alpha back to 1 and swaps the other way.
Two of the card’s Set Alphas have no lines under them. A new Set Alpha’s Alpha box starts at 1, fully solid, and that’s what both need. So leave them as they start.
Still Protected? comes first on every ring. Once the protection cooldown is over, it makes the Fighter solid again and stops the timer. Reset Modes puts the Event’s Modes back the way they started, so the next blink starts dim. Return comes last, so Go Dim doesn’t answer this final ring.
Make its two Shared Variables first, blinkSeconds and dimAlpha, both Constants, and then go by the card for the boxes. Here the Timer Names and the Cooldown Key are plain boxes. So blink and protection go in bare, as the card gives them, and the blocks draw them in quote marks.
This is the chapter’s third Combined Event, after Zero Fighter Guns’ two. Go Dim’s and Go Bright’s Turn Off Mode and Turn On Mode name no Event, so they work on the Current Event, where their Event list starts. Their Mode list holds this Event’s three Modes. Attach Protection Blink to the Fighter once it’s built.
While the Fighter is protected it blinks, dim and bright every blinkSeconds, and is bright again when protection ends.
Any Object- Timer Name
blink- Repeat Every (s)
@self.blinkSeconds- First Delay (s)
0
- Action Name
protectionOver- Cooldown Key
protection
protectionOver.value == true- Timer Name
blink
- Alpha
@self.dimAlpha
- Mode
Go Dim
- Mode
Go Bright
- Mode
Go Bright
- Mode
Go Dim
Run the game. The Fighter blinks for two seconds as the mission starts, then holds steady. Fly into a round, and after the red flash it blinks again, a little longer, before it holds steady.
That’s half the chapter. If you’d like a break, this is a good place for one. Save your project, and the next part starts from here.
4.7 Medkits
Next, the medkits show.
A Medkit Icon is a small white case with a blue cross, 32 pixels square. MEDKITS, in small coral-red letters, sits above the row of them. Both are screen Objects at Bottom Center.
Make them the way you made the pips in Chapter 2 and the score’s words in Chapter 3. The label’s Color is a swatch. Click it, and type FF8A80 into the HEX box.
The Object and its picture share a name, Medkit Icon. That’s fine. Myth Engine keeps an Object and a picture apart, and the Sprite list holds only pictures.
Window / UIBottom CenterUIX 128, Y 128102Medkit IconX 32, Y 32Window / UIBottom CenterUIX 128, Y 48MEDKITSBebas Neue18#FF8A801Wrap to Width1804.7.1 Show If At Least
Show If At Least is Show Pip For Gun Level made a little wider, so the medkits can use it too. The old Function always compared the gun level. This one compares any value it’s given. If the value is at least level, it shows the Caller. Its Else hides it.
Shows the caller while a value is at least the given level, and hides it otherwise.
value >= level- Applies To
Caller- Visible
true
- Applies To
Caller- Visible
false
4.7.2 Show Medkits
Show Medkits works the way Show Gun Level does. When the icon appears, and whenever $medkits changes, it asks Show If At Least, with this icon’s level and $medkits. With three medkits, icons 1 to 3 show, and 4 and 5 hide.
Its level is the card’s PER INSTANCE VARIABLES, made as on Show Gun Level. For its second Event, Myth Engine asks which Global Variable, so pick medkits. In each call, caller starts on self. Type $medkits into the value box and self.level into the level box.
Shows this medkit icon while the Fighter has at least its number of medkits (1 to 5).
Any Object- caller
self- value
$medkits- level
self.level
- caller
self- value
$medkits- level
self.level
Show Gun Level now asks the new Function too, in place of the old one. On its Changes card, both old calls are struck. Right-click each one, and choose Delete. Then add a call to Show If At Least in each Event, with $gunLevel as the value. Changes cards has more on deleting.
These new calls list level before value on the card. On the block, the boxes keep the Function’s own order, value and then level. Go by their names.
Shows this power pip while the gun level is at least its level (1 to 4).
Any Object- caller
self- level
self.level
- caller
self- level
self.level- value
$gunLevel
- caller
self- level
self.level
- caller
self- level
self.level- value
$gunLevel
Now nothing calls Show Pip For Gun Level. That’s why it’s REMOVED on the Set up card. Right-click it in the Resources, and choose Delete at the bottom of the menu.
Attach Show Medkits to the Medkit Icon. Place the icon five times from PLACE THESE. The line under four of the rows, such as with Per Instance Variables > Level = 2, is that icon’s own level. The first has none, because 1 is where level starts. In Show Medkits’ section of each placement’s Logic, type the line’s value into the Level box, as you did for the pips. The label goes above them, with its Z-Index of 120. All six hang from Bottom Center, so their X is below 0, to the left of the middle.
Run the game. Three medkits glow at the bottom left, under MEDKITS. Take a hit, and the third goes out.
4.8 The Last Medkit
Now a mission can end.
The Big Explosion is the Plane Explosion grown large: 110 bigger puffs in five fiery colors, flung out faster and wider, some lasting longer than a second. It’s the Fighter’s last burst. Lost With the Last Medkit, next, sets it off.
01101.25min 400, max 1400min 2.5, max 14.375FX Smoke PuffMultiple Colors#FFFFFF, #FFF1B8, #FFB347, #FF6A3C, #6B2B2B1.8start 2.4, end 00.7Random Spin On4.8.1 Lost With the Last Medkit
The last medkit goes. The Fighter bursts in a ball of fire far bigger than any plane’s, and smoke rolls out after it. A boom, a long, hard shake, and the Fighter is gone.
It doesn’t wait to be told it was hit for the last time. Like the music, it watches the Game State. When the Game State turns to Mission Failed, the Fighter does all of that to itself, and removes itself last.
The smoke is the Smoke Puff you made in Chapter 3. Burst Particles’ Count wins here, as it did there, so 20 puffs burst, more than the effect’s own Burst Count. The four numbers are its Shared Variables, all Constants. Check Game State starts on Playing, so pick Mission Failed.
When the mission fails, the Fighter explodes and is removed.
Any Object- Action Name
missionFailed- Game State
Mission Failed
missionFailed.value == true- Particles
"Big Explosion"- Count
@self.bigExplosionCount- Z Index Offset
2
- Particles
"Smoke Puff"- Count
@self.smokePuffCount- Z Index Offset
2
- Sound
"Explosion Large"
- Intensity
@self.shakeStrength- Seconds
@self.shakeSeconds
Attach it to the Fighter.
4.8.2 Add Points
Rounds already in the air fly on after the Fighter is gone. Should a plane they bring down still score? Not once the mission is lost. So Add Points checks the Game State first, and adds the points only while it’s Playing.
On its Changes card, the old Change Variable is struck, and the same block comes back inside the new If. Delete the old one, and build the three new steps. Check Game State stays on Playing, as it starts.
Adds the points of every enemy shot down to the score, while the mission is being played.
Any Object- Variable
$score- Operator
+=- Value
event("points")
- Action Name
stillPlaying- Game State
Playing
stillPlaying.value == true- Variable
$score- Operator
+=- Value
event("points")
4.8.3 High Score
High Score keeps the best score. When the Scene starts, Load Persistent Value reads the one kept under the key highScore, or 0 if there’s none yet. $highScore takes it.
When the Game State changes to Mission Failed, a second If compares the score with it. If the score is higher, $highScore takes the score, and Save Persistent Value keeps it under the same key.
Make $highScore first, with the Globals card’s New Global…. It’s made like $medkits: Name highScore, Type Number, Default 0. Each Key box takes the name in its quotes, "highScore", as the card has it. The Action Name of Save Persistent Value, persistentWriteResult, is the one its block starts with. And its Check Game State gets Mission Failed, like the others.
Reads the high score from this device when a mission starts, and saves a better score when the mission ends.
Any Object- Action Name
savedHighScore- Key
"highScore"- Default
0
- Variable
$highScore- Value
savedHighScore.value
- Action Name
missionFailed- Game State
Mission Failed
missionFailed.value == true$score > $highScore- Variable
$highScore- Value
$score
- Action Name
persistentWriteResult- Key
"highScore"- Value
$highScore
Attach it to Game Rules.
The high score gets a place in the middle of the top bar. High Score Label and High Score Text are made like Score Label and Score Text, at Top Center. Their words are centered, so they sit over the middle of the bar.
Window / UITop CenterUIX 128, Y 48HIGH SCOREBebas Neue20#F4C5421CenterWrap to Width200Window / UITop CenterUIX 128, Y 48{$highScore}Bebas Neue321CenterWrap to Width240Place them from PLACE THESE, each with its Z-Index of 120.
Three medkits are a lot to lose on purpose. To reach the end sooner, open Game Rules, and under Shared Variables in its Components view, type 1 into startMedkits’ Value. One hit ends the mission then, so put it back to 3 before Chapter 5.
Run the game. HIGH SCORE sits in the middle of the top bar. Shoot down a plane, then lose your last medkit. The Fighter bursts into fire and smoke with a boom, the music stops, and the jingle plays. If you beat the high score, it jumps to your score at once. After that the sea slides on, and nothing more happens until the next part brings the screen.
4.9 GAME OVER
Last comes the screen at the end, and the way back into the sky.
Six screen Objects make it. Each is centered on the screen, and each is placed hidden until it’s needed. The Result Veil is one white pixel stretched over the whole window and tinted nearly black. At an opacity of 0.6, the game shows dimly through it. The Game Over Banner is its art, a red banner reading GAME OVER and YOUR SQUADRON FIGHTS ON WITHOUT YOU.
Final Score and Result High Score are words, white and gold. Fly Again Key is a picture of the Enter key, and Fly Again Prompt says FLY AGAIN beside it, in pale blue.
Each piece has its own layer, from back to front, so the veil sits behind the rest. Its Sprite has a Scene Depth Draw Order of 140, the banner’s has 141 and the key’s 142. The three lines of words have no Sprite, so their 142 is a Z-Index, which they get when they’re placed.
Make each one an Empty Object with Space Window / UI first. The six cards start alike, and the three word cards differ in their words, sizes and colors. Final Score’s Text has two spaces before its brace. So does Result High Score’s.
The veil’s card has one Sprite line to leave for now, Tint (on its placement). It goes on the placement, at the end of this part.
Window / UICenterUIX 128, Y 128140White PixelX 720, Y 960#020B14Window / UICenterUIX 128, Y 128141Game Over Banner ArtX 640, Y 170Window / UICenterUIX 128, Y 48FINAL SCORE {$score}Bebas Neue481CenterWrap to Width600Window / UICenterUIX 128, Y 48HIGH SCORE {$highScore}Bebas Neue30#F4C5421CenterWrap to Width600Window / UICenterUIX 128, Y 128142Key Enter IconX 72, Y 36Window / UICenterUIX 128, Y 48FLY AGAINBebas Neue28#BCD7E81CenterWrap to Width1064.9.1 Show With Results
All six use one Logic Component. Show With Results waits for showResults, the message Game Rules will send when the screen is due. When it hears it, it asks whether the Game State is this piece’s own. If so, it shows the piece at its opacity.
Each piece says which Game State it belongs to, in a Per Instance Variable, state. It starts at mission-failed. That’s how Myth stores the Game State Mission Failed. Here every piece belongs to Mission Failed. In Chapter 9 the same Logic Component brings up the screen of a mission won, and those pieces give another state.
Press the + on the canvas’s Per Instance Variables card. Give state the Type Text, and type mission-failed into its Starting Value, with no quotes. Then make opacity, a Number that starts at 1, for every piece. Only the veil gives it another value.
Nothing sends showResults yet. Mission Failed will, at the end of this part. So in the Add Event window, type Custom into the filter, pick Add Custom Event…, and press OK. Myth Engine asks for the Event Name. Type showResults.
Its Check Game State reads state, so that every piece checks its own. That’s the card’s self.state. Open the Game State list. Under your Game States, it holds this Logic’s Per Instance Variables, so pick self.state there.
Shows this result screen piece when Game Rules sends showResults, if the Game State is the piece's own.
Any Object- Action Name
stateMatches- Game State
self.state
stateMatches.value == true- Alpha
self.opacity
- Visible
Yes
Attach Show With Results to all six pieces, from the veil to FLY AGAIN.
4.9.2 Start a New Mission
Press Enter on the GAME OVER screen, and Menu Select sounds. You’re over the sea again, with a fresh mission.
That’s Start a New Mission. Restart Scene starts Gameplay over from the beginning. Mission Start does the rest, as it does every time the Scene starts.
Starts a new mission: plays Menu Select and restarts the Gameplay Scene.
- Applies To
Caller- Sound
"Menu Select"
- Applies To
Caller
4.9.3 Fly Again
Fly Again listens for Confirm and for Fire, and either one calls Start a New Mission.
But it mustn’t listen during the mission, or every press of Space would start the mission over before it’s lost. So it’s attached to Game Rules switched off. After you attach it, click the switch on its row in the Attached Logic, so it’s gray. A Logic Component that’s off answers no Events.
The next one turns it on when the screen shows. And a restart builds every Object again as you made it, so in the new mission Fly Again is off once more.
On the result screen, Confirm (Enter) or Fire starts a new mission. It is off until the result screen shows (Mission Failed turns it on).
Any Object- caller
self
- caller
self
4.9.4 Mission Failed
This Logic Component is named after the Game State it waits for, and it ties the end together. The Fighter bursts, and for a moment the sea slides on as if nothing happened. Then the screen comes, all six pieces at once, and Enter works again.
That moment is a timer named resultScreen. When the Game State changes to Mission Failed, the timer starts, and it rings once, resultSeconds later, which is 2.4 seconds. When it rings, Trigger Custom Event sends showResults to every Object that listens, and all six pieces hear it. Last, Set Logic State turns Fly Again on.
Make its one Shared Variable first, resultSeconds, a Constant, then go by the card for the boxes. The Timer Name takes resultScreen bare, and Ring Once is a list: Yes. Set Logic State’s Logic Component is a list too. Where the card has “Fly Again”, pick Fly Again, and leave State on Enable. Its Check Game State gets Mission Failed. For the timer’s Event, Myth Engine asks which timer, as for enemyFire.
When the mission fails, resultSeconds later it shows the result screen and switches FLY AGAIN on.
Any Object- Action Name
missionFailed- Game State
Mission Failed
missionFailed.value == true- Timer Name
resultScreen- First Delay (s)
@self.resultSeconds- Ring Once
Yes
- Custom Event
showResults
- Logic Component
"Fly Again"
Attach it to Game Rules. Here is Game Rules now, with all nine, and Fly Again turned off. Your rows may be in another order, since you attached them as you made them. That’s fine here: none of them needs another to go first.
X 3, Y 3Run Mission TimelineRun Mission Timeline DataNow place the screen from PLACE THESE. All six are hidden, so turn off each one’s Visible at Game Start. The three lines of words get their Z-Index of 142.
The veil’s line on the card, with Per Instance Variables > Opacity = 0.6, is its own opacity. In Show With Results’ section of its placement’s Logic, type 0.6 into the Opacity box.
The veil’s Tint goes on its placement too. Select the veil in the Scene, open Sprite under Rendering, and click the Tint swatch. Type 020B14 into its HEX box, and the veil is done. A placement’s own values has this too.
Run the game, and lose the mission. The Fighter bursts, the music stops, and for two seconds and a little more, nothing happens. The window darkens, and there it is: GAME OVER.
Press Enter. You’re flying again, with a score of 0 and your medkits back.
Watch for each of these.
- The Battle Theme starts with the mission, with an engine’s drone under it.
- The Fighter blinks for two seconds as the mission starts.
- Once the Zero Fighters are in the window, they fire: small orange rounds, each with a spark at a plane’s nose. Some fall straight, and some lean toward you.
- A round that touches the Fighter breaks in a spray of sparks.
- A hit that lands: a red flash, a shake, a burst of fire on the Fighter, a bang, and one medkit goes out at the bottom left.
- After a hit, the Fighter blinks for 2.4 seconds, and rounds that touch it then do no harm.
- Fly into a Zero Fighter. That costs a medkit too, and the plane flies on.
- Lose the last medkit: a big burst of fire and smoke, a long shake, and the Fighter is gone. The music stops, and a short jingle plays.
- If you beat the high score, HIGH SCORE in the middle of the top bar jumps to your score at once.
- 2.4 seconds later, the window darkens behind GAME OVER, FINAL SCORE, HIGH SCORE and FLY AGAIN.
- Press Enter, or Space. A new mission starts with a score of 0, and the high score stays.
- With the game in front, press Alt+F4, then press Play again. HIGH SCORE still shows your best.
The mission starts Playing. The Zero Fighters fire while it is, and a hit costs a medkit. Protection keeps the next hit away for a moment. The last medkit turns the Game State to Mission Failed, and the screen follows.
Underneath it all is the Game State. Lose a Medkit never stops the music, removes the Fighter or shows the screen. It turns one shared word, and everything that cares about that word answers by itself. The guns go quiet. The music stops. The Fighter falls, the high score is kept, and the screen appears. In Chapter 9, the same word will say Mission Complete, and the same pieces will answer again.
4.10 If It Didn’t Work
Something may be a little off the first time. That’s normal. This chapter is the longest yet, and one gray switch can hide a lot. Run the game, watch what it does, and think it through one piece at a time.
No music? Look for Mission Music on Game Rules, and check that both Operation lists say Loop.
The Zero Fighters never fire? Is Zero Fighter Guns in the Zero Fighter’s Attached Logic? Look next at its Events. Both should be Combined, with On at start on for every Mode but Shoot Aimed. Perhaps the Game State never became Playing. Mission Start sets it, so look for Mission Start on Game Rules. Last, the timer’s name: enemyFire, bare, in the box Myth asked for and in both Start Recurring Timers.
A plane fires two rounds at once? Then Shoot Straight and Shoot Aimed are both answering. Look at Choose a Pilot. Turn Off Mode should switch off Shoot Straight, and Turn On Mode should switch on Shoot Aimed, both in On the Enemy Fire Timer. Shoot Aimed’s own On at start should be off.
The rounds fly through the Fighter? Check the Tags first, and then the lists on both Colliders. The Enemy Round wears Enemy Fire, and its Collider meets the Fighter. The Fighter’s Collider meets Tagged Enemy Fire. Breaks on Fighter goes on the Enemy Round, with Fighter as its Collision Target.
The rounds break, but nothing else happens, ever? Hurt by Enemies should be on the Fighter. Compare the cooldown’s name in Start Protection and in Hurt the Fighter: both should read "protection". A Fighter whose protection never ends can’t be hurt.
The music stops after a few hits, and the planes go quiet, but the Fighter stays and no screen comes? That’s a lost mission with nothing built yet to end it. Look for Lost With the Last Medkit on the Fighter and Mission Failed on Game Rules.
The Fighter never blinks? Protection Blink’s first Event should be for protectionStarted, spelled the way Start Protection sends it. Look at On at start too: on for Still Protected? and Go Dim, off for Go Bright.
The Fighter stays dim? Look at Still Protected?. Its key should read protection, bare, and its Set Alpha should still hold 1, as it starts.
No medkits at the bottom? Show Medkits belongs on the Medkit Icon, and each of its five placements needs its own level, 1 to 5. Select one of the last four, and Show Medkits’ section should count 1 override.
The Fighter takes hit after hit, and the mission never ends? Look at Lose a Medkit’s If, $medkits <= 0, and at its Set Game State, which should pick Mission Failed.
The Fighter explodes, but no screen comes? Look at Mission Failed on Game Rules, and the timer’s name, resultScreen, bare, in its Start Recurring Timer. Look at the six pieces next. Each needs Show With Results, with self.state in its Check Game State. The name showResults should be spelled the same in Mission Failed and in Show With Results.
The screen is there as soon as the game starts? Each of its six placements needs Visible at Game Start off.
The screen shows, but Enter does nothing? Is Confirm’s key Enter? If it is, look at Mission Failed’s Set Logic State, which should name Fly Again.
Space starts the mission over every time you fire? Fly Again is on when it should be off, so look at its switch on Game Rules. It should be gray.
Each of these is one small fix. Make it, run the game again, and you’re back with the chapter. And if you’d like to compare, the catch-up download in the Goal is this chapter’s game, finished.
The mission is yours to tune now. Give the Fighter five medkits with startMedkits, under Game Rules’ Shared Variables, and watch five cases glow. Or make every pilot aim. Open the Zero Fighter, and raise aimedChance under Shared Variables. What’s the smallest number that makes every roll aim?
Or give the hit a color of your own: change the red of the flash in Hurt the Fighter.
Chapter 5 starts from the card’s values. Before you go on, put them back as the cards have them, or save a copy of your game first so you can come back to it. Or start Chapter 5 from the catch-up download.
Still stuck? Search the manual, or ask in the Myth Engine Discord (opens a new tab).
Your Fighter can be hit now, and lost, and sent up again. In Chapter 5, the sea below it fills with islands, ships and clouds.
