Build a GameCreating Shatterfield

7  Score

Goal

Rocks break, waves come and go, and nothing keeps count. By the end of this chapter, every rock pays. Its points rise off it as it breaks, and the score at the top left jumps by the same amount. The high score follows it at the top center, the wave shows at the top right, and every 10,000 points brings an EXTRA SHIP.

The game as it is at the end of this chapter. Click the game to play.

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

Shatterfield, Chapter 7 finishedZip of a Myth project · 5.0 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, Press Start 2P.

7.1 The Idea

A Large rock cracks in two. A small pale 20 rises off it and fades, and at the top left of the screen a number jumps from 0 to 20. Break a Medium, and 50 rises. A Small gives 100. At the top center, a smaller line in pale blue reads HI and keeps up with every point. At the top right, WAVE 1.

In Chapter 4 a broken rock gave you nothing, because nothing kept a score. This chapter makes one.

That number at the top left is the score, the points of every rock you’ve broken this game. The high score is the best score so far.

And at every 10,000 points, the game gives you an extra Ship: one more life, with a bright little chime and the words EXTRA SHIP above the middle of the screen.

How does a piece of Logic know the score went up? It could look, every single step of the game, whether anything happened or not. Here, the piece that changes the score says so instead. Break Apart adds a rock’s points, and in the same moment it tells the whole game scored, the way Waves tells everyone nextWave. Two new pieces of Logic, Score and Extra Ships, wait for that news, and each does its own job.

Why a message? In Chapter 5, Life Icon heard the lives through Variable Changed. That news comes at the end of a step of the game. scored comes the very moment the points land, so whatever must follow the points does.

The extra Ship needs one more idea. Picture a finish line painted across the track at 10,000 points. Cross it, and the game paints the next one 10,000 points further on. That moving line is nextExtraShipAt, a field in a small form Extra Ships keeps, Extra Ships Data. It has to last from one scored to the next, so it lives in a Data Structure, the way Ship Shield’s memory did in Chapter 5.

7.2 The Plan

Here’s how the pieces work together, read from left to right.

  • The game starts -> Score sets $score to 0, and Extra Ships paints the first finish line at 10,000.
  • A Shot hits a rock -> Break Apart adds the rock’s points to $score, tells everyone scored, and shows the points rising.
  • The score changes -> Score Display shows the new number, through the braces in its Text.
  • Score hears scored -> if the score is past the high score, $highScore follows it, and HI shows the new best.
  • Extra Ships hears scored -> if the score has crossed the finish line, it adds a life, plays ExtraLife, shows EXTRA SHIP and moves the line on.
  • A life is added -> Life Icon, from Chapter 5, shows one more tiny Ship.

7.3 Set Up

This chapter needs one new sound, ExtraLife, the bright little chime for an extra Ship, and two Global Variables. Make score and highScore the way you made wave, with New Global… on Ship Gun’s Globals card. Each is a Number, with a Default of 0.

PLACE THESE waits until its three Objects exist, in the next part.

Set upWhat this chapter adds
SOUNDS (from the starter kit)
ExtraLife
GLOBAL VARIABLES
$scoreNumberstarts at 0
$highScoreNumberstarts at 0
SCENE Space: PLACE THESE
ObjectXY
Score Display150-28
High Score Display0-24
Wave Display-110-26

7.4 Numbers at the Top

First, the numbers.

7.4.1 Score Display

Score Display is the big white number at the top left. It’s a Screen UI Object, made the way you made the Wave Banner in Chapter 6.

Its Text is {$score}, braces and all, with nothing around it. So it shows the score and only the score. Its Font Size is 24, the biggest of the three, because it’s the number you’ll glance at most.

Its words sit in a box of their own. Under Text / UI, Text Bounds is a list that starts on Fit to Text. Pick Wrap to Width. Now the box has a width you choose. The card’s last line gives it, Transform > Size X, 260. Type 260 into W, under Text Frame, and Text / UI’s Transform shows the same 260 as its Size X. The score starts at the box’s left side and grows to the right.

There’s no Screen Anchor line on its card. A new Screen UI Object starts at Top Left, right where the score belongs.

