Build a GameCreating Sky Ace

3  Enemy Fighters

Goal

Five Zero Fighters come down the sea in a V. Fly under one and fire. It flashes white, and the second hit sends it up in a burst of fire and smoke, while the score at the top of the window climbs. By the end of this chapter, your Fighter has something to shoot at.

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.

If your game and this chapter part ways, here is the chapter’s finished project. Open it and compare, or start Chapter 4 from it.

Sky Ace, Chapter 3 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.

3.1 The Idea

The Fighter flies, and its guns fire, but the sea below it is empty. Not for long.

Three seconds into the mission, five planes slide out from under the top of the window. They’re pale gray-green, and they come down side by side in a V that points at you, the middle plane lowest. Fly under one and hold Space. The first hit flashes it white for a blink. The second throws out a burst of fire and a puff of gray smoke, with a bang, and the plane is gone. At the top of the window, under SCORE, the 0 turns to 100.

The planes you miss fly on past the Fighter and out at the bottom. They don’t shoot back. Not yet.

The Zero Fighter is the first of four kinds of enemy plane in Sky Ace. They’ll all fly down, take hits and go down in the same way. In Chapter 7, the other three add their own moves on top: a weave, a dive, more guns. So this chapter builds that shared part as Logic Components any plane can carry. And every enemy plane will wear a Tag, Enemy Aircraft. A Tag is a word stuck on an Object, like a label on a jar. A round never asks which kind of plane it touched. It looks for the label.

What makes a Zero Fighter itself is three numbers: how fast it flies, how many hits it takes, and how many points it’s worth. They live in a Data Table, one row per kind of plane. And each plane carries a Data Structure, a small form of named fields, and fills it from the row that has its name.

A hit takes more than one piece of Logic. The round notices the touch. The plane flashes and counts the hit. When the count reaches the plane’s health, it goes down, and the score goes up. Each piece does its one job and then tells the next piece, with a message, a Custom Event sent by name. It works like a relay race. Each runner carries the news one stretch and hands it on.

The hits are counted on a meter, a number that runs from 0 up to the plane’s health. Myth Engine comes with a Logic Component that keeps one, and this chapter uses it.

And something has to send the planes. That’s Game Rules, an Object with no picture that runs the mission, and it reads the Mission Timeline, a table of what arrives when. Today it has one row: the first V, three seconds in.

3.2 The Plan

Here’s how the pieces work together. Read each line from left to right.

  • Three seconds in -> Run Mission Timeline’s timer rings -> Spawn V Formation makes five Zero Fighters in a V, above the window.
  • A Zero Fighter appears -> Fly Down sends it down the screen.
  • A round touches anything Tagged Enemy Aircraft -> Breaks on Hit sends roundHit to that plane, throws a few sparks and breaks.
  • The roundHit message arrives -> Takes Hits flashes the plane white and sends changeMeter -> Meter with Thresholds counts one hit.
  • The hits reach the plane’s health -> Shot Down sends enemyShotDown and explodes.
  • The enemyShotDown message arrives -> Add Points adds that plane’s points to $score -> the Score Text shows the new score.
  • A plane leaves the window -> Remove When Out of View removes it.

3.3 Set Up

This chapter adds the score, one shared number, and four placements. The Zero Fighter’s picture, the smoke puff’s, the top bar’s and the explosion sound came with the Starter Kit.

Set upWhat this chapter adds
ART (sprites, from the starter kit)
Zero Fighter Art
FX Smoke Puff
HUD Top Bar Art
SOUNDS (from the starter kit)
Explosion Small
GLOBAL VARIABLES
$scoreNumberstarts at 0
SCENE Gameplay: PLACE THESE
ObjectXY
Game Rules11.2518.75
HUD Top Bar0-92
Score Label-250-76
with Z-Index = 120
Score Text-250-104
with Z-Index = 120

The score waits for Add Points, in the last part. You’ll make it there, with the + on the Globals card of its canvas, the way you made the gun level in Chapter 2. PLACE THESE comes as each Object is made. Game Rules goes in during The first V, and the three on the screen in The score.

3.4 Two Tags

First, the planes, and the rounds that will hit them.

Make Enemy Stats first. It’s the Data Structure every enemy carries, with three fields: speed, health and points. Make it with Add > Data Structure, and give it the card’s name. It starts with no fields at all. Press Add Field for each line. A Data Structure card uses this very card as its example.

Data StructureEnemy Stats

What every enemy carries; each enemy takes the values from its own row of Enemy Types.

speedNumberdefault 0
healthNumberdefault 1
pointsNumberdefault 0

Then the table it fills from. Enemy Types has the same three columns, because its rows are Enemy Stats. Make the table. Then pick Enemy Stats in its Entry Type list, at its top left. The table also made a Data Structure of its own, Enemy Types Entry. Nothing uses it, so delete it from the Resources. A Data Table card has this too.

