Build a GameCreating Sky Ace

4  Mission Failed

Goal

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.

Sky Ace, Chapter 4 finishedZip of a Myth project · 4.1 MB

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.

Set upWhat this chapter adds
ART (sprites, from the starter kit)
Enemy Round Art
Medkit Icon
White Pixel
Game Over Banner Art
Key Enter Icon
SOUNDS (from the starter kit)
Enemy Guns
Fighter Hit
Explosion Large
Game Over Jingle
Battle Theme
Engine Drone
Menu Select
COMMANDS (Game Settings > Input Manager)
ConfirmButton
KeybindingsEnter
GLOBAL VARIABLES
$medkitsNumberstarts at 3
$highScoreNumberstarts at 0
GAME SETTINGS > General > Game State
Available Game StatesPlaying, Mission Failed
SCENE Gameplay: PLACE THESE
ObjectXY
Medkit Icon-31684
Medkit Icon-28484
with Per Instance Variables > Level = 2
Medkit Icon-25284
with Per Instance Variables > Level = 3
Medkit Icon-22084
with Per Instance Variables > Level = 4
Medkit Icon-18884
with Per Instance Variables > Level = 5
Medkit Label-260116
with Z-Index = 120
Result Veil00hidden
with Per Instance Variables > Opacity = 0.6
Game Over Banner0120hidden
Final Score0-20hidden
with Z-Index = 142
Result High Score0-75hidden
with Z-Index = 142
Fly Again Key-154-172hidden
Fly Again Prompt-60-172hidden
with Z-Index = 142
High Score Label0-76
with Z-Index = 120
High Score Text0-104
with Z-Index = 120
REMOVED
Function: Show Pip For Gun Level

Confirm 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.

Logic ComponentMission StartAttach to: Game Rules

Sets up a fresh mission each time the Gameplay Scene starts: Playing, score 0, startMedkits medkits, gun level startGunLevel.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
startMedkitsNumberConstant3
startGunLevelNumberConstant1
When the Scene Starts
WhenScene Start
1Set Game State
Game State
Playing
2Change Variable
Variable
$score
Value
0
3Change Variable
Variable
$medkits
Value
@self.startMedkits
4Change Variable
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.

Logic ComponentMission MusicAttach to: Game Rules

Plays the Battle Theme and the engine drone during the mission, and the Game Over Jingle when it fails.

Attach toAny Object
When the Scene Starts
WhenScene Start
1Control Sound
Operation
Loop
Sound
"Battle Theme"
2Control Sound
Operation
Loop
Sound
"Engine Drone"
On Game State Changed
WhenGame State Changed
1Check Game State
Action Name
missionFailed
Game State
Mission Failed
2IfmissionFailed.value == true
Then
3Control Sound
Operation
Stop
Sound
"Battle Theme"
4Control Sound
Operation
Stop
Sound
"Engine Drone"
5Control Sound
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.

ObjectEnemy Round
Transform
Bounding Box > SizeX 3, Y 3
Sprite
Scene Depth Draw Order45
SpriteEnemy Round Art
Transform > SizeX 3, Y 3
Collider
CollisionSensor
Shape and Transform > SizeX 0.313, Y 0.313
Tags and Interactions > InteractionsCollide Only With
Tags and Interactions > Collide Only WithFighter
Tags
Object TagsEnemy Fire
Logic
Remove When Out of View
Breaks on Fighter

4.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.

Logic ComponentBreaks on FighterAttach to: Enemy Round

An enemy round that hits the Fighter breaks with a small spark.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
hitSparksCountNumberConstant6
When Starting to Hit Fighter
WhenCollision EnterObject: Fighter
1Burst Particles
Particles
"Hit Sparks"
Count
@self.hitSparksCount
Z Index Offset
2
2Destroy Instance

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.