ObjectScore Display
Transform
Presentation > SpaceWindow / UI
Presentation > Render LayerUI
Bounding Box > SizeX 32, Y 32
UI Interaction
Element TypeText
Text / UI
Text{$score}
FontArcade HUD Font
Font Size24
Color#F2FBFF
Text BoundsWrap to Width
Transform > Size X260

7.4.2 High Score Display

High Score Display is the quieter line at the top center: HI, and the best score so far. It’s half the score’s size, in pale blue, so your eye finds the score first. It’s anchored at the top center and centered on that spot, so however long the number grows, the line stays in the middle.

ObjectHigh Score Display
Transform
Presentation > SpaceWindow / UI
Presentation > Screen AnchorTop Center
Presentation > Render LayerUI
Bounding Box > SizeX 32, Y 32
UI Interaction
Element TypeText
Text / UI
TextHI {$highScore}
FontArcade HUD Font
Font Size12
Color#9FB4D8
AlignmentCenter

7.4.3 Wave Display

Wave Display matches it, at the top right, with the same words the Wave Banner shows: WAVE {$wave}. The banner comes and goes, though. This one stays. It has a box of its own too, made the same way: Wrap to Width, and 180 in W. Alignment Right keeps the line against the box’s right side as the wave grows to two figures.

ObjectWave Display
Transform
Presentation > SpaceWindow / UI
Presentation > Screen AnchorTop Right
Presentation > Render LayerUI
Bounding Box > SizeX 32, Y 32
UI Interaction
Element TypeText
Text / UI
TextWAVE {$wave}
FontArcade HUD Font
Font Size12
Color#9FB4D8
AlignmentRight
Text BoundsWrap to Width
Transform > Size X180

Now place all three, from PLACE THESE. Each X and Y is a Screen Offset in pixels from its own Screen Anchor. X counts to the right and Y counts up, so a minus sign turns either one around. Score Display’s X of 150 is the middle of its box, 260 wide. So the box starts a little in from the corner, and the score sits above the row of tiny Ships from Chapter 5. Wave Display’s X of -110 does the same from the right edge, for its box of 180. Each Y below 0 counts down from the top, so all three sit a little below the top edge. If the placement boxes have slipped your mind since Chapter 6, the passage on the Set up card shows them.

Run the game. A 0 sits at the top left, HI 0 in the middle, and WAVE 1 at the right. Break a rock, and the 0 stays a 0, because nothing adds to the score yet.

7.5 Every Rock Counts

Now each broken rock pays.

7.5.1 Break Apart

A Shot touches a Large rock. Along with the sparks and the boom, two new things happen. The score jumps by 20. And a small 20 rises off the rock, pale blue-white, and fades in about half a second.

Chapter 4 promised that the points would come with the score. Here they are. Break Apart gets a new Shared Variable, points, and each size sets its own under its Variables. A Large is worth 20, a Medium 50 and a Small 100. The smaller the rock, the more it pays.

Three new Actions go at the very top of the hit Event. First, Change Variable adds points to $score. Then Trigger Custom Event tells the whole game scored, in that same moment. Last, Popup Text shows the same number. It rises from the rock.

Change Variable’s Variable box takes $score, dollar sign and all. The card adds the points on, with +=. Click the = on its block and pick += · Add, as in Chapter 6. Its Value is @self.points. Trigger Custom Event is the Action Waves uses for nextWave, and scored is a new name, so type it into its box.

On the card, Popup Text’s Text is text(@self.points). The Text wants words, but points is a number, so text() turns it into words. A Large’s 20 becomes the text 20.

Here Myth falls short today. Popup Text’s Text keeps whatever you type as plain words, so text(@self.points) would rise off the rock as written, letters and all. Words can hold a live value between braces, though, written the way Myth writes it inside. Type {sharedVar("self","points")} into the Text. Type all of it, quotes too. It’s the rock’s points, filled in as it breaks. That’s Myth’s gap, not yours.

The popup’s look comes from four more Shared Variables: popupColor, popupSize, popupRise and popupSeconds. They’re the same for every size, so no Object card lists them.