The row’s name goes in the grid’s Entry column: Zero Fighter, spelled exactly as the Object will be. That’s how a plane finds its row. A Zero Fighter flies a little under six meters a second, two hits shoot it down, and it’s worth 100 points.

Data TableEnemy TypesData Structure: Enemy Stats
Row 0Zero Fighter
speed5.9375
health2
points100

Now the Zero Fighter. It’s a pale gray-green plane, three meters across like the Fighter. Make it as a 2D Object, and turn its Physics Object switch off, as you did for the Fighter. Its Collider is a box a meter and a half wide, around the wings and the body. Its Scene Depth Draw Order is 20, below the Fighter’s 30, so the Fighter flies over it.

The Data Structure is where the plane meets its row. Attach one from Data, and pick Enemy Stats. Its Input Source, Data Table, and its Data Table, Enemy Types, mean: fill the fields from the row with this plane’s own name.

Then its Tag. Attach Tags, also from Data. The Tag to Add list is empty the first time, apart from Create New Tag…. Create Enemy Aircraft there, and add it. An Object card and its components has the steps, and more on each field.

The rest of the card waits. Five Logic Components are listed under Logic, and each comes in its own part of this chapter. Its Shared Variables come with one of them. Leave the Collider’s list for a moment too, because it names a Tag that no round wears yet.

ObjectZero Fighter
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
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")

MG Round gets a Tag of its own, Fighter Round. In Chapter 8 the Fighter gets two more kinds of round, and they’ll wear it too. Attach Tags to MG Round, and create Fighter Round the same way.

Now its Collider learns what it may hit. Under Tags and Interactions, pick Collide Only With in Interactions, then press Search to add… and pick Tagged Enemy Aircraft. Breaks on Hit comes later.

ObjectMG RoundAddDelete
Transform
Bounding Box > SizeX 3, Y 3
Sprite
Scene Depth Draw Order35
SpriteMG Round Art
Transform > SizeX 3, Y 3
Collider
CollisionSensor
Shape and Transform > SizeX 0.25, Y 0.75
Tags and Interactions > InteractionsCollide Only With
Tags and Interactions > Collide Only WithTagged Enemy Aircraft
Tags
Object TagsFighter Round
Logic
Remove When Out of View
Breaks on Hit

Back on the Zero Fighter, its Collider gets its list now. Pick Collide Only With, as on MG Round, and add the Fighter and Tagged Fighter Round. Every round counts, because every round wears that Tag.

The Fighter needs one line too. Add Tagged Enemy Aircraft to its Collide Only With list, so that in Chapter 4 the planes can reach it.

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
Logic
Top-down Controls
Keep Inside Box
Fighter Guns
Shared Variables
moveSpeed10.313
minimumX1.313
maximumX21.188
minimumY7.188
maximumY30
roundMG Round

You won’t see a Zero Fighter yet, because nothing sends one and nothing moves one. The next part does both.

But MG Round has a new list, so check that your guns still work. Save your project with Ctrl+S, and run the game. Hold Space. The gold rounds climb the window as they did in Chapter 2. Nothing broke. With the game in front, Alt+F4 brings you back.

3.5 The First V

Now the planes arrive.

The mission’s schedule is a Data Table, the Mission Timeline. Each row is something that arrives, and when. Its columns are the mission time in seconds, the formation, which Object arrives, and where: the formation’s middle, how many planes, and how far apart. Today the table has one row, Wave 1 V. It brings five Zero Fighters in a V at the middle of the window, 2.25 meters apart, three seconds in.

Its rows are made like Mission Timeline Entry, the Data Structure the table makes for itself, as Gun Patterns Entry was in Chapter 2. Its card comes first. Give its fields their defaults, and the row needs only its name and its time. The object field’s Type is Object, the one up among the plain values, and its Value is a button. Press it and pick Zero Fighter. In the row, that cell is a button too, so you pick there as well. By Chapter 6, this table holds the whole mission.

Data StructureMission Timeline Entry

One row of the "Mission Timeline" Data Table.

timeSecondsNumberdefault 0
formationTextdefault V
objectThing Objectdefault Zero Fighter
xNumberdefault 11.25
countNumberdefault 5
spacingNumberdefault 2.25
Data TableMission TimelineData Structure: Mission Timeline Entry
Row 0Wave 1 V
timeSeconds3
formationV
objectZero Fighter
x11.25
count5
spacing2.25

3.5.1 Fly Down

A Zero Fighter appears above the window, turns its nose down the screen and goes. It never steers. It flies straight down at its own speed until it leaves the window at the bottom.