ObjectFighterAddDelete
Transform
Bounding Box > SizeX 3, Y 3
Physics > Physics ObjectOff
Sprite
Scene Depth Draw Order30
SpriteFighter Art
Transform > SizeX 3, Y 3
Collider
Shape and Transform > PositionX 0, Y -0.094
Shape and Transform > SizeX 0.656, Y 0.75
Tags and Interactions > InteractionsCollide Only With
Tags and Interactions > Collide Only WithTagged Enemy Aircraft, Tagged Enemy Fire
Tags and Interactions > Collide Only WithTagged Enemy Aircraft
Logic
Top-down Controls
Keep Inside Box
Fighter Guns
Hurt by Enemies
Protection Blink
Lost With the Last Medkit
Shared Variables
moveSpeed10.313
minimumX1.313
maximumX21.188
minimumY7.188
maximumY30
roundMG Round

Next, 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.

Particle EffectEnemy Muzzle Flash
Emitter
Emission > Emit Every (ms)0
Emission > Burst Count5
Emitter Shape > Emit Shapepoint
Motion
Lifecycle > Each Particle Lives (ms)min 60, max 140
Motion > Speed (m/s)min 0.938, max 3.125
Motion > Angle (Deg)min -110, max -70
Appearance
Appearance > Particle SpriteFX Spark
Appearance > Color SourceMultiple Colors
Appearance > Multiple Colors#FFF0D0, #FF9A3C, #FF5A1F
Appearance > Glow1.2
Appearance Over Life > Scalestart 0.6, end 0
Appearance Over Life > Starting RotationRandom Spin On

4.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.

FunctionWait for the Firing Band

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.

PARAMETERS
NameTypeStarts at
CallerObject
bandTopNumber32.813
speedNumber5.938
delayNumber0
RETURN TYPENumber
ACTIONS
1Declare Variable
Name
wait
Value
0
2Declare Variable
Name
secondsToBand
Value
0
3Change Variable
Variable
wait
Value
delay
4Change Variable
Variable
secondsToBand
Value
(Caller.transform.position.y - bandTop) / speed
5IfsecondsToBand > wait
Then
6Change Variable
Variable
wait
Value
secondsToBand
7Return
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.

FunctionAim Down at the Fighter

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.

PARAMETERS
NameTypeStarts at
CallerObject
fighterObjectStructural
Required Components
Slot Nametransform
Component TypeTransform
aimMinNumber200
aimMaxNumber340
RETURN TYPENumber
ACTIONS
1Declare Variable
Name
across
Value
0
2Declare Variable
Name
up
Value
0
3Declare Variable
Name
aim
Value
0
4Iffighter.transform.position.y < Caller.transform.position.y
Then
5Change Variable
Variable
across
Value
fighter.transform.position.x - Caller.transform.position.x
6Change Variable
Variable
up
Value
fighter.transform.position.y - Caller.transform.position.y
7Change Variable
Variable
aim
Value
radtodeg(atan2(up, across)) + 360
8Ifaim < aimMin
Then
9Change Variable
Variable
aim
Value
aimMin
10Ifaim > aimMax
Then
11Change Variable
Variable
aim
Value
aimMax
12Otherwise
13Change Variable
Variable
aim
Value
270
14Return
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.

Logic ComponentZero Fighter GunsAttach to: Zero Fighter

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.

Attach toAny Object
DATA STRUCTURES
Enemy Statsself.enemyStats
SHARED VARIABLES
NameTypeKindStarting Value
roundObjectConstantNone
fighterObjectConstantNone
aimedChanceNumberConstant50
firstShotMinNumberConstant0.4
firstShotMaxNumberConstant1.1
shotGapMinNumberConstant1.7
shotGapMaxNumberConstant2.5
straightSpeedNumberConstant7.031
aimedSpeedNumberConstant6.719
aimMinNumberConstant200
aimMaxNumberConstant340
muzzleYNumberConstant-1.219
bandBottomNumberConstant10
bandTopNumberConstant32.813
enemyMuzzleFlashCountNumberConstant5
When Created
WhenCreate
ModeChoose a Pilot (Combined, On at start)
1Generate Random Integer
Action Name
pilotRoll
Maximum
99
2IfpilotRoll.value < @self.aimedChance
Then
3Turn Off Mode
Event
On the Enemy Fire Timer
Mode
Shoot Straight
4Turn On Mode
Event
On the Enemy Fire Timer
Mode
Shoot Aimed
When Created
WhenCreate
ModeWait for the Firing Band (Combined, On at start)
1Generate Random Number
Action Name
firstShot
Minimum
@self.firstShotMin
Maximum
@self.firstShotMax
2Wait for the Firing BandFunction
Action Name
firstShotWait
caller
self
bandTop
@self.bandTop
speed
self.enemyStats.speed
delay
firstShot.value
3Start Recurring Timer
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.