The first, popupColor, is a Color. Pick Color in the Add Shared Variable window’s Type list, and its Starting Value turns into a swatch with a HEX box. Type the card’s code there, after the #. Myth puts each new Shared Variable at the bottom of its list, while the card shows where the game keeps it. Their order changes nothing in play, so leave yours as it comes.

Popup Text’s Color is a box once the Logic has a Color of its own, with a small swatch beside it. Click it, type @self.popupColor over the white that’s there, and click away. Size, Rise and Seconds are boxes too, and they take @self.popupSize and the rest as the card has them.

Each new block goes in from a right-click on Mode 1, with Add unattached Action here, and lands loose, with no arrow into it. This time, don’t use Connect to sequence. It would join them at the bottom of the line, after Destroy Instance, and once the rock is destroyed, nothing after it runs. Join them with the round handles instead.

Click the handle at the bottom of Mode 1, then the handle at the top of Change Variable. Now click the handle at the bottom of Change Variable, and then the one at the top of Trigger Custom Event. Last, click the bottom of Trigger Custom Event, then the top of Popup Text.

The three blocks don’t move from where they landed. The arrows show the order. They run from Mode 1 to Change Variable, on to Trigger Custom Event and Popup Text, and from there to Burst Particles. The passage on Actions has the handles too.

Logic ComponentBreak ApartAttach to: Asteroid Large, Asteroid Medium, Asteroid SmallAddDelete

An Asteroid that is hit scores and shows its points, bursts into sparks, plays its break sound, leaves its fragments and is destroyed.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
pointsNumberConstant20
sparkCountNumberConstant34
shakeNumberConstant0.012
shakeSecondsNumberConstant0.18
popupColorColorConstant#dff6ff
popupSizeNumberConstant0.469
popupRiseNumberConstant0.813
popupSecondsNumberConstant0.55
breakSoundSoundConstantExplosionLarge
fragmentObjectConstantNone
fragmentsNumberConstant2
On Hit
WhenhitCustom Event
1Change Variable
Variable
$score
Operator
+=
Value
@self.points
2Trigger Custom Event
Custom Event
scored
3Popup Text
Text
text(@self.points)
Color
@self.popupColor
Size
@self.popupSize
Rise
@self.popupRise
Seconds
@self.popupSeconds
4Burst Particles
Particles
"Impact Sparks"
Count
@self.sparkCount
5Control Sound
Sound
@self.breakSound
6If@self.shake > 0
Then
7Camera Shake
Intensity
@self.shake
Seconds
@self.shakeSeconds
8Repeat@self.fragmentstimes
Each time
9Create Instance
Object to Create
@self.fragment
Position Relative To
Self
Created As
newFragment
10Destroy Instance

The old steps keep their places and count on from 4. Now each size gets its points. They go in its Variables. A Large keeps the Starting Value, 20, so its card has no points line. Type 50 into the Medium’s and 100 into the Small’s. Their cards show each whole Object this time. The one new line is points, on the Medium and the Small.

ObjectAsteroid Large
Transform
Bounding Box > SizeX 3.875, Y 3.875
Physics > Allow RotationOn
Collider
CollisionSensor
Shape and Transform > ShapeCircle
Shape and Transform > Radius1.5
Sprite
Scene Depth Draw Order10
SpriteAsteroid Standard
Transform > SizeX 3.875, Y 3.875
Tags
Object TagsAsteroid
Logic
Asteroid Material
Asteroid Drift
Break Apart
Wrap Around World
Shared Variables
fragmentAsteroid Medium
wave > KindExpression
wave > Expression$wave
ObjectAsteroid Medium
Transform
Bounding Box > SizeX 2.0625, Y 2.0625
Physics > Allow RotationOn
Collider
CollisionSensor
Shape and Transform > ShapeCircle
Shape and Transform > Radius0.781
Sprite
Scene Depth Draw Order10
SpriteAsteroid Standard
Transform > SizeX 2.0625, Y 2.0625
Tags
Object TagsAsteroid
Logic
Asteroid Material
Asteroid Drift
Break Apart
Wrap Around World
Shared Variables
points50
sparkCount22
shake0.006
breakSoundExplosionSmall
fragmentAsteroid Small
wave > KindExpression
wave > Expression$wave
minSpeed2.5
maxSpeed4.219
ObjectAsteroid Small
Transform
Bounding Box > SizeX 1.125, Y 1.125
Physics > Allow RotationOn
Collider
CollisionSensor
Shape and Transform > ShapeCircle
Shape and Transform > Radius0.406
Sprite
Scene Depth Draw Order10
SpriteAsteroid Standard
Transform > SizeX 1.125, Y 1.125
Tags
Object TagsAsteroid
Logic
Asteroid Material
Asteroid Drift
Break Apart
Wrap Around World
Shared Variables
points100
sparkCount14
shake0
breakSoundAsteroid Break
fragmentAsteroid Small
fragments0
wave > KindExpression
wave > Expression$wave
minSpeed3.75
maxSpeed6.094