Fly Down is the whole of that. Its one Event, When Created, runs once, as the plane appears. Set Direction points it at 270 degrees, straight down. Set Speed sends it off at self.enemyStats.speed, the speed field of the plane’s own Enemy Stats.

That name, self.enemyStats.speed, has three parts. Its first part, self, is the plane. Its middle part, enemyStats, is the plane’s Enemy Stats, by the name Fly Down gives it. And its last part, speed, is the field.

So Fly Down needs Enemy Stats first. Press the + on its canvas’s Data Structures card, and pick Enemy Stats under Existing Data Structures. Myth names it enemyStats, and the card’s DATA STRUCTURES row shows that name. A Logic Component card shows this too.

Logic ComponentFly DownAttach to: Zero Fighter

Flies straight down the screen at the speed in its Enemy Stats.

Attach toAny Object
DATA STRUCTURES
Enemy Statsself.enemyStats
When Created
WhenCreate
1Set Direction
Direction
270
2Set Speed
Speed
self.enemyStats.speed

Attach Fly Down to the Zero Fighter. Its Enemy Stats is there already, so nothing is added twice. Then attach Remove When Out of View too, so a plane that leaves the window is removed for good, like a round.

The Attached Logic lists Logic Components in the order you attach them. By the end of this chapter, yours may not match the card’s order, and that’s all right. No two of them answer the same Event, so their order changes nothing. The same goes for Game Rules.

3.5.2 Spawn V Formation

Spawn V Formation makes one V. It makes the planes one at a time, from left to right, and each one goes a little farther right than the one before, by spacing. The farther a plane is from the middle, the higher it sits. So the middle plane is lowest. The V points down at the Fighter.

All of it happens above the top of the window, at entryY. The planes slide into view only as they fly down.

So the Function is a Repeat with one Create Instance in it, count times. If, Else, Repeat and While shows how to make a Repeat and put a block inside it. Its X and Y look long, but they’re both about one small number: how far this plane is from the middle of the V.

Here’s where that number comes from. Inside a Repeat, local.index says which pass through the Repeat this is, counting from 0. For five planes, that’s 0 to 4. Take away (count - 1) / 2, which is 2 here. Now they’re two to the left, one to the left, the middle, one to the right and two to the right. The X multiplies that by spacing. The Y takes it without its sign, which is what abs does, and multiplies it by rowStep.

Make its PARAMETERS first, on its Start block. Caller comes first, made as in Chapter 2. The planes come from Caller, which is Game Rules, so Create Instance’s Applies To is Caller.

Which plane to make is a Parameter too, enemy. On the card it’s a Thing Object. It holds a kind of Object, such as Zero Fighter, and not one in the game. That’s the Object up among the plain values in the Type list, which Chapter 2 pointed out. Type enemy in its Name box. Its Default stays at None.

To make Create Instance use it, open its Object to Create list. It holds Caller, and at its bottom, From a Value (Variable, Data Table, Expression). Pick that one, and the list turns into a box. Click the box and type enemy. Applies To has picked Caller by itself, the first Object Parameter. Actions, one at a time has this too.

FunctionSpawn V Formation

Creates a V of enemies above the top edge, centered on x, with its middle plane lowest.

PARAMETERS
NameTypeStarts at
CallerObject
enemyThing Object
xNumber11.25
countNumber5
spacingNumber2.25
entryYNumber35.938
rowStepNumber1.719
ACTIONS
1Repeatcounttimes
Each time
2Create Instance
Applies To
Caller
Object to Create
enemy
X
x + (local.index - (count - 1) / 2) * spacing
Y
entryY + abs(local.index - (count - 1) / 2) * rowStep

Why does the Function take its plane from a Parameter, when it could name the Zero Fighter itself? Because it doesn’t care which plane it makes. In Chapter 6, three more formations join it, each a Function like this one. In Chapter 7, the table sends other kinds of plane through them.

3.5.3 Run Mission Timeline

Run Mission Timeline doesn’t watch the clock. It sets an alarm for the first row’s time and waits. When the alarm rings, that row arrives. Then it sets the alarm again, for the gap until the next row.

The alarm is a timer that rings once. When Created starts it, named timeline, with First Delay read from the table: row nextRow, column timeSeconds. And nextRow starts at 0, the first row, so the alarm rings three seconds in.

When it rings, the second Event runs. Its If reads the row’s formation. Is it V? Then it calls Spawn V Formation, with that row’s object, x, count and spacing. Next, nextRow goes up by one.

The last four Actions set the alarm again, if a row is left. They work out the gap between this row’s time and the next row’s, and the timer waits that long. Today the table has one row, so they wait. They’re four short blocks, and they’re what lets the table grow. Give it a second row, as the Challenge invites you to, and that row arrives on time.