Logic ComponentZero Fighter Gunscontinued
On the Enemy Fire Timer
WhenRecurring TimerTimer name: enemyFire
ModeStill Firing? (Combined, On at start)
1Check Game State
Action Name
stillPlaying
Game State
Playing
2IfstillPlaying.value == false || self.transform.position.y <= @self.bandBottom
Then
3Return
On the Enemy Fire Timer
WhenRecurring TimerTimer name: enemyFire
ModeShoot Straight (Combined, On at start)
1Create Instance
Object to Create
@self.round
Position Relative To
Self
Y
@self.muzzleY
2Set Direction
Applies To
created
Direction
270
3Set Speed
Applies To
created
Speed
@self.straightSpeed
On the Enemy Fire Timer
WhenRecurring TimerTimer name: enemyFire
ModeShoot Aimed (Combined)
1Aim Down at the FighterFunction
Action Name
fighterAim
caller
self
fighter
@self.fighter
aimMin
@self.aimMin
aimMax
@self.aimMax
2Create Instance
Object to Create
@self.round
Position Relative To
Self
Y
@self.muzzleY
Created As
created2
3Set Direction
Applies To
created2
Direction
fighterAim.value
4Set Speed
Applies To
created2
Speed
@self.aimedSpeed
On the Enemy Fire Timer
WhenRecurring TimerTimer name: enemyFire
ModeAfter the Shot (Combined, On at start)
1Burst Particles
Particles
"Enemy Muzzle Flash"
Y
@self.muzzleY
Count
@self.enemyMuzzleFlashCount
Z Index Offset
2
2Control Sound
Sound
"Enemy Guns"
3Generate Random Number
Action Name
nextShot
Minimum
@self.shotGapMin
Maximum
@self.shotGapMax
4Start Recurring Timer
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.

ObjectZero FighterAddDelete
Transform
Bounding Box > SizeX 3, Y 3
Physics > Physics ObjectOff
Sprite
Scene Depth Draw Order20
SpriteZero Fighter Art
Transform > SizeX 3, Y 3
Collider
Shape and Transform > SizeX 1.5, Y 1.125
Tags and Interactions > InteractionsCollide Only With
Tags and Interactions > Collide Only WithFighter, Tagged Fighter Round
Data Structure
Data StructureEnemy Stats
Input SourceData Table
Data TableEnemy Types
Tags
Object TagsEnemy Aircraft
Logic
Zero Fighter Guns
Fly Down
Takes Hits
Meter with Thresholds
Shot Down
Remove When Out of View
Shared Variables
maximum > KindExpression
maximum > ExpressionobjectComponentProperty("self","dataStruct","health")
threshold > KindExpression
threshold > ExpressionobjectComponentProperty("self","dataStruct","health")
roundEnemy Round
fighterFighter

Run 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.

FunctionStart Protection

Protects the caller for some seconds: starts its protection cooldown and its blinking.

PARAMETERS
NameTypeStarts at
CallerObject
secondsNumber2
ACTIONS
1Start Cooldown
Applies To
Caller
Cooldown Key
"protection"
Seconds
seconds
2Trigger Custom Event on Object
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.

FunctionHurt the Fighter

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).