Nothing to build for this next part. You’ll see it, though. A Ship that crashes into a rock sends the rock hit too, from Ship Crash. So a crash still scores. Its points rise over the wreck, a small comfort as your Ship goes up in a ball of sparks.

Run the game, and break a rock. A small number rises off it, and the score at the top left jumps by the same amount. HI keeps its 0 for now. Break Apart sends scored, and nothing listens for it yet. Score will, in the next part.

7.5.2 Score

Score goes on Game Rules, with Lives and Respawn and Waves. Both its Events are short.

At Game Start, it sets $score to 0. The Global already starts at 0, so why say it again? Look ahead to Chapter 9, where a new game can begin without the whole program starting over. The score goes back to 0 then too, and this is where it happens.

The second Event waits for scored. Break Apart sends it, so type scored into the Add Event window’s filter, and it’s there. On the card, its heading is On Scored.

Each time scored arrives, Score asks whether the score is past the best. If it is, the best moves up to meet it. If not, HI keeps its number.

Every new block here goes at the end of its line, so Connect to sequence is the right join this time. The If’s condition is its one box. The Change Variable inside it goes in with Add inside Then, as If, Else and Repeat shows.

Logic ComponentScoreAttach to: Game Rules

The score starts at 0 each game; the high score follows it whenever the score passes it.

Attach toAny Object
When the Game Starts
WhenGame Start
1Change Variable
Variable
$score
Value
0
On Scored
WhenscoredCustom Event
1If$score > $highScore
Then
2Change Variable
Variable
$highScore
Value
$score

Attach Score to Game Rules, below Waves. Game Rules’ card comes with the next part, which adds one more.

Run the game, and break a few rocks. The score climbs by 20, 50 and 100. HI climbs with it, since every point of a first game is a new best.

7.6 An Extra Ship

Last, the score starts to pay you back.

7.6.1 Extra Ships

Extra Ships also goes on Game Rules, and it listens for the same news Score does. When scored arrives, both of them hear it, each in its own Event, and neither needs to know about the other.

This part is the chapter’s one hard idea, so take it slowly, one moment at a time.

At Game Start, Extra Ships paints the first finish line. Its field nextExtraShipAt gets extraShipEvery, ten thousand points, and the finish line belongs to Extra Ships alone.

Score, meanwhile, sets the score to 0 in that same first moment. Does Extra Ships hear that? No. It listens only for scored, and a score set to 0 sends nothing.

Then you play. Each broken rock sends scored, and each time, Extra Ships asks if the score is at the line or past it. That’s the If, with >=. For a long while the answer is no.

Then one Small rock takes the score past ten thousand. Past the line. Four things happen at once. $lives goes up by 1. The finish line moves on by extraShipEvery, to twenty thousand. ExtraLife chimes. And EXTRA SHIP rises in mint green, a little above the middle of the screen, and fades.

Why move the line, instead of asking whether the score is a whole number of ten thousands? Because the score jumps. It often goes from a little under ten thousand to a little over, without landing on it. A line that the score only has to cross can’t be missed.

The popup’s X and Y are worked out from $areaWidth and $areaHeight, the screen’s size from Chapter 3. Half of each is the middle.