Its four numbers last from one Event to the next, so they live in a Data Structure of its own, Run Mission Timeline Data. Make it first. Press the + on the canvas’s Data Structures card, and choose New Data Structure. Myth makes it, names it after the Logic, and opens it in a tab of its own. Add the card’s four fields there, each a Number starting at 0. Back in the Logic’s tab, the card’s row reads Run Mission Timeline Data self.runMissionTimelineData.

Data StructureRun Mission Timeline Data

Object Data of Logic "Run Mission Timeline" (its state that lasts between Events).

nextRowNumberdefault 0
gapSecondsNumberdefault 0
lastRowTimeNumberdefault 0
nextRowTimeNumberdefault 0

So its blocks reach a field as self.runMissionTimelineData.nextRow: Game Rules’ own copy of that Data Structure, then the field. Here self is Game Rules, the Object this Logic runs on.

Change Component Value changes one of those fields. Type the card’s path into its Component Value box, and its Operator and Value appear after it. The Operator is a list, and the card’s += reads Plus there. A step with no Operator line keeps =.

The rest goes by the card. Type timeline into the Timer Name bare, as the card gives it, and pick Yes in Ring Once. The If’s condition is one box. Type it whole, with “V” in its quotes.

The call to Spawn V Formation goes on the If’s True line. Right-click the If, choose Add inside Then, and pick Spawn V Formation under Functions. Join it with Connect to sequence. Its fields have the names you gave its Parameters. Caller is a list, and it starts on self, as the card has it. The rest are boxes, so type the card’s values over what they hold. Entry Y and Row Step aren’t on the card. Leave them.

Step 3 comes after the If, back on the main line, so the card gives it no indent. Add it from the Action List, and join it with Connect to sequence. It goes under the If, not inside it. The second If, step 4, goes on the main line the same way, and its four Actions fill its True line.

Logic ComponentRun Mission TimelineAttach to: Game Rules

Runs the Mission Timeline: each row's formation arrives at its mission time, in order.

Attach toAny Object
DATA STRUCTURES
Run Mission Timeline Dataself.runMissionTimelineData
When Created
WhenCreate
1Start Recurring Timer
Timer Name
timeline
First Delay (s)
data("Mission Timeline", self.runMissionTimelineData.nextRow, "timeSeconds")
Ring Once
Yes
On the Timeline Timer
WhenRecurring TimerTimer name: timeline
1Ifdata("Mission Timeline", self.runMissionTimelineData.nextRow, "formation") == "V"
Then
2Spawn V FormationFunction
caller
self
enemy
data("Mission Timeline", self.runMissionTimelineData.nextRow, "object")
x
data("Mission Timeline", self.runMissionTimelineData.nextRow, "x")
count
data("Mission Timeline", self.runMissionTimelineData.nextRow, "count")
spacing
data("Mission Timeline", self.runMissionTimelineData.nextRow, "spacing")
3Change Component Value
Component Value
self.runMissionTimelineData.nextRow
Operator
+=
Value
1
4Ifself.runMissionTimelineData.nextRow < dataCount("Mission Timeline")
Then
5Change Component Value
Component Value
self.runMissionTimelineData.lastRowTime
Value
data("Mission Timeline", self.runMissionTimelineData.nextRow - 1, "timeSeconds")
6Change Component Value
Component Value
self.runMissionTimelineData.nextRowTime
Value
data("Mission Timeline", self.runMissionTimelineData.nextRow, "timeSeconds")
7Change Component Value
Component Value
self.runMissionTimelineData.gapSeconds
Value
self.runMissionTimelineData.nextRowTime - self.runMissionTimelineData.lastRowTime
8Start Recurring Timer
Timer Name
timeline
First Delay (s)
self.runMissionTimelineData.gapSeconds
Ring Once
Yes

Now the Object that runs the mission. Game Rules is an Empty Object with no picture, so nobody playing ever sees it. It has two Logic Components on its card, and one of them, Add Points, comes in the last part. Attach Run Mission Timeline now. Its Data Structure comes with it, From Logic, as the card shows.

ObjectGame Rules
Transform
Bounding Box > SizeX 3, Y 3
Data Structure
From LogicRun Mission Timeline
Data StructureRun Mission Timeline Data
Logic
Add Points
Run Mission Timeline

Place Game Rules from PLACE THESE. It sits in the middle of the window, and it’s invisible, so its place makes no difference to the game.

Save your project with Ctrl+S, and then run the game. Count three seconds. Five Zero Fighters slide out from under the top of the window in a V and fly down past the Fighter. Fire at them. The rounds fly straight through, for now.

3.6 Hits

Next, the rounds learn to hit.