PARAMETERS
NameTypeStarts at
CallerObject
protectSecondsNumber2.4
SectionEffects
planeExplosionCountNumber30
shakeStrengthNumber0.02
shakeSecondsNumber0.4
flashSecondsNumber0.18
ACTIONS
1Check Cooldown Ready
Action Name
canBeHurt
Applies To
Caller
Cooldown Key
"protection"
2IfcanBeHurt.value == true
Then
3Start ProtectionFunction
caller
Caller
seconds
protectSeconds
4Burst Particles
Applies To
Caller
Particles
"Plane Explosion"
Count
planeExplosionCount
Z Index Offset
2
5Control Sound
Applies To
Caller
Sound
"Fighter Hit"
6Camera Shake
Applies To
Caller
Intensity
shakeStrength
Seconds
shakeSeconds
7Camera Flash
Applies To
Caller
Color
"#ff5a3c"
Seconds
flashSeconds
8Trigger Custom Event
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.

Logic ComponentHurt by EnemiesAttach to: Fighter

An enemy round or an enemy plane that touches the Fighter hurts it (Hurt the Fighter); it starts every mission protected.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
startProtectSecondsNumberConstant2
When Created
WhenCreate
1Start ProtectionFunction
caller
self
seconds
@self.startProtectSeconds
When Starting to Hit Anything Tagged Enemy Fire
WhenCollision EnterObject: tag:Enemy Fire
1Hurt the FighterFunction
caller
self
When Starting to Hit Anything Tagged Enemy Aircraft
WhenCollision EnterObject: tag:Enemy Aircraft
1Hurt the FighterFunction
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.

Logic ComponentLose a MedkitAttach to: Game Rules

Each hit on the Fighter costs one medkit.

Attach toAny Object
On Fighter Hit
WhenfighterHitCustom Event
1Change Variable
Variable
$medkits
Operator
-=
Value
1
2If$medkits <= 0
Then
3Set Game State
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.

Logic ComponentLose a Gun LevelAttach to: Game Rules

Each hit on the Fighter costs one gun level, but the gun level never goes below 1.

Attach toAny Object
On Fighter Hit
WhenfighterHitCustom Event
1If$gunLevel > 1
Then
2Change Variable
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.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.

ObjectMedkit Icon
Transform
Presentation > SpaceWindow / UI
Presentation > Screen AnchorBottom Center
Presentation > Render LayerUI
Bounding Box > SizeX 128, Y 128
Sprite
Scene Depth Draw Order102
SpriteMedkit Icon
Transform > SizeX 32, Y 32
Logic
Show Medkits
ObjectMedkit Label
Transform
Presentation > SpaceWindow / UI
Presentation > Screen AnchorBottom Center
Presentation > Render LayerUI
Bounding Box > SizeX 128, Y 48
Text / UI
TextMEDKITS
FontBebas Neue
Font Size18
Color#FF8A80
Letter Spacing1
Text BoundsWrap to Width
Transform > Size X180

4.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.

FunctionShow If At Least

Shows the caller while a value is at least the given level, and hides it otherwise.

PARAMETERS
NameTypeStarts at
CallerObject
valueNumber0
levelNumber1
ACTIONS
1Ifvalue >= level
Then
2Set Visible
Applies To
Caller
Visible
true
3Otherwise
4Set Visible
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.

Logic ComponentShow MedkitsAttach to: Medkit Icon

Shows this medkit icon while the Fighter has at least its number of medkits (1 to 5).

Attach toAny Object
PER INSTANCE VARIABLES
NameTypeStarting Value
levelNumber1
When Created
WhenCreate
1Show If At LeastFunction
caller
self
value
$medkits
level
self.level
On Variable Changed · Medkits
WhenVariable ChangedGlobal Variable: medkits
1Show If At LeastFunction
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.

Logic ComponentShow Gun LevelAttach to: Power PipAddDelete

Shows this power pip while the gun level is at least its level (1 to 4).

Attach toAny Object
PER INSTANCE VARIABLES
NameTypeStarting Value
levelNumber1
When Created
WhenCreate
1Show Pip For Gun LevelFunction
caller
self
level
self.level
1Show If At LeastFunction
caller
self
level
self.level
value
$gunLevel
On Variable Changed · Gun Level
WhenVariable ChangedGlobal Variable: gunLevel
1Show Pip For Gun LevelFunction
caller
self
level
self.level
1Show If At LeastFunction
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.

