- Learn
- Tutorials
- Algorithms
- A* Search
- 1 Slide the Tiles
1 Slide the Tiles
By the end of this chapter, the puzzle lies ready on the worktable. Eight Tiles sit out of order on the velvet, and the Goal waits on a parchment card beside them. Click a Tile beside the Blank, and it slides in. Put them all in order, and the card says Solved.
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 2 from it.
To open it, start Myth Engine, choose File › Open Project... and pick the downloaded file.
1.1 The Idea
Try the game above. Click Tile 5, in the top-left corner, and nothing moves, because Tile 5 isn’t beside the Blank. Now click Tile 4, above the Blank. It glides straight down in 0.22 seconds and lands square.
That’s this chapter’s whole game: the worktable, the Tiles, the Goal on its parchment card, and your hand. The navy bar under the Board stays empty, and only your hands move the Tiles.
To you, the puzzle is eight Tiles on velvet. The game needs something smaller to hold. In Chapter 2, a search will write down dozens of Boards, one after another, and check each new one against the rest. A Board that fits in one number is quick to write down and quick to check. So the game keeps the whole puzzle as one number.
Read the Board the way you read a page. Go along the top row, then the middle, then the bottom, and write each Tile’s number as you go, with a 0 for the Blank. You get 542703816. That’s the Board State, the whole puzzle in nine digits.
Each place on the Board is a Slot. Slots are numbered the same way, from Slot 0 in the top-left corner to Slot 8 in the bottom-right. So the first digit of the Board State is Slot 0’s, and the last is Slot 8’s. The Blank is in Slot 4, the middle.
Think of the Board State as the puzzle written on a slip of paper. The Tiles are a drawing of what the slip says. Change the slip, and the drawing follows.
A Move is one Tile sliding into the Blank, and on the slip it’s a swap: the Tile’s digit and the 0 trade places. Every Move costs the same, one slide. Keep that in mind. In Chapters 2 and 3 you’ll build A* Search, and it finds a Route with the fewest Moves.
The Goal is a Board State too: 123456780, the Tiles in order with the Blank last. The puzzle is solved when the Board State equals it. That’s one comparison of two numbers.
One Object holds the slip and decides every Move. It’s Puzzle Rules, and it has no picture at all. The Tiles only ask it.
Two small Functions you’ll make today, Slot Distance and Board After Move, look modest. Chapter 2’s search runs on both of them.
One more thing, so it doesn’t worry you. Most parts of this chapter end with something new on the screen. The part named Puzzle Rules doesn’t. When you run the game at its end, your Tiles stand exactly where they stood. The part after it, A Move, makes them move at last.
1.2 The Plan
Here’s how the pieces work together. Read each line from left to right. Almost every name in them is new, so read them once for their shape. They’ll make sense one at a time as you build.
- The Scene starts -> Start Board writes the start Board into
$boardState-> each Tile, as it’s created, finds its Slot there and goes to it (Slide To Slot). - Each Goal Cell is created -> Show Goal Tile finds its place on the parchment card and its number in the Goal.
- You click a Tile -> Click To Choose calls Choose Tile -> Choose Tile sends
tileChosento Puzzle Rules. - Puzzle Rules hears
tileChosen-> Hand Moves checks the Tile is beside the Blank, makes the Move in$boardState, and sendsboardChanged. - Every Tile hears
boardChanged-> the one whose Slot changed slides there -> it sendsslideFinishedto Puzzle Rules -> Hand Moves listens again. - Check Goal hears
boardChangedtoo -> it shows Solved when$boardStateequals the Goal. - You press a key from 1 to 8 -> Tile Keys calls Choose Tile, the same as a click.
1.3 Set Up
A new project opens on an empty blue Scene. It can feel like a great deal of nothing, and the feeling lasts only until the first thing you place.
If you made a Blank 2D project on the Welcome page and installed the Starter Kit, you’re ready. If not, choose File > New Project… and pick Blank 2D. Name it 8-Puzzle Solver, choose its folder with Browse…, and press Create Project. Then install the Starter Kit with File > Install Myth Pack… and the file from the button below. Myth Engine asks first. Its window says the kit adds 2 resources, the game’s two pictures. Press Install.
To install it, open Myth Engine, choose File › Install Myth Pack... and pick the downloaded file.
Turn on Advanced Mode now, from the Settings menu, because the Tiles glide with two of its blocks. Before your first card, on the Making page, says more.
The Set up card follows these paragraphs. Read them first, then work down the card from the top. Leave three of its blocks for later. COMMANDS come with the keys, in the last part. GLOBAL VARIABLES are made on a Logic Component’s Globals card, so they wait for Start Board, in the part named Puzzle Rules. And each part places its own Objects from PLACE THESE, once they exist.
ART names the two pictures. The Starter Kit brought both, so there’s nothing to make.
The SCENE block names a Scene called Puzzle Table, marked (new). Your project already has one Scene, named Scene, so give it the card’s name instead of making another. In the Resources panel, open Scenes, right-click Scene, choose Rename, and type Puzzle Table. Start Scene follows the new name by itself.
Now open Game Settings, the button at the top of the Resources panel on the left. Enter the card’s GAME SETTINGS lines from the top down. The Set up card on the Making page says where each one lives.
Pixels per Meter comes first, and that’s on purpose. The moment you type the Reference Height, Myth works out the game’s height in meters, at the Pixels per Meter it has then. In the card’s order, that’s 850 pixels at 40 to the meter: 21.25 meters, the game’s own height.
Typed them the other way round? Nothing is lost. Once Pixels per Meter reads 40, type a different number into Reference Height, then 850 again. Myth works the height out afresh each time it changes.
Reference Width and Reference Height make the game’s screen 1000 by 850 pixels. Every X and Y you’ll type for something on the screen counts in those pixels. The Page Background is the dark slate around the game. Click its swatch and type the code into the HEX box.
Now the camera. Open Puzzle Table, pick Select, the arrow above the preview, and click an empty spot. The Scene’s Properties appear on the left. Under Cameras and Views, press Add View. Myth makes the Main Camera and the Main View together, sized from the Game Settings you’ve typed. They already match the card. Check them against its Camera and View lines. Under the View, one line sums it up and ends with 1 meter = 40 screen px.
If a camera number is different, type the card’s over it. The Main Camera’s boxes are right there, under Visible World Area: Position X and Y, then Visible Width and Visible Height. If the View’s pixels are different, look again at Reference Width and Reference Height.
Start Scene should already read Puzzle Table · 2D. It followed the name.
12345678408-Puzzle Solver1000850#101E29Puzzle Table · 2DSave your project now with Ctrl+S. Do it again at the end of every part.
1.4 The Worktable
First, the table itself.
Everything behind the Tiles on the Welcome page is one picture. The dark wood, the brass frames, the velvet Board, the parchment card, the navy bar, the lantern and the star charts are all the Observatory Worktable. It’s drawn 1000 by 850 pixels, so it fills the whole screen.
It goes on a Screen UI Object, the Observatory Background, with a Sprite whose Scene Depth Draw Order of -30 keeps it behind everything else. An Object card and its components on the Making page shows how. Read it down to the paragraph on UI Interaction. The rest waits for the Tile. A new Screen UI Object comes with UI Interaction, but the worktable’s card doesn’t list it, so remove it.
The card gives the size twice. Under Transform, the Bounding Box is the Object’s own box, and the Sprite’s Transform > Size is how big the picture is drawn. On every card in this game, the two match.
Window / UIUIX 1000, Y 850-30-30Observatory WorktableX 1000, Y 850The plate at the top of the picture is blank, and the words on it are yours to add. The Title says 8-puzzle (A*) in pale gold. Under it, smaller, the Subtitle says Slide tiles into order. Each is a Screen UI Object with a Text / UI and nothing else, so remove UI Interaction from both.
Window / UIUI8-puzzle (A*)32Semibold#F4E4BFCenterVectorWindow / UIUISlide tiles into order.16Semibold#E0CDA5CenterVectorNow place all three. Open Puzzle Table, find each one under Predefined Objects in the Place Scene Content panel, and drag it onto the Scene. Type its X and Y into its Screen Offset (px). The worktable goes at 500 and -425, the Title at 500 and -82, and the Subtitle at 500 and -119.
Across, 500 is the middle of the screen. Down, a minus sign means below the top edge, because up counts as positive there. So -425 is halfway down.
Run the game: press Play, the triangle at the top of the editor. The worktable fills the window. The plate reads 8-puzzle (A*), with its smaller line under it, and the velvet Board is empty. Close the game’s window to come back.
The table is set for a puzzle.
1.5 Eight Tiles
Now the Tiles.
Each one is a cream square, 142 pixels across, with a big slate-blue number. They stand 150 pixels apart, so a thin line of navy velvet shows between them.
There are eight Tiles but only one Tile Object, placed eight times, and each placement carries its own number. Tile 5 is always the same Tile, wherever it slides.
That number lives in a Data Structure, a small form of named fields that an Object carries. This one, Numbered Tile, has a single field, number. A Data Structure card on the Making page shows how to make it.
The number a Tile carries, 1 to 8. Each Tile placement sets its own; the Tile shows it and its Logic reads it.
The Tile is a number on a picture. The picture is UI Background, the tiny white square from the Starter Kit, drawn at 142 pixels and tinted cream on each placement. Its Z Index Within Object of -1 keeps it under the number. The number is the Text {number}, braces and all: it shows the number field of the Tile’s own Numbered Tile.
The Tile keeps its UI Interaction. That’s what will let a click reach it.
The card says Numbered Tile comes From Logic, because in the finished game Slide To Slot brings it. Your Tiles need their numbers now, though. So attach it yourself: Data Structure is under Data in the Component Toolbox, and Numbered Tile is in its Data Structure list. When Slide To Slot arrives later, it finds this one and uses it. No second copy is made. Your Tile’s Data Structure part won’t say From Logic, and that’s all right.
The card’s foot lists two Logic Components and a Shared Variable that don’t exist yet. Leave them off for now.
Window / UIUIX 142, Y 142{number}50Bold#233947CenterVector-1UI BackgroundX 142, Y 142#F1E8D3Slide To Slot, Click To ChooseNumbered TilePuzzle RulesThen place eight Tiles from PLACE THESE, the last block of the Set up card. The link takes you to the top of the card, so scroll down past the Game Settings to its foot. Your browser’s Back button brings you here again. Under each Tile is a line like with Data Structure > Values > Number = 1. That’s the placement’s own number. Give each Tile its Tint, #F1E8D3, too. A placement’s own values on the Making page shows where both of them go.
Look at where the card puts them. Tile 5 goes at 187 and -260, the top-left Slot, with Tile 4 beside it and then Tile 2. They’re placed exactly as the puzzle starts.
Run the game. Eight cream Tiles sit on the velvet: 5 4 2 across the top, then 7, an empty square and 3, then 8 1 6 across the bottom. Click one. Nothing happens yet. For now the Tiles are only a picture of a puzzle.
1.6 The Goal on Its Card
Next, the picture on the parchment card that shows where the Tiles belong.
On the parchment card, under the word Goal, sits a small picture of the solved puzzle: 1 2 3, 4 5 6, 7 8, and a last cell, empty and a shade darker than the rest. Each of the nine cells is a Goal Cell, 64 pixels square.
You could type a number into each cell by hand. The game doesn’t. It reads the Goal from a table and draws whatever the Goal says. Change the Goal, and the picture follows.
Two tables hold the facts. Puzzle Settings has one row, puzzle, with two Board States: startBoard, the puzzle the game opens with, and goalBoard, the Goal. A Data Table card on the Making page shows how to make a table.
542703816123456780The table’s columns are the fields of its own Data Structure, Puzzle Settings Entry, which Myth makes with the table. Give it its two fields first. Their defaults are the puzzle’s own numbers, so the new row comes out right, and you only name it puzzle.
One row of the "Puzzle Settings" Data Table.
Board Layout says where each drawing of a Board sits on the screen, one row for each. The board row is the Board you play on. The goalPicture row is the small copy on the parchment card, with its Slots closer together. In each row, boardLeft and boardTop are the center of Slot 0, the top-left Slot, and slotSpacing is how far apart the Slots stand.
187-260150694-31772Board Layout Entry works the same way, and its defaults are the board row’s numbers. Only the goalPicture row needs new ones.
One row of the "Board Layout" Data Table.
Each Goal Cell carries a Goal Slot, a Data Structure of two fields. The first, slot, says which Slot of the picture the cell shows. The second, label, is the number it shows. It starts empty, so clear its Value box, and the Blank’s cell keeps it that way.
What one Goal Cell shows. slot is the Slot of the Goal Picture it shows (0 to 8, in reading order), set on each placement; label is the number it shows: the Tile the Goal has in that Slot, empty for the Blank.
1.6.1 Tile In Slot
Here is the chapter’s hardest idea, so it gets the most room.
Tile In Slot answers one question: which Tile is in this Slot? You hand it a Board State and a Slot, and it hands back tile, the digit in that place, with 0 for the Blank.
How do you pull one digit out of a number? With two moves from ordinary arithmetic. Dividing by 10 pushes the last digit past the decimal point, and floor() throws away everything after the point. And % 10, the remainder after dividing by 10, keeps only the last digit.
Count it out for Slot 1 of 542703816. Slot 8 holds the last digit, so after any Slot come 8 - slot more digits. After Slot 1, that’s seven. The pow(10, 8 - slot) in the formula is a 1 with that many zeros after it, ten million here. Dividing by it pushes all seven past the decimal point, and floor() throws them away. What’s left is the first two digits, a 5 and a 4. And % 10 keeps the last of those, 4. Tile 4 is in Slot 1, top middle, as the Board shows.
Ask about Slot 4, and the answer is 0. That’s the Blank.
The whole answer fits in one line. That’s the Value of its only Action, a Return, which gives the answer back. Its RETURN TYPE is Number.
It’s your first Function. A Function card on the Making page shows how to make one, with its PARAMETERS, its RETURN TYPE and its Return.
Which Tile is in one Slot of a Board State: 0 for the Blank. The Board State's first digit is Slot 0 (the top-left cell) and its last digit is Slot 8.
- Value
floor(board / pow(10, 8 - slot)) % 10
1.6.2 Slot Position
No player ever sees Slot Position, yet every Tile and every Goal Cell asks it where to stand. It’s the one place where a Slot becomes a spot on the screen.
It works in two moves. First, the Slot’s column and row: the column is what’s left over when slot is divided by 3, and the row is how many whole rows of 3 come before it. Second, pixels. It starts at the Slot 0 center from Board Layout, adds slotSpacing for each column across, and takes away slotSpacing for each row down.
It takes away because up counts as positive on the screen, so a lower row has a smaller y.
Which drawing? That’s layout, a word naming a row of Board Layout: board for the Board, goalPicture for the Goal picture. One Function serves both.
It hands back two numbers, x and y, so its answer is a small Data Structure, Slot Position Result. Make that first. Then it’s on the Return Type list.
What Slot Position gives back: x and y, the center of the Slot on screen.
Slot Position is the first Function with a line of Actions, seven blocks hanging from the Start block at the top of the canvas. Two Declare Variables make slotX and slotY, which live only while it runs. Four Change Variables work them out. Last, the Return gives both back, as x and y. Actions, one at a time shows how to add each one, join it to the line and set its Operator.
Join all seven. A block left standing apart from the line does nothing when the game runs, and the Goal Cells would land in the wrong places.
In the editor, a Change Variable’s box may show self in front, as in self.slotX. It’s the same Variable.
Where one Slot of a Board drawing is on screen: the center of that Slot, from the Board Layout row named by layout ("board" for the Board, "goalPicture" for the Goal Picture). This is the only place a Slot is turned into a position.
- Name
slotX- Value
0
- Name
slotY- Value
0
- Variable
slotX- Value
data('Board Layout', layout, 'boardLeft')
- Variable
slotX- Operator
+=- Value
(slot % 3) * data('Board Layout', layout, 'slotSpacing')
- Variable
slotY- Value
data('Board Layout', layout, 'boardTop')
- Variable
slotY- Operator
-=- Value
floor(slot / 3) * data('Board Layout', layout, 'slotSpacing')
- x
slotX- y
slotY
1.6.3 Show Goal Tile
From one Goal Cell’s point of view, the job is short. It knows its own slot. When it’s created, it asks Slot Position where that Slot sits in the goalPicture layout, and goes there. Next it asks Tile In Slot which Tile the Goal has in that Slot.
If the Goal has a Tile in that Slot, the cell writes the Tile’s number into its own label, as words. That’s text(goalTile.value). If it’s the Blank, the cell writes nothing. It tints its picture a darker cream instead.
Its Set Position counts in screen pixels from the top-left corner, as Screen Offset does, so its Position Relative to list says Screen. World is where the list starts.
Type goalPicture into the layout box bare, the way the card shows it. The card always shows which boxes want quote marks, so step 7’s color keeps its quotes. Values, quote marks and all on the Making page says why the same box can differ from one Logic to the next.
It’s your first Logic Component. A Logic Component card on the Making page shows how to make one. Its Data Structures card gets Goal Slot, from Existing Data Structures, so it reads its slot as self.goalSlot.slot. Events: the When bars shows its Create Event. Its Actions go in the way Slot Position’s did. This time the line runs down from the Event’s Mode block, where Start was. The Else is in If, Else, Repeat and While.
Shows one Slot of the Goal in the Goal Picture. Each Goal Cell placement sets the Slot it shows (Goal Slot). When the Goal Cell is created it moves to that Slot of the Goal Picture (Slot Position with the Board Layout row goalPicture) and shows the Tile the Goal (Puzzle Settings / goalBoard) has there; the Blank's cell shows no number and is drawn darker.
Any Objectself.goalSlot- Action Name
spot- slot
self.goalSlot.slot- layout
goalPicture
- Position Relative To
Screen- X
spot.x- Y
spot.y
- Action Name
goalTile- board
data('Puzzle Settings', 'puzzle', 'goalBoard')- slot
self.goalSlot.slot
goalTile.value > 0- Component Value
self.goalSlot.label- Value
text(goalTile.value)
- Value
'#d5c6a7'
The Goal Cell is a small Tile, made the same way, with its label where a Tile shows its number. Attach Show Goal Tile, and its Goal Slot arrives From Logic. It has no UI Interaction, because nobody clicks the Goal. The Goal Label is the word Goal above the cells, made like the Title.
Window / UIUIX 64, Y 64{label}32Semibold#233947CenterVector-1UI BackgroundX 64, Y 64#E8D9B9Show Goal TileGoal SlotWindow / UIUIGoal21Semibold#233947CenterVectorPlace the Goal Label at 766 and -227. Next, place the nine Goal Cells from PLACE THESE, at the foot of the Set up card, each with its own Slot, 0 to 8, and its Tint, #E8D9B9.
Run the game. On the parchment card, under Goal, you see 1 2 3, 4 5 6, 7 8, and a darker empty cell. Every one of those numbers came out of goalBoard, the Goal in Puzzle Settings.
The parchment card knows where the Tiles belong.
1.7 Puzzle Rules
Now the puzzle gets a keeper.
Puzzle Rules is an Empty Object, with no picture and no words. The whole puzzle lives on it. That means the Board State, the Moves and, from Chapter 2, the search. The Tiles only ask. Puzzle Rules decides.
1.7.1 Start Board
When the Scene starts, Start Board copies startBoard from Puzzle Settings into $boardState. That’s its whole job in this chapter: it writes the puzzle down. It’s also the first piece to run. A Scene Start runs before the Tiles are created, so the Board State is waiting by the time each Tile appears.
Make Start Board, but give it no Event yet. The three Global Variables come first. One holds the Board State, one the Tile you chose last, and one the words under the Goal. On Start Board’s canvas, press + on the Globals card and choose New Global… for each one in your Set up card’s GLOBAL VARIABLES. Leave off the $: $boardState goes in as boardState. The last one, $statusLine, is Text and starts empty. Clear its Default box.
After that come its Scene Start and its one Action.
Sets up the Board State when the puzzle opens: the Start Board from Puzzle Settings.
Any Object- Variable
$boardState- Value
data('Puzzle Settings', 'puzzle', 'startBoard')
Make Puzzle Rules, an Empty Object, and attach Start Board to it. Its card names three more Logic Components, and each one comes later in the chapter. Its Shared Variable comes with the last of them.
Puzzle RulesPlace Puzzle Rules from PLACE THESE. It stands in the world, not on the screen, so its 0 and 21.25 go into World Position. That’s the top-left corner of the screen, in the world’s meters. With no picture, it never shows. But Logic only runs on an Object the Scene has placed, so it has to be there.
1.7.2 Slot Of Tile
Start Board wrote the puzzle down, and now each Tile has to find itself in it. Slot Of Tile asks Tile In Slot’s question the other way round. Where is this Tile?
It looks at every Slot in reading order and asks Tile In Slot what’s there. When the answer is the Tile it wants, it keeps that Slot. A Repeat does the looking. It runs nine times, once for each Slot. If, Else, Repeat and While on the Making page shows how to fill one.
Inside a Repeat, local.index counts the times round, starting at 0. The first time round it’s 0, so Slot Of Tile reads Slot 0, then Slot 1, and on up to Slot 8. So local.index is the Slot.
A Declare Variable makes slot, starting at -1, no Slot at all, and that’s the answer if no Slot holds the Tile. Ask it for Tile 0, and it finds where the Blank is. Hand Moves will need that.
On its card, slot names two things. The Declared slot keeps the answer, and the Return gives it back. In step 3, slot is Tile In Slot’s own Parameter, and local.index fills it.
Where one Tile is in a Board State: the Slot (0 to 8) that holds it. Tile 0 is the Blank.
- Name
slot- Value
-1
9times- Action Name
digit- board
board- slot
local.index
digit.value == tile- Variable
slot- Value
local.index
- Value
slot
1.7.3 Slide To Slot
Slide To Slot is the Tile’s own Logic, and it has three moments: the jump, the slide and the landing. You’ll build all three here, though only the jump does anything yet.
The jump comes when the Tile is created. It asks Slot Of Tile where its own number is in $boardState. Slot Position says where that Slot sits on the Board, and Set Position puts the Tile there. Last, it remembers that Slot as shownSlot, the Slot it’s shown in.
Fill its left cards before any Event. On Data Structures, Numbered Tile is the one you made, so the Tile reads its own number as self.numberedTile.number. Slide To Slot Data is new. Choose New Data Structure for it, and Myth makes it, names it after the Logic and opens it. Its one field, shownSlot, is on its card below. That’s where each Tile keeps the Slot it’s shown in: self.slideToSlotData.shownSlot.
Shared Variables come next. One is puzzleRules, the Object a Tile reports to. The other is slideSeconds, how long a slide takes: 0.22 seconds, a quick glide.
What each Tile remembers: shownSlot, the Slot it is drawn in (-1 before the first Board is shown), so it slides only when its Slot changes.
Keeps this Tile on the Slot the Board State gives it. It jumps there when it is created. When the Board State moves it, it slides there in a straight line at an even speed, taking slideSeconds, lands exactly on the Slot, and tells Puzzle Rules that the slide is over.
Any Objectself.numberedTileself.slideToSlotData- Action Name
startSlot- board
$boardState- tile
self.numberedTile.number
- Action Name
startPlace- slot
startSlot.value- layout
board
- Position Relative To
Screen- X
startPlace.x- Y
startPlace.y
- Component Value
self.slideToSlotData.shownSlot- Value
startSlot.value
The slide waits for a message, boardChanged, which every Tile hears after a Move. Each Tile asks where it is now. Only the Tile that moved gets an answer different from its shownSlot, and the If lets only that one through. The other seven stay put.
Two Tween Properties make the slide, one for X and one for Y. Both take slideSeconds at an even speed, so they start together and arrive together, and the Tile travels in a straight line. On a Screen UI Object, the X and Y in the Property list are its place on the screen, in the same pixels as Screen Offset. A timer named slide is started too. It rings once, when the slide should be over.
Nothing sends boardChanged yet, though in the next part Hand Moves will.
- Action Name
mySlot- board
$boardState- tile
self.numberedTile.number
mySlot.value != self.slideToSlotData.shownSlot- Component Value
self.slideToSlotData.shownSlot- Value
mySlot.value
- Action Name
place- slot
mySlot.value- layout
board
- Value
self.transform.position.x- Target
place.x- Duration
@self.slideSeconds
- Value
self.transform.position.y- Target
place.y- Duration
@self.slideSeconds
- Timer Name
slide- Repeat Every (s)
@self.slideSeconds- Ring Once
Yes
The landing comes when the timer rings. Control Tween ends the glide, and Set Position puts the Tile exactly on its Slot, so it never stops a hair off. Last, the Tile tells Puzzle Rules the slide is over: slideFinished.
- Action Name
restingPlace- slot
self.slideToSlotData.shownSlot- layout
board
- Position Relative To
Screen- X
restingPlace.x- Y
restingPlace.y
- Applies To
@self.puzzleRules- Custom Event
slideFinished
Open the Tile, switch the list to Logic, and attach Slide To Slot. Now its puzzleRules needs an Object. Switch back to Components, and look under Variables in the Tile’s Properties. There’s puzzleRules, marked From Logic. Pick Puzzle Rules in its Value list.
Run the game. The Tiles stand exactly where they stood. That’s right: you placed each one on its Slot, so it jumps to where it already is.
To see the jump, put Tile 5 in the wrong place. Select it in the Scene and type 337 and -410 into its Screen Offset, the middle Slot, where the Blank is. Run the game. Tile 5 is back in the top-left corner, and the middle is empty again. The Board State put it there, not the Scene. Close the game, and type Tile 5’s own X and Y back in: 187 and -260.
Your Tiles answer to the Board State now, and they’re waiting to hear that it changed.
1.8 A Move
Now the Tiles learn to move.
Click Tile 4. In that instant, before anything moves, the game decides whether Tile 4 is beside the Blank. It is, right above it. So the Move is made in the Board State first, and only then does Tile 4 glide down to catch up.
Here is the whole trip, in order. The click reaches the Tile, and the Tile asks Puzzle Rules. Puzzle Rules checks, makes the Move and tells every Tile. Tile 4 slides. When it lands, it tells Puzzle Rules, and Puzzle Rules listens for the next choice.
1.8.1 Slot Distance
Is a Tile beside the Blank? Slot Distance counts how many Moves apart two Slots are: the rows between them plus the columns between them. A Tile never moves on a diagonal, so that sum is the count. Side by side, or one above the other, comes to 1.
A row is floor(slot / 3) and a column is slot % 3, as in Slot Position. The abs() around each difference turns it into a distance, so it never comes out below 0.
In Chapter 2, the search calls Slot Distance for every Tile of a Board, to guess how far that Board is from the Goal.
How many Moves apart two Slots are: the rows between them plus the columns between them, since a Tile never moves diagonally. Slots side by side, or one above the other, are 1 apart.
- Name
rowsApart- Value
0
- Name
columnsApart- Value
0
- Variable
rowsApart- Value
abs(floor(fromSlot / 3) - floor(toSlot / 3))
- Variable
columnsApart- Value
abs(fromSlot % 3 - toSlot % 3)
- Value
rowsApart + columnsApart
1.8.2 Board After Move
Board After Move makes a Move on the slip. It hands back the Board State after the Tile in fromSlot slides into the Blank at toSlot.
It looks like a long formula, but it only moves one digit. The Blank is a 0, so the Tile’s digit has to appear at toSlot and vanish from fromSlot. Each Slot has its own place in the number. It’s the pow(10, 8 - slot) that Tile In Slot divides by. Adding the digit at toSlot’s place and taking it away at fromSlot’s does both at once.
Take Tile 4 sliding down from Slot 1 into the Blank at Slot 4. Slot 4’s place is ten thousand, and Slot 1’s is ten million, as Tile In Slot counted. So the Board State gains four ten-thousands and loses four ten-millions. The digits of 542703816 become 5 0 2 7 4 3 8 1 6. The 4 and the 0 have traded places.
First it asks Tile In Slot which Tile is in fromSlot, and names the answer moving. So moving.value is the Tile’s number.
On its card, board is the Board before the Move. Step 1 passes it on to Tile In Slot, whose own Parameter happens to be named board too. The Return starts from it. Its Value is the Board after the Move.
In Chapter 2, the search calls Board After Move for every Board one Move away.
The Board State after the Tile in fromSlot slides into the Blank at toSlot.
- Action Name
moving- board
board- slot
fromSlot
- Value
board + moving.value * (pow(10, 8 - toSlot) - pow(10, 8 - fromSlot))
1.8.3 Choose Tile
Choose Tile is how a Tile asks. A click calls it, and so will a key, so the two can never behave differently.
It has a small problem to solve. A Custom Event is a bell: it rings, but it can’t say who rang it. So Choose Tile writes the chosen number into $chosenTile first, and only then rings tileChosen, for Puzzle Rules alone.
Its puzzleRules is an Object Parameter. A Function card shows how to make one: Nominal, Puzzle Rules. There’s no RETURN TYPE on its card, because Choose Tile only rings a bell and gives nothing back.
Tells Puzzle Rules which Tile the player chose, by click, tap, or key. Puzzle Rules decides whether it moves.
- Variable
$chosenTile- Value
tile
- Applies To
puzzleRules- Custom Event
tileChosen
1.8.4 Hand Moves
Hand Moves is where Puzzle Rules decides. It hears tileChosen and answers in one of two ways. Each way is a Mode, with its own name and its own Actions.
Ready is the way it starts. It asks Slot Of Tile twice: where the chosen Tile is, chosenSlot, and where the Blank is, blankSlot, by asking for Tile 0. Slot Distance says how far apart they are, and if the answer is 1, the Move is real.
What follows happens in this order. Board After Move gives the new Board, and $boardState takes it. Hand Moves switches On Tile Chosen to While Sliding. Last, it rings boardChanged for everyone.
The Board State changes before anything moves on the screen. Everything that hears boardChanged reads the new Board, the sliding Tile included.
Build it in this order. Make the On Tile Chosen Event. Rename its Mode Ready, and add a second one, While Sliding. Make On Slide Finished. Switch Mode picks the Event and the Mode by name, so both Modes have to exist before it does. Modes on the Making page shows each step. When the card is done, attach Hand Moves to Puzzle Rules.
Makes each Move on the Board State, one at a time. When a Tile beside the Blank is chosen (by click, tap, or key), the Move is stored and every Tile is told (boardChanged); while that Tile slides, other choices are ignored.
Any Object- Action Name
chosenSlot- board
$boardState- tile
$chosenTile
- Action Name
blankSlot- board
$boardState- tile
0
- Action Name
apart- fromSlot
chosenSlot.value- toSlot
blankSlot.value
apart.value == 1- Action Name
afterMove- board
$boardState- fromSlot
chosenSlot.value- toSlot
blankSlot.value
- Variable
$boardState- Value
afterMove.value
- Event
On Tile Chosen- Mode
While Sliding
- Custom Event
boardChanged
Remember boardChanged, waiting in Slide To Slot? Hand Moves sends it in step 8, the last step of Ready.
While Sliding has no Actions at all. While it’s the one that answers, a choice does nothing, so two Tiles never move at once. When the sliding Tile lands, it sends slideFinished to Puzzle Rules. On Slide Finished switches On Tile Chosen back to Ready, so Ready answers the next choice.
- Event
On Tile Chosen- Mode
Ready
1.8.5 Click To Choose
The last piece of the chain is the click itself. When you click or tap a Tile, its UI Activated Event runs, and Click To Choose calls Choose Tile with this Tile’s own number. The card’s heading, On Hud Activated, is the name Myth gives that Event by itself.
Its left cards hold two things you’ve met in Slide To Slot: Numbered Tile on Data Structures, from Existing Data Structures, and puzzleRules on Shared Variables.
Clicking or tapping this Tile chooses it. Puzzle Rules decides whether it moves.
Any Objectself.numberedTile- puzzleRules
@self.puzzleRules- tile
self.numberedTile.number
Attach Click To Choose to the Tile, beside Slide To Slot. There’s nothing new to pick. Its puzzleRules has the same name as Slide To Slot’s, so the Tile holds only one, already set to Puzzle Rules.
Run the game and click Tile 5, and nothing happens. Click Tile 4. It glides down in 0.22 seconds and lands square. Now click Tile 5 again. With the Blank beside it, it slides across. Your Tiles move.
Every Move goes through Puzzle Rules, and the Tiles follow.
1.9 Solved
Now the parchment card gets its word.
Under the Goal picture is room for one line of words. In this chapter it says one word, Solved, and only when the Tiles match the Goal.
The words live in a table, Messages, with one row for each thing the game can say. Today it has one row, solved, and Chapter 2 adds more.
SolvedIts Messages Entry has one Text field, words. Clear its Value box, as you did for Goal Slot’s label, because it starts empty.
One row of the "Messages" Data Table.
1.9.1 Check Goal
Check Goal hears boardChanged too. After every Move, it compares two numbers, $boardState and goalBoard. Equal, and $statusLine takes the solved row’s words. Not equal, and it’s emptied with "", the card’s word with no letters in it.
The Board State changes first, so Solved appears as the last Tile starts to slide, not when it lands.
Check Goal is the only piece of the game that ever says Solved, in this chapter and every one after.
Says "Solved" on the Status Line when a Move makes the Goal, as its Tile begins to slide. After any other Move the Status Line is empty.
Any Object$boardState == data('Puzzle Settings', 'puzzle', 'goalBoard')- Variable
$statusLine- Value
data('Messages', 'solved', 'words')
- Variable
$statusLine- Value
""
Attach Check Goal to Puzzle Rules.
The Status Line shows $statusLine in small slate letters. Make it like the Goal Label, with {$statusLine} as its Text, braces and all.
Window / UIUI{$statusLine}18Semibold#233947CenterVectorPlace it at 766 and -604, low on the parchment card. Run the game and solve the puzzle. Play it! below has a way through, if you’d like one.
1.10 Keys 1 To 8
Last come the keys.
Each key is a Command, a name your Logic uses, joined to a key on the keyboard. Make the eight from COMMANDS on your Set up card. They’re Slide Tile 1 to Slide Tile 8, each a Button, each joined to its own number key. The Set up card passage on the Making page shows the Input Manager.
1.10.1 Tile Keys
Tile Keys has eight Events, one for each Command. Each one calls Choose Tile with its own Tile’s number, so a key does what a click does. A Command Pressed Event names its Command in the Event itself, so every key gets an Event of its own.
It’s Click To Choose eight times over. This card is long only because it says the same thing eight ways.
The card’s headings read When Tile1 Is Pressed and so on. Myth gives those names by itself, from each Event’s Command, so you never type one. Its Shared Variables card gets puzzleRules, the same as Click To Choose’s.
Keys 1 to 8 choose that Tile, the same as clicking it. A Command Event picks its Command in the Event itself, so each key has its own Event.
Any Object- puzzleRules
@self.puzzleRules- tile
1
- puzzleRules
@self.puzzleRules- tile
2
- puzzleRules
@self.puzzleRules- tile
3
- puzzleRules
@self.puzzleRules- tile
4
- puzzleRules
@self.puzzleRules- tile
5
- puzzleRules
@self.puzzleRules- tile
6
- puzzleRules
@self.puzzleRules- tile
7
- puzzleRules
@self.puzzleRules- tile
8
Attach Tile Keys to Puzzle Rules. Its puzzleRules now shows under Puzzle Rules’ own Variables, and it points at Puzzle Rules itself, so pick Puzzle Rules in its Value list. Run the game and press 4. Tile 4 slides down, the same as a click.
Here is what to watch for, one thing at a time.
- The worktable fills the window. The plate at the top reads 8-puzzle (A*), and under it, Slide tiles into order.
- Eight cream Tiles sit on the velvet: 5 4 2 across the top, then 7, the Blank and 3, then 8 1 6.
- The parchment card shows the Goal: 1 2 3, 4 5 6, 7 8, and a darker empty cell. The line under it is empty.
- Click Tile 5. Nothing moves, because it isn’t beside the Blank.
- Click Tile 4. It glides straight down at an even speed, takes 0.22 seconds, and lands square in its Slot.
- Press 4. Tile 4 slides back up, the same as a click.
- Press 4 and then 5, quickly. Only Tile 4 moves. While a Tile slides, other choices do nothing.
- Start the game again for a fresh puzzle. Press 1, 8, 7, 5, 4, 1, 5, 4, 1, 2, 3 and 6, one at a time, each after the last slide ends.
- As Tile 6 starts its slide, Solved appears under the Goal. Twelve Moves.
Start Board writes the puzzle down as one number. Each Tile finds its Slot in it, and each Goal Cell finds its number in the Goal. A click only asks. Hand Moves decides, changes the number and rings boardChanged. The Tile that moved slides to catch up, and Check Goal compares two numbers.
Underneath all of it is one idea. The puzzle is stored once, as the Board State, and everything you see only shows it. The Tiles never decide where they are.
That’s what makes a search possible, because a whole Board fits in nine digits. So the search in Chapter 2 can write Boards down, compare them and make Moves on them, all without touching a Tile.
1.11 If It Didn’t Work
Something may be a little off the first time. That’s part of building, and each fix shows you where something lives. Run the game, watch what it does, and think it through one piece at a time.
The window is plain blue, with no worktable? Look in Puzzle Table for the Observatory Background’s placement, at 500 and -425, and at its Sprite’s picture, Observatory Worktable.
A Tile shows 0? Its placement’s Number is still 0. Select it, and type its number under Values, in its Data Structure part.
A 0 in the Goal’s dark empty cell, or under the Goal? Some Text still holds the editor’s 0. Look at Goal Slot’s label, whose Value box should be clear, and at $statusLine, whose Default box should be clear.
All nine Goal Cells are the same color, with no numbers? That means Show Goal Tile never ran. Is it attached to the Goal Cell? If it is, open it and look for a block standing apart from the line, with no arrow into it. Right-click it and choose Connect to sequence to join it.
The Goal Cells pile up in one spot, or show their numbers in the wrong places? Open Slot Position and look for a block standing apart. Join it with Connect to sequence. After that, look at each placement’s Slot, 0 to 8. Last, step 2 of Show Goal Tile should have its Position Relative to on Screen.
Clicking a Tile does nothing at all? Follow the chain from the click, one link at a time, starting at the Tile. Does it still have its UI Interaction? Without it, a click never reaches the Tile at all, so that’s the first link. Is Click To Choose on it? Is Puzzle Rules in the Scene, with Hand Moves on it? Logic only runs on an Object the Scene has placed, so Puzzle Rules has to be there. Is Ready the Starting Mode of On Tile Chosen? And is tileChosen spelled the same, letter for letter, in Choose Tile and in Hand Moves?
A Tile moves once, and then nothing moves again? Perhaps slideFinished never arrived, so Hand Moves is still in While Sliding. Look at On the Slide Timer, the last Event of Slide To Slot, whose timer name is slide, the same as the Timer Name in Start Recurring Timer. Its last step sends slideFinished to @self.puzzleRules. Does the Tile’s puzzleRules, under Variables, say Puzzle Rules? After that, look at On Slide Finished in Hand Moves, which switches back to Ready.
No Tween in the Action List? Advanced Mode is off. Turn it on from the Settings menu, and the Timeline’s Actions appear, Tween and Control Tween among them.
A Tile slides to the wrong Slot? Look at Slot Position, where the fourth step adds, with +=, and the sixth takes away, with -=.
A Tile that isn’t beside the Blank moves anyway? Look at step 4 of Hand Moves, whose If reads apart.value == 1.
Solved never appears? Look for Check Goal on Puzzle Rules, and at the Status Line’s Text, {$statusLine}. After that, look at the solved row of Messages. Its words are Solved.
Clicks work, but the keys don’t? Look at each Command’s key under Keybindings, and for Tile Keys on Puzzle Rules.
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 at the top of this chapter is its finished project.
Make a puzzle of your own. Open Puzzle Settings and change startBoard in its one row, puzzle. That’s the cell Start Board reads.
Any Board you reach by sliding Tiles away from the Goal can be solved, because every Move can be undone. So start from 123456780, slide a few Tiles in your head or on paper, and write down where you end up, row by row, with 0 for the Blank. One Move away is 123456708, with Tile 8 one Slot to the right. Run the game, and your Tiles start where you said.
Before Chapter 2, put 542703816 back. The search there starts from that puzzle, and its numbers are about it.
Eight Tiles slide where your hand sends them, and the card knows when they’re home. In Chapter 2, something else starts working the puzzle.