Hit Sparks is a tiny burst of white, yellow and orange sparks, gone in a quarter of a second. It uses FX Spark, the picture Chapter 2’s Muzzle Flash uses. A Particle Effect card shows its pages.

Particle EffectHit Sparks
Emitter
Emission > Emit Every (ms)0
Emission > Burst Count8
Emitter Shape > Emit Shapepoint
Motion
Lifecycle > Each Particle Lives (ms)min 90, max 260
Motion > Speed (m/s)min 2.5, max 8.125
Appearance
Appearance > Particle SpriteFX Spark
Appearance > Color SourceMultiple Colors
Appearance > Multiple Colors#FFFFFF, #FFE08A, #FFB347
Appearance > Glow1.4
Appearance Over Life > Scalestart 0.45, end 0

3.6.1 Breaks on Hit

A round touches a plane, and two things have to happen. The round breaks, and the plane takes a hit. Breaks on Hit does the round’s half, and it tells the plane about the rest.

Its Event is a Collision Enter Event, which runs once, at the moment the round starts to touch something. Add it, and open the Collision section on its block. Pick Tagged Enemy Aircraft in Collision Target. Myth renames the Event to match the card: When Starting to Hit Anything Tagged Enemy Aircraft. The Tag stands for every kind of plane.

Then three Actions, in order. Trigger Custom Event on Object sends roundHit to other, the plane the round touched. A message is answered at once. The plane’s own Logic runs before the next Action here begins.

Next, Burst Particles throws six Hit Sparks, not the 8 on the Hit Sparks card. The Action’s Count wins over the effect’s own Burst Count. That six is hitSparksCount, the one Shared Variable here, a Constant. Its Z Index Offset of 2 draws the sparks a little in front of the round. Last, Destroy Instance removes the round.

The round breaks last because an Action does nothing once the Object it works on is gone. The sparks come from the round, so it has to be there for them. That’s the rule all through this chapter. Whatever removes the round or the plane goes last.

Burst Particles and Destroy Instance work on the round, so their Applies To stays on Self, where it starts. Trigger Custom Event on Object is the one aimed at the plane. Pick Other in its Applies To list, under Event Context. The name roundHit goes into its Custom Event box exactly as it’s spelled, with no quotes.

Logic ComponentBreaks on HitAttach to: MG Round

A round that hits an enemy tells it (roundHit) and breaks with a small spark.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
hitSparksCountNumberConstant6
When Starting to Hit Anything Tagged Enemy Aircraft
WhenCollision EnterObject: tag:Enemy Aircraft
1Trigger Custom Event on Object
Applies To
other
Custom Event
roundHit
2Burst Particles
Particles
"Hit Sparks"
Count
@self.hitSparksCount
Z Index Offset
2
3Destroy Instance

Attach Breaks on Hit to MG Round. Nothing hears roundHit yet, but the next Logic Component will.

3.6.2 Takes Hits

Hit a Zero Fighter, and for one blink it’s solid white, every part of it. Then it’s itself again.

Takes Hits makes that blink. Make its SHARED VARIABLES first: flashSeconds, a Constant Number. Its blocks use it.

Its first Event listens for roundHit. Breaks on Hit sends that name already, so the Add Event window knows it. Type roundHit into the window’s filter, and pick it.

First the Event tints the plane, with three Change Sprite Tint Property Actions: the tint’s color, its mode, and whether it’s on. The first has no lines on the card, because its color starts as white, which is what the flash needs. The other two make the white cover the whole plane and switch it on.

The blink ends by itself. Start Recurring Timer starts a timer named hitFlash that rings once, flashSeconds later, which is 0.06 seconds. When the timer rings, the second Event turns the tint off.

A timer that rings once rings at its First Delay. Its Repeat Every only has to be more than 0, and its box starts at 1. So Run Mission Timeline’s card leaves it as it starts, and this card gives it flashSeconds too.

Last, Takes Hits sends changeMeter to its own plane. On the hit that fills the meter, that message shoots the plane down then and there. So by the rule from Breaks on Hit, it goes last.

Go by the card for the boxes. It writes each value the way its box takes it:

  • The Mode’s Value takes "solid", in quotes.
  • The Enabled Value box holds true.
  • Start Recurring Timer’s Timer Name takes hitFlash bare, and Ring Once is a list: Yes.
  • The Custom Event box takes changeMeter bare, exactly as you type it.

For the second Event, Myth Engine asks which timer, so choose Type a timer name… and press OK. Then type hitFlash in the box that comes next. Events: the When bars shows how.

Logic ComponentTakes HitsAttach to: Zero Fighter