Particle EffectBig Explosion
Emitter
Emission > Emit Every (ms)0
Emission > Burst Count110
Emitter Shape > Emit Radius (m)1.25
Motion
Lifecycle > Each Particle Lives (ms)min 400, max 1400
Motion > Speed (m/s)min 2.5, max 14.375
Appearance
Appearance > Particle SpriteFX Smoke Puff
Appearance > Color SourceMultiple Colors
Appearance > Multiple Colors#FFFFFF, #FFF1B8, #FFB347, #FF6A3C, #6B2B2B
Appearance > Glow1.8
Appearance Over Life > Scalestart 2.4, end 0
Appearance Over Life > Size Variation (0–1)0.7
Appearance Over Life > Starting RotationRandom Spin On

4.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.

Logic ComponentLost With the Last MedkitAttach to: Fighter

When the mission fails, the Fighter explodes and is removed.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
bigExplosionCountNumberConstant110
smokePuffCountNumberConstant20
shakeStrengthNumberConstant0.035
shakeSecondsNumberConstant0.8
On Game State Changed
WhenGame State Changed
1Check Game State
Action Name
missionFailed
Game State
Mission Failed
2IfmissionFailed.value == true
Then
3Burst Particles
Particles
"Big Explosion"
Count
@self.bigExplosionCount
Z Index Offset
2
4Burst Particles
Particles
"Smoke Puff"
Count
@self.smokePuffCount
Z Index Offset
2
5Control Sound
Sound
"Explosion Large"
6Camera Shake
Intensity
@self.shakeStrength
Seconds
@self.shakeSeconds
7Destroy Instance

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.

Logic ComponentAdd PointsAttach to: Game RulesAddDelete

Adds the points of every enemy shot down to the score, while the mission is being played.

Attach toAny Object
On Enemy Shot Down
WhenenemyShotDownCustom Event
1Change Variable
Variable
$score
Operator
+=
Value
event("points")
1Check Game State
Action Name
stillPlaying
Game State
Playing
2IfstillPlaying.value == true
Then
3Change Variable
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.

Logic ComponentHigh ScoreAttach to: Game Rules

Reads the high score from this device when a mission starts, and saves a better score when the mission ends.

Attach toAny Object
When the Scene Starts
WhenScene Start
1Load Persistent Value
Action Name
savedHighScore
Key
"highScore"
Default
0
2Change Variable
Variable
$highScore
Value
savedHighScore.value
On Game State Changed
WhenGame State Changed
1Check Game State
Action Name
missionFailed
Game State
Mission Failed
2IfmissionFailed.value == true
Then
3If$score > $highScore
Then
4Change Variable
Variable
$highScore
Value
$score
5Save Persistent Value
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.

ObjectHigh Score Label
Transform
Presentation > SpaceWindow / UI
Presentation > Screen AnchorTop Center
Presentation > Render LayerUI
Bounding Box > SizeX 128, Y 48
Text / UI
TextHIGH SCORE
FontBebas Neue
Font Size20
Color#F4C542
Letter Spacing1
AlignmentCenter
Text BoundsWrap to Width
Transform > Size X200
ObjectHigh Score Text
Transform
Presentation > SpaceWindow / UI
Presentation > Screen AnchorTop Center
Presentation > Render LayerUI
Bounding Box > SizeX 128, Y 48
Text / UI
Text{$highScore}
FontBebas Neue
Font Size32
Letter Spacing1
AlignmentCenter
Text BoundsWrap to Width
Transform > Size X240

Place 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.