Make Extra Ships Data first, the way you made Ship Shield Data in Chapter 5, with Add > Data Structure. Press Add Field, and type nextExtraShipAt over the field’s name. It’s a Number already, at 0, as the card says.

Data StructureExtra Ships Data

Object Data of Logic "Extra Ships" (its state that lasts between Events).

nextExtraShipAtNumberdefault 0

Then make Extra Ships, its SHARED VARIABLES first, each Constant. popupColor is a Color again, with its own mint green. Press the + on its Data Structures card, and pick Extra Ships Data under Existing Data Structures. Its row reads self.extraShipsData. Every path below starts with that name.

Both Change Component Values take the path typed, self.extraShipsData.nextExtraShipAt, then Enter. An Operator list and a Value box appear. The first keeps =, with @self.extraShipEvery as its Value. The second adds on, and its Operator list writes the card’s += as Plus. Pick Plus there.

The If’s condition is its one box: $score >= self.extraShipsData.nextExtraShipAt. Inside it, the Change Variable adds a life. As in Break Apart, pick += · Add on its block, and type 1 into its Value. Pick ExtraLife in Control Sound’s Sound list.

In Popup Text, type EXTRA SHIP into the Text, plain, with no quotes. The block draws its own quote marks around it afterward. Its Color takes @self.popupColor, as in Break Apart, and this time that’s the mint green. Position Relative To is a list that starts on Object. Pick World, and type the card’s X and Y.

The four Actions inside the If go in one at a time, each with Add inside Then, and Connect to sequence joins each to the True line.

Logic ComponentExtra ShipsAttach to: Game Rules

Each time the score passes another extraShipEvery points, the player gains a life, with a sound and an "EXTRA SHIP" popup.

Attach toAny Object
DATA STRUCTURES
Extra Ships Dataself.extraShipsData
SHARED VARIABLES
NameTypeKindStarting Value
extraShipEveryNumberConstant10000
popupAboveCenterNumberConstant3.75
popupColorColorConstant#7dffb2
popupSizeNumberConstant0.75
popupRiseNumberConstant1.25
popupSecondsNumberConstant1.2
When the Game Starts
WhenGame Start
1Change Component Value
Component Value
self.extraShipsData.nextExtraShipAt
Value
@self.extraShipEvery
On Scored
WhenscoredCustom Event
1If$score >= self.extraShipsData.nextExtraShipAt
Then
2Change Variable
Variable
$lives
Operator
+=
Value
1
3Change Component Value
Component Value
self.extraShipsData.nextExtraShipAt
Operator
+=
Value
@self.extraShipEvery
4Control Sound
Sound
"ExtraLife"
5Popup Text
Text
EXTRA SHIP
Color
@self.popupColor
Size
@self.popupSize
Rise
@self.popupRise
Seconds
@self.popupSeconds
Position Relative To
World
X
$areaWidth / 2
Y
$areaHeight / 2 + @self.popupAboveCenter

Attach Extra Ships to Game Rules, below Score. The order changes nothing in play, since neither touches what the other uses, but the card’s order is quicker to check. Extra Ships Data comes along, as Ship Shield Data came to the Ship. On Game Rules’ card, that’s the Data Structure line.

ObjectGame RulesAddDelete
Data Structure
From LogicExtra Ships
Data StructureExtra Ships Data
Logic
Lives and Respawn
Waves
Score
Extra Ships
Shared Variables
shipShip
asteroidAsteroid Large
bannerWave Banner

Remember the five Life Icons from Chapter 5, and the two that never showed? This is what they were waiting for. Extra Ships adds a life, Life Icon hears lives change, and one more tiny Ship appears. There’s no new Logic for it at all. A sixth life still counts, though the row stops at five tiny Ships.

Ten thousand points is a lot of rocks. To see an extra Ship now, open Game Rules, and under Variables type 100 into extraShipEvery’s Value. Run the game, break a few rocks, and there it is. The next one comes at two hundred. Then type 10000 back.

Play it!