Each Fighter round that hits counts one hit on the enemy's meter and flashes the enemy white for a moment.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
flashSecondsNumberConstant0.06
On Round Hit
WhenroundHitCustom Event
1Change Sprite Tint Property
2Change Sprite Tint Property
Property
Mode
Value
"solid"
3Change Sprite Tint Property
Property
Enabled
Value
true
4Start Recurring Timer
Timer Name
hitFlash
Repeat Every (s)
@self.flashSeconds
First Delay (s)
@self.flashSeconds
Ring Once
Yes
5Trigger Custom Event on Object
Custom Event
changeMeter
On the Hit Flash Timer
WhenRecurring TimerTimer name: hitFlash
1Change Sprite Tint Property
Property
Enabled
Value
false

Attach Takes Hits to the Zero Fighter, where Fly Down already is.

3.6.3 Meter with Thresholds

Meter with Thresholds counts. It comes whole from Myth Engine, from the State group of the Starter list, and it listens for changeMeter by itself. Each time the message arrives, it adds changeAmount to its meter. It never lets the meter pass maximum. And the moment the meter reaches threshold, it runs one Event on its Object, Meter Threshold Reached.

So for a plane, the meter is the hits it has taken. It counts by 1 from 0, and it stops at the plane’s health, which is also the moment the plane goes down.

The sentence under its name on the card is Myth’s own description, in the engine’s words. It says the same thing: a meter kept between two numbers, and an Event when it reaches its mark.

Logic ComponentMeter with ThresholdsAttach to: Zero Fighter

Owns a bounded meter update entry point and publishes its threshold crossings as Events.

Attach toAny Object
DATA STRUCTURES
Meter with Thresholds Dataself.meterWithThresholdsData
SHARED VARIABLES
NameTypeKindStarting Value
changeAmountNumberConstant1
minimumNumberConstant0
maximumNumberConstant100
thresholdNumberConstant100
meterFieldTextConstant(empty)
Built in: this Logic Component comes whole from the engine's template.
You add it and set its Variables on the Object; you do not build its Events.

Attach it to the Zero Fighter. Its meter comes with it, in a Data Structure of its own. Then switch the list back to Components. Under Shared Variables, its changeAmount and minimum already read 1 and 0, which is what a plane needs.

Its maximum and threshold start at 100, and a plane needs its health there instead. So both turn into an Expression. Pick Expression in maximum’s Kind list, and type the card’s line into the box that takes the Value’s place, quotes and all. Then the same for threshold.

That line reads the health field from the plane’s own Enemy Stats. Each plane reads its own, so a Zero Fighter’s meter tops out at 2, from its row of Enemy Types.

Leave meterField empty. It could name a field to keep the count in, for words on the screen or other Logic to read. A plane keeps its count to itself.

Run the game, and fire at the V. Each round breaks with a spray of sparks, and each plane you hit flashes white. But they keep flying. Their meters fill, and nothing listens for that yet.

3.7 Shot Down

Now the planes go down.

Two more particle effects make the fall. The Plane Explosion is a burst of fire in five colors, from white and cream to orange, red and dark brown, each puff turning and shrinking as it flies out. It’s over in less than a second. The Smoke Puff stays longer, a few gray puffs that drift, swell and fade. Both use the FX Smoke Puff picture.

Particle EffectPlane Explosion
Emitter
Emission > Emit Every (ms)0
Emission > Burst Count40
Emitter Shape > Emit Radius (m)0.313
Motion
Lifecycle > Each Particle Lives (ms)min 260, max 860
Motion > Speed (m/s)min 1.875, max 9.375
Appearance
Appearance > Particle SpriteFX Smoke Puff
Appearance > Color SourceMultiple Colors
Appearance > Multiple Colors#FFFFFF, #FFE8A3, #FFB347, #E85D3F, #5A2D2D
Appearance > Glow1.6
Appearance Over Life > Scalestart 1.5, end 0
Appearance Over Life > Size Variation (0–1)0.6
Appearance Over Life > Starting RotationRandom Spin On
Particle EffectSmoke Puff
Emitter
Emission > Emit Every (ms)0
Emission > Burst Count12
Emitter Shape > Emit Radius (m)0.438
Motion
Lifecycle > Each Particle Lives (ms)min 700, max 1500
Motion > Speed (m/s)min 0.313, max 1.875
Appearance
Appearance > Particle SpriteFX Smoke Puff
Appearance > Color SourceMultiple Colors
Appearance > Multiple Colors#5B5F66, #3D4046, #7A7D84
Appearance > BlendNormal
Appearance Over Life > Scalestart 1.1, end 2.4
Appearance Over Life > Alphastart 0.55, end 0
Appearance Over Life > Starting RotationRandom Spin On

3.7.1 Shot Down

The second hit lands. In the same moment, the Zero Fighter bursts, a cloud of smoke opens where it was, and a sharp bang goes off. The plane is gone.