ObjectResult Veil
Transform
Presentation > SpaceWindow / UI
Presentation > Screen AnchorCenter
Presentation > Render LayerUI
Bounding Box > SizeX 128, Y 128
Sprite
Scene Depth Draw Order140
SpriteWhite Pixel
Transform > SizeX 720, Y 960
Tint (on its placement)#020B14
Logic
Show With Results
ObjectGame Over Banner
Transform
Presentation > SpaceWindow / UI
Presentation > Screen AnchorCenter
Presentation > Render LayerUI
Bounding Box > SizeX 128, Y 128
Sprite
Scene Depth Draw Order141
SpriteGame Over Banner Art
Transform > SizeX 640, Y 170
Logic
Show With Results
ObjectFinal Score
Transform
Presentation > SpaceWindow / UI
Presentation > Screen AnchorCenter
Presentation > Render LayerUI
Bounding Box > SizeX 128, Y 48
Text / UI
TextFINAL SCORE {$score}
FontBebas Neue
Font Size48
Letter Spacing1
AlignmentCenter
Text BoundsWrap to Width
Transform > Size X600
Logic
Show With Results
ObjectResult High Score
Transform
Presentation > SpaceWindow / UI
Presentation > Screen AnchorCenter
Presentation > Render LayerUI
Bounding Box > SizeX 128, Y 48
Text / UI
TextHIGH SCORE {$highScore}
FontBebas Neue
Font Size30
Color#F4C542
Letter Spacing1
AlignmentCenter
Text BoundsWrap to Width
Transform > Size X600
Logic
Show With Results
ObjectFly Again Key
Transform
Presentation > SpaceWindow / UI
Presentation > Screen AnchorCenter
Presentation > Render LayerUI
Bounding Box > SizeX 128, Y 128
Sprite
Scene Depth Draw Order142
SpriteKey Enter Icon
Transform > SizeX 72, Y 36
Logic
Show With Results
ObjectFly Again Prompt
Transform
Presentation > SpaceWindow / UI
Presentation > Screen AnchorCenter
Presentation > Render LayerUI
Bounding Box > SizeX 128, Y 48
Text / UI
TextFLY AGAIN
FontBebas Neue
Font Size28
Color#BCD7E8
Letter Spacing1
AlignmentCenter
Text BoundsWrap to Width
Transform > Size X106
Logic
Show With Results

4.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.

Logic ComponentShow With ResultsAttach to: Result Veil, Game Over Banner, Final Score, Result High Score, Fly Again Key, Fly Again Prompt

Shows this result screen piece when Game Rules sends showResults, if the Game State is the piece's own.

Attach toAny Object
PER INSTANCE VARIABLES
NameTypeStarting Value
stateTextmission-failed
opacityNumber1
On Show Results
WhenshowResultsCustom Event
1Check Game State
Action Name
stateMatches
Game State
self.state
2IfstateMatches.value == true
Then
3Set Alpha
Alpha
self.opacity
4Set Visible
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.

FunctionStart a New Mission

Starts a new mission: plays Menu Select and restarts the Gameplay Scene.

PARAMETERS
CallerObject
ACTIONS
1Control Sound
Applies To
Caller
Sound
"Menu Select"
2Restart Scene
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.

Logic ComponentFly AgainAttach to: Game Rules

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).

Attach toAny Object
When Confirm Is Pressed
WhenCommand PressedCommand: Confirm
1Start a New MissionFunction
caller
self
When Fire Is Pressed
WhenCommand PressedCommand: Fire
1Start a New MissionFunction
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.

Logic ComponentMission FailedAttach to: Game Rules

When the mission fails, resultSeconds later it shows the result screen and switches FLY AGAIN on.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
resultSecondsNumberConstant2.4
On Game State Changed
WhenGame State Changed
1Check Game State
Action Name
missionFailed
Game State
Mission Failed
2IfmissionFailed.value == true
Then
3Start Recurring Timer
Timer Name
resultScreen
First Delay (s)
@self.resultSeconds
Ring Once
Yes
On the Result Screen Timer
WhenRecurring TimerTimer name: resultScreen
1Trigger Custom Event
Custom Event
showResults
2Set Logic State
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.

ObjectGame RulesAddDelete
Transform
Bounding Box > SizeX 3, Y 3
Data Structure
From LogicRun Mission Timeline
Data StructureRun Mission Timeline Data
Logic
Add Points
Run Mission Timeline
Lose a Medkit
Lose a Gun Level
Mission Start
High Score
Mission Music
Mission Failed
Fly Again(turned off)

Now 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.

Play it!

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.
How it works

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.

Challenge

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.