Watch for each of these.

  • When the game starts, the top left shows 0, the top center HI 0, and the top right WAVE 1.
  • Break a Large rock. A pale 20 rises off it and fades, and the score goes up by 20. A Medium shows and adds 50, and a Small 100.
  • HI follows the score, point for point, through your first game.
  • Crash into a rock. The Ship is lost, but the rock’s points still rise and count.
  • The top right changes to WAVE 2 the moment the banner says WAVE 2.
  • Reach 10,000 points, or 100 with the tip above. ExtraLife chimes, EXTRA SHIP rises above the middle of the screen in mint green, and one more tiny Ship appears at the top left.
  • The next extra Ship comes at 20,000, or 200, and not before.
How it works

A rock breaks, and its points land. Break Apart tells the whole game, scored, in that same moment. Three numbers along the top follow their Globals. Score keeps the best. Extra Ships keeps a finish line, and moves it on each time the score crosses it.

Underneath is one idea. Nothing here checks the score every step. The piece that changes the score tells the others, and each listener does its own job when the news comes. Two can listen for one message, and neither gets in the other’s way.

7.7 If It Didn’t Work

Something may be a little off the first time, and that’s normal. Run the game and watch the numbers.

The score stays at 0, and no number rises off a broken rock? Break Apart’s three new steps may have joined at the bottom, after Destroy Instance, where nothing runs. Make the handle moves from Break Apart’s part again. The handles move a block from wherever it sits, so they bring all three back to the top.

A number rises, but the score stays at 0? Break Apart’s Change Variable needs $score in its Variable box, dollar sign and all.

The score jumps about instead of climbing? Then that Change Variable needs += on its block, before @self.points. With =, the score only ever shows the last rock’s points.

The score climbs, but no number rises? Popup Text may still have no arrow into it, waiting to be joined after Trigger Custom Event with the handles.

The top left shows the word score, or nothing at all, where the number should be? Check the Text in Score Display: {$score}, braces, dollar sign and all. If it reads {value} when you open it again, that’s how Myth shows it once typed, as with the Wave Banner, and it’s fine.

The score works, but HI stays at 0? Perhaps Score was never attached to Game Rules, or it went onto another Object by mistake. If it’s on Game Rules, perhaps nothing reaches its scored Event. Break Apart’s Trigger Custom Event has to send scored, spelled the same way. And Score’s If compares $score with $highScore.

The score starts far in from the left edge, or the wave number stops short of the right one? Check Text Bounds on Score Display and Wave Display. Each should be Wrap to Width, with the card’s number in W.

The numbers sit in the wrong corners? Check each Screen Anchor on the three cards, one at a time. Score Display has none, so it stays at Top Left. If a number is off the screen, its X or Y in PLACE THESE may have lost its minus sign.

An extra Ship comes with the very first rock you break? The finish line was never painted, so it started at 0 and the first rock crossed it. Look in Extra Ships’ Game Start Event.

Extra Ships come with every rock once you pass the first line? The line isn’t moving on. Check the Change Component Value inside the If. Its path is self.extraShipsData.nextExtraShipAt, with Plus in its Operator list and @self.extraShipEvery as its Value.

No extra Ship ever comes, even at 100? First make sure Extra Ships is attached to Game Rules at all, and that its second Event waits for scored. If it does, check the If’s comparison, >=, and make sure the score in it is $score, with its dollar sign.

A rock shows words instead of its points, such as text(@self.points)? Its Popup Text needs the braces form, {sharedVar("self","points")}, typed whole.

Each of these is a small fix. Make it, run the game again, and you’re back with the chapter. The catch-up download in the Goal is this chapter, finished, if you’d like to compare.

Challenge

What’s a rock worth to you? Each Asteroid’s points is under its Variables, so make a Small worth 500 and see how fast the score runs. Set extraShipEvery to 5000, and the game turns generous. Or give the score a word in front, the way HI has one, and make its Text SCORE {$score}. Chapter 8 is written for the card’s numbers. Set them back before you go on, and write yours down if you’d like to keep them.

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

Every rock counts now, and a good run pays you back with a Ship. In Chapter 8, something out there starts shooting back.