Shot Down waits for Meter Threshold Reached. When you add that Event, Myth Engine asks which meter. Leave it on Any meter and press OK, since this plane has only the one.

It tells the news first, while the plane is still there to read its points from. Then comes the show, all from the plane. Last, by the rule from Breaks on Hit, the plane removes itself.

The Counts on Burst Particles win here too. They’re its two Shared Variables, Constants: the explosion has 36 puffs, not the 40 on its card, and the smoke has 8, not 12.

Like roundHit, the name enemyShotDown goes into its Custom Event box exactly as it’s spelled, with no quotes. Nothing listens for enemyShotDown yet. At the end of this chapter, Game Rules will.

Logic ComponentShot DownAttach to: Zero Fighter

When this enemy has taken as many hits as its health it tells Game Rules (enemyShotDown), explodes and is removed.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
explosionCountNumberConstant36
smokeCountNumberConstant8
On Meter Threshold Reached
WhenMeter Threshold Reached
1Trigger Custom Event
Custom Event
enemyShotDown
2Burst Particles
Particles
"Plane Explosion"
Count
@self.explosionCount
Z Index Offset
2
3Burst Particles
Particles
"Smoke Puff"
Count
@self.smokeCount
Z Index Offset
2
4Control Sound
Sound
"Explosion Small"
5Destroy Instance

Attach Shot Down to the Zero Fighter, and its card is complete, with all five Logic Components.

Run the game. Two hits, and a Zero Fighter goes down in fire and smoke. Shoot down all five, and the sky is clear.

3.8 The Score

Last, the score.

3.8.1 Add Points

Remember enemyShotDown, the message Shot Down sent while nothing was listening for it? This is who it was for. Add Points hears it on Game Rules, and it does one thing. It adds the points of the plane that went down to $score.

How does it know that plane’s points? A message carries its sender. The Event hands over the plane that sent enemyShotDown, and event("points") reads that plane’s points field, from its row of Enemy Types. So a Zero Fighter adds 100, and the other planes of later chapters will add their own.

Make the score first. Press the + on the canvas’s Globals card and choose New Global…. Give it Name score, Type Number and Default 0. Then add its Event, for enemyShotDown, which the Add Event window knows already. Its one Action comes last. The Variable box takes the Global by its $, so type $score there.

Logic ComponentAdd PointsAttach to: Game Rules

Adds the points of every enemy shot down to the score.

Attach toAny Object
On Enemy Shot Down
WhenenemyShotDownCustom Event
1Change Variable
Variable
$score
Operator
+=
Value
event("points")

Attach Add Points to Game Rules.

The score needs a place on the screen. The HUD Top Bar is a dark strip as wide as the window, 720 by 64 pixels, the twin of the bar along the bottom. Make it the way you made the HUD Bottom Bar. It’s an Empty Object with Space Window / UI and its Screen Anchor at Top Center, and its Sprite comes from Rendering.

ObjectHUD Top Bar
Transform
Presentation > SpaceWindow / UI
Presentation > Screen AnchorTop Center
Presentation > Render LayerUI
Bounding Box > SizeX 128, Y 128
Sprite
Scene Depth Draw Order100
SpriteHUD Top Bar Art
Transform > SizeX 720, Y 64

Two words go on it. The Score Label is SCORE, in small gold letters. The Score Text is the number, larger and white. Both are Empty Objects with Space Window / UI and a Text / UI from Rendering.

Their font is Bebas Neue, tall and narrow, the font of the whole game from here on. Type Bebas into the Font list and pick Bebas Neue. It comes with Myth, so there’s nothing to install. The label’s gold is its Color, a swatch: click it, and type F4C542 into the HEX box. Two more characters stay at the end of that box, FF, and they keep the color solid.

Text Bounds Wrap to Width gives each word a box of its own, 200 pixels wide, and the words start at its left edge. So SCORE and the number line up on the left, and the number grows to the right as the score climbs. Pick Wrap to Width first. Picking it sets the box to the width of the words, so the 200 goes into the Text / UI’s own Size X after it.

The Score Text’s Text is {$score}, braces and all. The braces turn it into a live value, so the words always show the score as it is now.

ObjectScore Label
Transform
Presentation > SpaceWindow / UI
Presentation > Screen AnchorTop Center
Presentation > Render LayerUI
Bounding Box > SizeX 128, Y 48
Text / UI
TextSCORE
FontBebas Neue
Font Size20
Color#F4C542
Letter Spacing1
Text BoundsWrap to Width
Transform > Size X200
ObjectScore Text
Transform
Presentation > SpaceWindow / UI
Presentation > Screen AnchorTop Center
Presentation > Render LayerUI
Bounding Box > SizeX 128, Y 48
Text / UI
Text{$score}
FontBebas Neue
Font Size36
Letter Spacing1
Text BoundsWrap to Width
Transform > Size X200

Now place the three from PLACE THESE. All three hang from Top Center, so their Y is below 0. The bar spans the top of the window, and the label sits over the number at its left.

On the card, each of the two words has one more line: with Z-Index = 120. Give each placement that Z-Index, under Rendering, so the words are drawn on the bar and not under it. A placement’s own values shows where it is.

Run your game. A dark bar runs across the top, with SCORE in gold and a white 0 under it. Now shoot down a Zero Fighter. The 0 turns to 100. It climbs by 100 more with every plane you bring down. Your game keeps score now.

Play it!

Watch for each of these.

  • A dark bar runs across the top of the window, with SCORE in small gold letters at its left and a white 0 under it.
  • About three seconds in, five pale gray-green planes slide out from under the bar in a V, the middle plane lowest.
  • They fly straight down at a steady pace, slower than the Fighter flies.
  • Hold Space under one. A round that reaches it breaks in a little spray of sparks, and the plane flashes white for a blink.
  • The second hit: a burst of fire and gray smoke, a bang, and the plane is gone.
  • The score goes up by 100 for each plane.
  • Fly beside the V instead of under it, and your rounds fly on past, because a round breaks only on a plane it touches.
  • Sit still and hold your fire. The middle plane flies right through your Fighter, under it, and nothing happens. In Chapter 4, a touch like that will cost you.
  • The planes you miss fly on past the Fighter and out at the bottom of the window. They don’t fire, and they don’t come back.
  • With your game in front, press Alt+F4, and you’re back in the editor.
How it works

Run Mission Timeline sets an alarm for each row of the table. Spawn V Formation makes the V. Fly Down sends each plane down. A round touches a plane, the plane flashes and counts, and at its health it goes down. Game Rules adds its points.

Underneath it all is one idea. Every piece does one small job and passes the news on by name. Breaks on Hit never changes a plane’s health. Shot Down never touches the score. Each one says what happened, and the piece whose job it is answers. Because of that, a new kind of plane needs only a row of numbers and a picture. Give it the same Logic and the Enemy Aircraft Tag, and it flies down, takes hits and goes down. Anything more, a weave or a dive, is Logic of its own.

3.9 If It Didn’t Work

Something may be a little off the first time. That’s normal. This chapter is the longest so far, and its pieces only work together. Open the catch-up download from the Goal beside your project, and follow the news from the round to the score, piece by piece, until the two part ways.

The rounds fly through the planes? Check the Tags. MG Round wears Fighter Round, and its Collider meets Tagged Enemy Aircraft. The Zero Fighter wears Enemy Aircraft, and its Collider meets the Fighter and Tagged Fighter Round. Then make sure Breaks on Hit is on MG Round, with Tagged Enemy Aircraft as its Collision Target.

The rounds break with sparks, but the planes never flash? The message isn’t arriving. Compare roundHit in Breaks on Hit and in Takes Hits, letter by letter, and look for quote marks in either box. Breaks on Hit’s Trigger Custom Event on Object should have Other in Applies To.

The planes flash but never go down? Look at the Zero Fighter’s Shared Variables, where maximum and threshold should both be Expressions. With their starting numbers there, a plane would take 100 hits. And check that Takes Hits sends changeMeter, spelled exactly that way, with no quotes: it’s the name the meter listens for. Last, look for Shot Down in the Attached Logic.

A plane stays white? The hitFlash timer isn’t ringing. In Takes Hits, the timer’s name should read hitFlash, and the second Event should be for the named hitFlash timer.

The planes go down, but the score stays at 0? Is Add Points on Game Rules? Its Variable box should read $score, with the $, and its Custom Event should be enemyShotDown, spelled as Shot Down sends it. The Score Text’s Text should be {$score}, braces and all.

The score sits dim behind the bar? The two words need their Z-Index of 120, so the bar is drawn under them.

Each of these is one small fix. Make it, and you’re back with the chapter. And the catch-up download in the Goal is this chapter’s game, finished. Chapter 4 starts from it.

Challenge

The V is yours to shape. Open Mission Timeline and give Wave 1 V more planes, or spread them wider. Add a second row a few seconds later, with its x off to one side, and watch two Vs come in turn.

Or make the Zero Fighter tougher. Raise its health in Enemy Types, and its points with it, and feel how the fight changes.

Chapter 4 starts from the tables as their cards have them. So note what you change, and put it back before you go on. Or start Chapter 4 from a fresh catch-up download.

Still stuck? Search the manual, or ask in the Myth Engine Discord (opens a new tab).

The sky over the sea has its first enemies now, and your Fighter knocks them down. In Chapter 4, they shoot back.