Build a GameCreating Crystal Cascade

Appendix A — Logic Reference

Every Logic Component and Function in Crystal Cascade, as it is in the finished game. Each entry stands on its own: read what it does, see what it needs, and build it from its card into your own game. A card’s Shared Variables and Per Instance Variables are the values you can change. A Shared Variable holds one value for the whole Object, under Variables in its Properties. A Per Instance Variable holds one for each placement in the Scene.

A.1 Build The Well

Built in Chapter 1, Falling Crystals.

Logic ComponentBuild The WellAttach to: Glass Well

When a game begins, empties the Well table (Empty The Well) and makes a Well Cell on every visible cell of the well, row by row from the bottom.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
wellCellObjectConstantNone
OBJECT KINDS
wellCellWell Cell
When the Scene Starts
WhenScene Start
1Empty The WellFunction
2Repeatdata('Well Layout', 0, 'visibleRows')times
Each time
3Declare Variable
Name
cellRow
Value
local.index
4Repeatdata('Well Layout', 0, 'columns')times
Each time
5Cell MiddleFunction
Action Name
newCellMiddle
column
local.index
row
cellRow
6Create Instance
Object to Create
@self.wellCell
X
newCellMiddle.x
Y
newCellMiddle.y

A.2 Cell At (Function)

Built in Chapter 1, Falling Crystals.

FunctionCell At

Answers which well cell is under a point in the world (meters): its column from the left and row from the bottom (Well Layout).

PARAMETERS
NameTypeStarts at
xNumber0
yNumber0
RETURN TYPECell At Result (a Data Structure)
ACTIONS
1Declare Variable
Name
cellSize
Value
0
2Declare Variable
Name
column
Value
0
3Declare Variable
Name
row
Value
0
4Change Variable
Variable
cellSize
Value
data('Well Layout', 0, 'cellSize')
5Change Variable
Variable
column
Value
floor((x - data('Well Layout', 0, 'left')) / cellSize)
6Change Variable
Variable
row
Value
floor((y - data('Well Layout', 0, 'bottom')) / cellSize)
7Return
column
column
row
row

A.3 Cell Middle (Function)

Built in Chapter 1, Falling Crystals.

FunctionCell Middle

Answers where the middle of a well cell is in the world (meters), from its column and row (Well Layout).

PARAMETERS
NameTypeStarts at
columnNumber0
rowNumber0
RETURN TYPECell Middle Result (a Data Structure)
ACTIONS
1Declare Variable
Name
cellSize
Value
0
2Declare Variable
Name
x
Value
0
3Declare Variable
Name
y
Value
0
4Change Variable
Variable
cellSize
Value
data('Well Layout', 0, 'cellSize')
5Change Variable
Variable
x
Value
data('Well Layout', 0, 'left') + (column + 0.5) * cellSize
6Change Variable
Variable
y
Value
data('Well Layout', 0, 'bottom') + (row + 0.5) * cellSize
7Return
x
x
y
y

A.4 Crystal Cell (Function)

Built in Chapter 1, Falling Crystals.

FunctionCrystal Cell

Answers where crystal 1-4 of a piece of this kind and rotation sits in its 4 x 4 box: its column and row from the box's bottom-left corner (Piece Shapes).

PARAMETERS
NameTypeStarts at
kindNumber0
rotationNumber0
crystalNumber1
RETURN TYPECrystal Cell Result (a Data Structure)
ACTIONS
1Declare Variable
Name
shapeRow
Value
0
2Declare Variable
Name
column
Value
0
3Declare Variable
Name
row
Value
0
4Declare Variable
Name
rotationColumn
Value
0
5Declare Variable
Name
rotationRow
Value
0
6Declare Variable
Name
rotatedColumn
Value
0
7Change Variable
Variable
shapeRow
Value
(kind - 1) * 4 + crystal - 1
8Change Variable
Variable
column
Value
data('Piece Shapes', shapeRow, 'column')
9Change Variable
Variable
row
Value
data('Piece Shapes', shapeRow, 'row')
10Change Variable
Variable
rotationColumn
Value
data('Piece Kinds', kind - 1, 'rotationColumn')
11Change Variable
Variable
rotationRow
Value
data('Piece Kinds', kind - 1, 'rotationRow')
12Repeatrotationtimes
Each time
13Change Variable
Variable
rotatedColumn
Value
rotationColumn + (row - rotationRow)
14Change Variable
Variable
row
Value
rotationRow - (column - rotationColumn)
15Change Variable
Variable
column
Value
rotatedColumn
16Return
column
column
row
row

A.5 Empty The Well (Function)

Built in Chapter 1, Falling Crystals.

FunctionEmpty The Well

Makes the Well table one empty row per cell of the well (Well Layout: columns x rows), or empties the rows it already has.

ACTIONS
1Repeatdata('Well Layout', 0, 'columns') * data('Well Layout', 0, 'rows')times
Each time
2Control Data Row
Action Name
addedRow
Table
Well
Row
blockLocal("index")
Values
{"kind":"0","isClearing":"false"}

A.6 Lock Piece

Built in Chapter 1, Falling Crystals.

Logic ComponentLock PieceAttach to: Falling Piece

Writes the falling piece's four crystals into the Well, takes the piece out of play, tells the well it locked and the Well Cells that crystals joined.

Attach toAny Object
DATA STRUCTURES
Pieceself.piece
SHARED VARIABLES
NameTypeKindStarting Value
rulesObjectConstantNone
OBJECT KINDS
rulesGame Rules
On Lock Piece
WhenlockPieceCustom Event
1Declare Variable
Name
lockedKind
Value
0
2Stop Recurring Timer
Timer Name
"gravity"
3Stop Recurring Timer
Timer Name
"lockDelay"
4Change Variable
Variable
lockedKind
Value
self.piece.kind
5Change Component Value
Component Value
self.piece.crystalsInView
Value
0
6Repeat4times
Each time
7Crystal CellFunction
Action Name
lockedCrystal
kind
self.piece.kind
rotation
self.piece.rotation
crystal
local.index + 1
8Well Cell IndexFunction
Action Name
lockedCell
column
self.piece.column + lockedCrystal.column
row
self.piece.row + lockedCrystal.row
9Declare Variable
Name
cellIndex
Value
lockedCell.value
10Set Data Cell
Table
Well
Row
cellIndex
Column
"kind"
Value
lockedKind
11If(self.piece.row + lockedCrystal.row) < data('Well Layout', 0, 'visibleRows')
Then
12Change Component Value
Component Value
self.piece.crystalsInView
Value
self.piece.crystalsInView + 1
13Control Sound
Sound
Lock Click
14Set Logic State
Logic Component
Piece Gravity
State
Disable
15Set Logic State
Logic Component
Move Piece
State
Disable
16Set Logic State
Logic Component
Rotate Piece
State
Disable
17Set Logic State
Logic Component
Hard Drop Piece
State
Disable
18Set Logic State
Logic Component
Hold Piece
State
Disable
19Change Component Value
Component Value
self.piece.hasHeld
Value
false
20Trigger Custom Event
Custom Event
holdChanged
21Trigger Custom Event on Object
Applies to
@self.rules
Custom Event
piecePlaced
22Trigger Custom Event
Custom Event
pieceLocked
23Trigger Custom Event
Custom Event
crystalsLocked

A.7 Move Piece

Built in Chapter 1, Falling Crystals.

Logic ComponentMove PieceAttach to: Falling Piece

Moves the falling piece one column in its moveDirection when asked (moveOnce, from Read The Move Keys), if the piece fits there.

Attach toAny Object
DATA STRUCTURES
Pieceself.piece
On Move Once
WhenmoveOnceCustom Event
1Piece Fits HereFunction
Action Name
roomBeside
piece
self
columnShift
self.piece.moveDirection
rowShift
0
2IfroomBeside.value == true
Then
3Change Component Value
Component Value
self.piece.column
Value
self.piece.column + self.piece.moveDirection
4Change Component Value
Component Value
self.piece.lastMoveWasRotation
Value
false
5Control Sound
Sound
Move Tick
6Find Landing RowFunction
piece
self
7Trigger Custom Event
Custom Event
pieceMoved
8Trigger Custom Event on Object
Custom Event
pieceShifted

A.8 Piece Fits (Function)

Built in Chapter 1, Falling Crystals.

FunctionPiece Fits

Answers whether a piece of this kind and rotation fits with its 4 x 4 box's bottom-left corner at this cell: each of its four crystals on a free cell of the well (Well Cell Filled).

PARAMETERS
NameTypeStarts at
kindNumber0
rotationNumber0
columnNumber0
rowNumber0
RETURN TYPEBoolean
ACTIONS
1Declare Variable
Type
Boolean
Name
fits
Value
true
2Declare Variable
Name
crystalColumn
Value
0
3Declare Variable
Name
crystalRow
Value
0
4Change Variable
Variable
fits
Value
true
5Repeat4times
Each time
6Crystal CellFunction
Action Name
testedCrystal
kind
kind
rotation
rotation
crystal
local.index + 1
7Change Variable
Variable
crystalColumn
Value
column + testedCrystal.column
8Change Variable
Variable
crystalRow
Value
row + testedCrystal.row
9Well Cell FilledFunction
Action Name
testedCell
column
crystalColumn
row
crystalRow
10IftestedCell.value == true
Then
11Change Variable
Variable
fits
Value
false
12Return
Value
fits

A.9 Piece Fits Here (Function)

Built in Chapter 1, Falling Crystals.

FunctionPiece Fits Here

Answers whether the falling piece, as it is turned now, would fit columnShift columns to the right and rowShift rows up from where it is (Piece Fits); 0 and 0 asks about where it is.

PARAMETERS
NameTypeStarts at
pieceObjectStructural
Required Components
Slot Namepiece
Component TypeData Structure
Required SchemaPiece
columnShiftNumber0
rowShiftNumber0
RETURN TYPEBoolean
ACTIONS
1Declare Variable
Type
Boolean
Name
fits
Value
true
2Piece FitsFunction
Action Name
shiftedPiece
kind
piece.piece.kind
rotation
piece.piece.rotation
column
piece.piece.column + columnShift
row
piece.piece.row + rowShift
3Change Variable
Variable
fits
Value
shiftedPiece.value
4Return
Value
fits

A.10 Piece Gravity

Built in Chapter 1, Falling Crystals.

Logic ComponentPiece GravityAttach to: Falling Piece

Moves the falling piece down one row whenever the gravity timer comes due; when it cannot fall it rests, and locks after the lock delay.

Attach toAny Object
DATA STRUCTURES
Pieceself.piece
SHARED VARIABLES
NameTypeKindStarting Value
lockResetLimitNumberConstant15
curveStartSecondsNumberConstant0.8
curveStepSecondsNumberConstant0.007
On Spawn Piece
WhenspawnPieceCustom Event
1Ifdata('Modes', global('mode') - 1, 'fallSeconds') > 0
Then
2Change Component Value
Component Value
self.piece.fallSeconds
Value
data('Modes', global('mode') - 1, 'fallSeconds')
3Otherwise
4Declare Variable
Name
levelsUp
Value
global('currentLevel') - 1
5Change Component Value
Component Value
self.piece.fallSeconds
Value
pow(@self.curveStartSeconds - levelsUp * @self.curveStepSeconds, levelsUp)
6Start Recurring Timer
Timer Name
"gravity"
Repeat Every (s)
self.piece.fallSeconds
7Switch Mode
Event
On the Gravity Timer
Mode
Falling
8Change Component Value
Component Value
self.piece.lowestRow
Value
self.piece.row
9Change Component Value
Component Value
self.piece.lockResets
Value
0
10Change Component Value
Component Value
self.piece.hasTouchedDown
Value
false
11Change Component Value
Component Value
self.piece.isLockDelayOver
Value
false
On the Gravity Timer
WhenRecurring TimerTimer name: gravity
ModeFalling (Starting Mode)
1Piece Fits HereFunction
Action Name
roomBelowOnGravity
piece
self
columnShift
0
rowShift
-1
2IfroomBelowOnGravity.value == true
Then
3Change Component Value
Component Value
self.piece.row
Value
self.piece.row - 1
4Change Component Value
Component Value
self.piece.lastMoveWasRotation
Value
false
5Note Lowest RowFunction
piece
self
6Trigger Custom Event
Custom Event
pieceMoved
7Trigger Custom Event on Object
Custom Event
pieceFell
8Piece Fits HereFunction
Action Name
roomBelowAfterFall
piece
self
columnShift
0
rowShift
-1
9IfroomBelowAfterFall.value == false
Then
10Trigger Custom Event on Object
Custom Event
pieceLanded
11Otherwise
12Trigger Custom Event on Object
Custom Event
pieceLanded
On Piece Landed
WhenpieceLandedCustom Event
1Switch Mode
Event
On the Gravity Timer
Mode
Resting
2Ifself.piece.hasTouchedDown == false
Then
3Change Component Value
Component Value
self.piece.hasTouchedDown
Value
true
4Start Recurring Timer
Timer Name
"lockDelay"
Repeat Every (s)
self.piece.lockDelaySeconds
Ring Once
Yes
5Trigger Custom Event
Custom Event
lockDelayStarted
6Ifself.piece.isLockDelayOver == true
Then
7Trigger Custom Event on Object
Custom Event
lockPiece
On the Gravity Timer
WhenRecurring TimerTimer name: gravity
ModeResting
(no Actions)
On the Lock Delay Timer
WhenRecurring TimerTimer name: lockDelay
1Change Component Value
Component Value
self.piece.isLockDelayOver
Value
true
2Piece Fits HereFunction
Action Name
roomBelowAfterDelay
piece
self
columnShift
0
rowShift
-1
3IfroomBelowAfterDelay.value == true
Then
4Switch Mode
Event
On the Gravity Timer
Mode
Falling
5Return
6Trigger Custom Event on Object
Custom Event
lockPiece
On Piece Shifted
WhenpieceShiftedCustom Event
1Note Lowest RowFunction
piece
self
2Ifself.piece.hasTouchedDown == true
Then
3Ifself.piece.lockResets < @self.lockResetLimit
Then
4Change Component Value
Component Value
self.piece.lockResets
Value
self.piece.lockResets + 1
5Change Component Value
Component Value
self.piece.isLockDelayOver
Value
false
6Start Recurring Timer
Timer Name
"lockDelay"
Repeat Every (s)
self.piece.lockDelaySeconds
Ring Once
Yes
7Trigger Custom Event
Custom Event
lockDelayStarted
8Piece Fits HereFunction
Action Name
roomBelowAfterShift
piece
self
columnShift
0
rowShift
-1
9IfroomBelowAfterShift.value == true
Then
10Switch Mode
Event
On the Gravity Timer
Mode
Falling
11Otherwise
12Trigger Custom Event on Object
Custom Event
pieceLanded
On Game Over
WhengameOverCustom Event
1Set Logic State
Logic Component
Piece Gravity
State
Disable

A.11 Read The Move Keys

Built in Chapter 1, Falling Crystals.

Logic ComponentRead The Move KeysAttach to: Falling Piece

Hears Move Left and Move Right: keeps the piece's moveDirection (the key pressed last wins) and asks for one move (moveOnce) at a press and again and again while the key is held (auto-repeat). It stays on between pieces, so a key let go then is heard too.

Attach toAny Object
DATA STRUCTURES
Pieceself.piece
Read The Move Keys Dataself.readTheMoveKeysData
SHARED VARIABLES
NameTypeKindStarting Value
autoRepeatDelaySecondsNumberConstant0.15
autoRepeatSecondsNumberConstant0.03
When Move Left Is Pressed
WhenCommand PressedCommand: Move Left
1Change Component Value
Component Value
self.readTheMoveKeysData.isLeftHeld
Value
true
2Change Component Value
Component Value
self.piece.moveDirection
Value
-1
3Trigger Custom Event on Object
Custom Event
moveOnce
4Start Recurring Timer
Timer Name
"autoRepeat"
Repeat Every (s)
@self.autoRepeatSeconds
First Delay (s)
@self.autoRepeatDelaySeconds
When Move Right Is Pressed
WhenCommand PressedCommand: Move Right
1Change Component Value
Component Value
self.readTheMoveKeysData.isRightHeld
Value
true
2Change Component Value
Component Value
self.piece.moveDirection
Value
1
3Trigger Custom Event on Object
Custom Event
moveOnce
4Start Recurring Timer
Timer Name
"autoRepeat"
Repeat Every (s)
@self.autoRepeatSeconds
First Delay (s)
@self.autoRepeatDelaySeconds
When Move Left Is Released
WhenCommand ReleasedCommand: Move Left
1Change Component Value
Component Value
self.readTheMoveKeysData.isLeftHeld
Value
false
2Ifself.piece.moveDirection == (-1) && self.readTheMoveKeysData.isRightHeld == true
Then
3Change Component Value
Component Value
self.piece.moveDirection
Value
1
4Start Recurring Timer
Timer Name
"autoRepeat"
Repeat Every (s)
@self.autoRepeatSeconds
First Delay (s)
@self.autoRepeatDelaySeconds
5Otherwise
6Ifself.piece.moveDirection == (-1)
Then
7Change Component Value
Component Value
self.piece.moveDirection
Value
0
8Stop Recurring Timer
Timer Name
"autoRepeat"
When Move Right Is Released
WhenCommand ReleasedCommand: Move Right
1Change Component Value
Component Value
self.readTheMoveKeysData.isRightHeld
Value
false
2Ifself.piece.moveDirection == 1 && self.readTheMoveKeysData.isLeftHeld == true
Then
3Change Component Value
Component Value
self.piece.moveDirection
Value
-1
4Start Recurring Timer
Timer Name
"autoRepeat"
Repeat Every (s)
@self.autoRepeatSeconds
First Delay (s)
@self.autoRepeatDelaySeconds
5Otherwise
6Ifself.piece.moveDirection == 1
Then
7Change Component Value
Component Value
self.piece.moveDirection
Value
0
8Stop Recurring Timer
Timer Name
"autoRepeat"
On the Auto Repeat Timer
WhenRecurring TimerTimer name: autoRepeat
1Trigger Custom Event on Object
Custom Event
moveOnce
On Game Resumed
WhengameResumedCustom Event
1Change Component Value
Component Value
self.readTheMoveKeysData.isLeftHeld
Value
false
2Change Component Value
Component Value
self.readTheMoveKeysData.isRightHeld
Value
false
3Change Component Value
Component Value
self.piece.moveDirection
Value
0
4Stop Recurring Timer
Timer Name
"autoRepeat"

A.12 Show Piece Crystal

Built in Chapter 1, Falling Crystals.

Logic ComponentShow Piece CrystalAttach to: Falling Crystal, Ghost Crystal

One crystal of the falling piece: whenever the piece moves, it goes to its cell (or, with showsLanding, to its cell in the landing row: the ghost) and shows the piece's color; it hides in the two hidden rows, and the piece's own crystals fade while it rests before locking.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
pieceObjectConstantNone
dimmedAlphaNumberConstant0.55
PER INSTANCE VARIABLES
NameTypeStarting Value
crystalNumber1
showsLandingBooleanNo
OBJECT KINDS
pieceFalling Piece
On Piece Moved
WhenpieceMovedCustom Event
1Control Tween
Which
Value
Value
self.transform.opacity
2Set Alpha
3Crystal CellFunction
Action Name
thisCrystal
kind
@self.piece.piece.kind
rotation
@self.piece.piece.rotation
crystal
self.crystal
4Declare Variable
Name
cellColumn
Value
@self.piece.piece.column + thisCrystal.column
5Declare Variable
Name
cellRow
Value
@self.piece.piece.row + thisCrystal.row
6Ifself.showsLanding == true
Then
7Change Variable
Variable
cellRow
Value
@self.piece.piece.landingRow + thisCrystal.row
8Cell MiddleFunction
Action Name
thisCellMiddle
column
cellColumn
row
cellRow
9Set Position
X
thisCellMiddle.x
Y
thisCellMiddle.y
10Set Frame
Frame
data('Piece Kinds', @self.piece.piece.kind - 1, 'frame')
11IfcellRow < data('Well Layout', 0, 'visibleRows')
Then
12Set Visible
Visible
Yes
13Otherwise
14Set Visible
Visible
No
On Lock Delay Started
WhenlockDelayStartedCustom Event
1Ifself.showsLanding == false
Then
2Piece Fits HereFunction
Action Name
roomBelowDimmingPiece
piece
@self.piece
columnShift
0
rowShift
-1
3IfroomBelowDimmingPiece.value == false
Then
4Tween
Value
self.transform.opacity
Target
@self.dimmedAlpha
Duration
@self.piece.piece.lockDelaySeconds
On Game Over
WhengameOverCustom Event
1Set Visible
Visible
No
When Created
WhenCreate
1Set Visible
Visible
No

A.13 Show Well Cell

Built in Chapter 1, Falling Crystals.

Logic ComponentShow Well CellAttach to: Well Cell

One cell of the well: it finds its cell from where it is placed, then shows the crystal stored there whenever the well changes; a crystal a lock just put there pops, and a crystal in a full line bursts into shards.

Attach toAny Object
DATA STRUCTURES
Show Well Cell Dataself.showWellCellData
SHARED VARIABLES
NameTypeKindStarting Value
popScaleNumberConstant1.22
popSecondsNumberConstant0.2
stoneDelaySecondsNumberConstant0.05
stoneRowSecondsNumberConstant0.035
When Created
WhenCreate
1Cell AtFunction
Action Name
myCell
x
self.transform.position.x
y
self.transform.position.y
2Well Cell IndexFunction
Action Name
thisCellIndex
column
myCell.column
row
myCell.row
3Change Component Value
Component Value
self.showWellCellData.cellIndex
Value
thisCellIndex.value
4Trigger Custom Event on Object
Custom Event
wellChanged
On Crystals Locked
WhencrystalsLockedCustom Event
1Ifself.showWellCellData.shownKind == 0 && data('Well', self.showWellCellData.cellIndex, 'kind') != 0
Then
2Set Scale
Horizontal Scale
@self.popScale
Vertical Scale
@self.popScale
3Tween
Value
self.transform.scale
Target
1
Duration
@self.popSeconds
Ease
Quad Out
4Burst Particles
Particles
Lock Glint
Z Index Offset
6
5Trigger Custom Event on Object
Custom Event
wellChanged
On Well Changed
WhenwellChangedCustom Event
1Ifdata('Well', self.showWellCellData.cellIndex, 'isClearing') == true && self.showWellCellData.isShowingShatter == false
Then
2Burst Particles
Particles
Crystal Shards
Z Index Offset
6
Tint
data('Piece Kinds', data('Well', self.showWellCellData.cellIndex, 'kind') - 1, 'color')
3Change Component Value
Component Value
self.showWellCellData.isShowingShatter
Value
data('Well', self.showWellCellData.cellIndex, 'isClearing')
4Change Component Value
Component Value
self.showWellCellData.shownKind
Value
data('Well', self.showWellCellData.cellIndex, 'kind')
5Ifself.showWellCellData.isShowingShatter == true
Then
6Set Frame
Frame
data('Crystal Frames', 0, 'shatter')
7Otherwise
8Set Frame
Frame
self.showWellCellData.shownKind
On Game Lost
WhengameLostCustom Event
1Declare Variable
Name
waitSeconds
Value
0
2Declare Variable
Name
rowFromBottom
Value
0
3Change Variable
Variable
rowFromBottom
Value
floor(self.showWellCellData.cellIndex / data('Well Layout', 0, 'columns'))
4Change Variable
Variable
waitSeconds
Value
@self.stoneDelaySeconds + rowFromBottom * @self.stoneRowSeconds
5Start Recurring Timer
Timer Name
"turnToStone"
Repeat Every (s)
waitSeconds
Ring Once
Yes
On the Turn to Stone Timer
WhenRecurring TimerTimer name: turnToStone
1Ifself.showWellCellData.shownKind != 0
Then
2Set Frame
Frame
data('Crystal Frames', 0, 'stone')

A.14 Spawn Piece

Built in Chapter 1, Falling Crystals.

Logic ComponentSpawn PieceAttach to: Falling Piece

Puts a new piece at the top of the well: the next kind from the Queue (or the held piece, from Hold Piece), rotation up, its box in the hidden rows, then one row down into view if it fits.

Attach toAny Object
DATA STRUCTURES
Pieceself.piece
SHARED VARIABLES
NameTypeKindStarting Value
startColumnNumberConstant3
On Spawn Piece
WhenspawnPieceCustom Event
1Change Component Value
Component Value
self.piece.rotation
Value
0
2Change Component Value
Component Value
self.piece.lastMoveWasRotation
Value
false
3Change Component Value
Component Value
self.piece.lastKickTest
Value
0
4Change Component Value
Component Value
self.piece.column
Value
@self.startColumn
5Change Component Value
Component Value
self.piece.row
Value
data('Well Layout', 0, 'rows') - 4
6Piece Fits HereFunction
Action Name
roomForNewPiece
piece
self
columnShift
0
rowShift
0
7IfroomForNewPiece.value == true
Then
8Set Logic State
Logic Component
Hold Piece
9Set Logic State
Logic Component
Piece Gravity
10Set Logic State
Logic Component
Move Piece
11Set Logic State
Logic Component
Rotate Piece
12Set Logic State
Logic Component
Hard Drop Piece
13Piece Fits HereFunction
Action Name
roomBelowNewPiece
piece
self
columnShift
0
rowShift
-1
14IfroomBelowNewPiece.value == true
Then
15Change Component Value
Component Value
self.piece.row
Value
self.piece.row - 1
16Find Landing RowFunction
piece
self
17Trigger Custom Event
Custom Event
pieceMoved
18Otherwise
19Change Component Value
Component Value
self.piece.isBlocked
Value
true
20Trigger Custom Event
Custom Event
pieceBlocked
On Next Piece Due
WhennextPieceDueCustom Event
1Check Game State
Action Name
isPlaying
Game State
Playing
2IfisPlaying.value == true
Then
3Change Component Value
Component Value
self.piece.kind
Value
data('Queue', 0, 'piece')
4Trigger Custom Event
Custom Event
pieceDealt
5Trigger Custom Event on Object
Custom Event
spawnPiece
On Well Reset
WhenwellResetCustom Event
1Ifself.piece.isBlocked == true
Then
2Change Component Value
Component Value
self.piece.isBlocked
Value
false
3Trigger Custom Event on Object
Custom Event
spawnPiece

A.15 Well Cell Filled (Function)

Built in Chapter 1, Falling Crystals.

FunctionWell Cell Filled

Answers whether a cell is taken: outside the well's sides or below its floor counts as taken, above its top as free, otherwise a crystal there.

PARAMETERS
NameTypeStarts at
columnNumber0
rowNumber0
RETURN TYPEBoolean
ACTIONS
1Declare Variable
Type
Boolean
Name
isFilled
Value
false
2Change Variable
Variable
isFilled
Value
false
3Ifcolumn < 0 || column >= data('Well Layout', 0, 'columns') || row < 0
Then
4Change Variable
Variable
isFilled
Value
true
5Otherwise
6Well Cell IndexFunction
Action Name
testedCellIndex
column
column
row
row
7Ifrow < data('Well Layout', 0, 'rows') && data('Well', testedCellIndex.value, 'kind') != 0
Then
8Change Variable
Variable
isFilled
Value
true
9Return
Value
isFilled

A.16 Well Cell Index (Function)

Built in Chapter 1, Falling Crystals.

FunctionWell Cell Index

Answers which row of the Well table holds the well cell at this column and row (row * columns + column, Well Layout).

PARAMETERS
NameTypeStarts at
columnNumber0
rowNumber0
RETURN TYPENumber
ACTIONS
1Return
Value
row * data('Well Layout', 0, 'columns') + column

A.17 Fade Away

Built in Chapter 2, Rotating and Dropping.

Logic ComponentFade AwayAttach to: Drop Streak

A short-lived effect: it fades out over fadeSeconds and removes itself after removeSeconds.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
startAlphaNumberConstant0.95
fadeSecondsNumberConstant0.26
removeSecondsNumberConstant0.3
When Created
WhenCreate
1Set Alpha
Alpha
@self.startAlpha
2Tween
Value
self.transform.opacity
Target
0
Duration
@self.fadeSeconds
Ease
Quad in
3Start Recurring Timer
Timer Name
"remove"
Repeat Every (s)
@self.removeSeconds
Ring Once
Yes
On the Remove Timer
WhenRecurring TimerTimer name: remove
1Destroy Instance

A.18 Find Landing Row (Function)

Built in Chapter 2, Rotating and Dropping.

FunctionFind Landing Row

Works out the lowest row the falling piece's box can fall to, straight down from where it is, and keeps it in the Piece's landingRow.

PARAMETERS
NameTypeStarts at
pieceObjectStructural
Required Components
Slot Namepiece
Component TypeData Structure
Required SchemaPiece
ACTIONS
1Declare Variable
Type
Boolean
Name
canFall
Value
true
2Change Component Value
Component Value
piece.piece.landingRow
Value
piece.piece.row
3Change Variable
Variable
canFall
Value
true
4WhilecanFall == true
Each time
5Piece FitsFunction
Action Name
roomUnderLanding
kind
piece.piece.kind
rotation
piece.piece.rotation
column
piece.piece.column
row
piece.piece.landingRow - 1
6IfroomUnderLanding.value == true
Then
7Change Component Value
Component Value
piece.piece.landingRow
Value
piece.piece.landingRow - 1
8Otherwise
9Change Variable
Variable
canFall
Value
false

A.19 First Kick Row (Function)

Built in Chapter 2, Rotating and Dropping.

FunctionFirst Kick Row

Answers where the five kicks of a rotation start in the Kicks table, for a piece of this kind rotating by rotateBy from this rotation (its layout is in Kicks Layout).

PARAMETERS
NameTypeStarts at
kindNumber1
rotationNumber0
rotateByNumber1
RETURN TYPENumber
ACTIONS
1Declare Variable
Name
firstTestRow
Value
0
2IfrotateBy == 2
Then
3Change Variable
Variable
firstTestRow
Value
data('Kicks Layout', 0, 'firstHalfRotationRow')
4Change Variable
Variable
firstTestRow
Operator
+=
Value
rotation * data('Kicks Layout', 0, 'testsPerRotation')
5Otherwise
6Change Variable
Variable
firstTestRow
Value
data('Piece Kinds', kind - 1, 'firstKickRow')
7Change Variable
Variable
firstTestRow
Operator
+=
Value
rotation * 2 * data('Kicks Layout', 0, 'testsPerRotation')
8IfrotateBy == (-1)
Then
9Change Variable
Variable
firstTestRow
Operator
+=
Value
data('Kicks Layout', 0, 'testsPerRotation')
10Return
Value
firstTestRow

A.20 Hard Drop Piece

Built in Chapter 2, Rotating and Dropping.

Logic ComponentHard Drop PieceAttach to: Falling Piece

When Hard Drop is pressed, the falling piece drops straight to its landing row and locks at once, with a thud and a small shake.

Attach toAny Object
DATA STRUCTURES
Pieceself.piece
SHARED VARIABLES
NameTypeKindStarting Value
shakeStrengthNumberConstant0.004
shakeSecondsNumberConstant0.12
When Hard Drop Is Pressed
WhenCommand PressedCommand: Hard Drop
1Change Component Value
Component Value
self.piece.hardDropRows
Value
self.piece.row - self.piece.landingRow
2Ifself.piece.hardDropRows > 0
Then
3Change Component Value
Component Value
self.piece.lastMoveWasRotation
Value
false
4Trigger Custom Event
Custom Event
hardDropped
5Change Component Value
Component Value
self.piece.row
Value
self.piece.landingRow
6Trigger Custom Event
Custom Event
pieceMoved
7Control Sound
Sound
Hard Drop
8Camera Shake
Intensity
@self.shakeStrength
Seconds
@self.shakeSeconds
9Trigger Custom Event on Object
Custom Event
lockPiece

A.21 Note Lowest Row (Function)

Built in Chapter 2, Rotating and Dropping.

FunctionNote Lowest Row

When the falling piece reaches a new lowest row, remembers it, clears its touchdown and lock-delay history, and stops the old delay. Its next landing gets a fresh delay and restart count.

PARAMETERS
NameTypeStarts at
pieceObjectStructural
Required Components
Slot Namepiece
Component TypeData Structure
Required SchemaPiece
ACTIONS
1Ifpiece.piece.row < piece.piece.lowestRow
Then
2Change Component Value
Component Value
piece.piece.lowestRow
Value
piece.piece.row
3Change Component Value
Component Value
piece.piece.lockResets
Value
0
4Change Component Value
Component Value
piece.piece.hasTouchedDown
Value
false
5Change Component Value
Component Value
piece.piece.isLockDelayOver
Value
false
6Stop Recurring Timer
Applies to
piece
Timer Name
"lockDelay"

A.22 Rotate Piece

Built in Chapter 2, Rotating and Dropping.

Logic ComponentRotate PieceAttach to: Falling Piece

Rotates the falling piece when a Rotate key is pressed: clockwise, counterclockwise or 180 degrees (Rotate With Kicks).

Attach toAny Object
DATA STRUCTURES
Pieceself.piece
When Rotate Clockwise Is Pressed
WhenCommand PressedCommand: Rotate Clockwise
1Rotate With KicksFunction
piece
self
rotateBy
1
When Rotate Counterclockwise Is Pressed
WhenCommand PressedCommand: Rotate Counterclockwise
1Rotate With KicksFunction
piece
self
rotateBy
-1
When Rotate 180 Is Pressed
WhenCommand PressedCommand: Rotate 180
1Rotate With KicksFunction
piece
self
rotateBy
2

A.23 Rotate With Kicks (Function)

Built in Chapter 2, Rotating and Dropping.

FunctionRotate With Kicks

Rotates a piece by rotateBy quarter rotations (1 clockwise, -1 counterclockwise, 2 for 180 degrees) the standard way: it tries the five places of the Kicks table for this rotation in order and takes the first where the piece fits; where none fits, the piece does not rotate.

PARAMETERS
NameTypeStarts at
pieceObjectStructural
Required Components
Slot Namepiece
Component TypeData Structure
Required SchemaPiece
rotateByNumber1
ACTIONS
1Declare Variable
Name
newRotation
Value
0
2Declare Variable
Name
firstTestRow
Value
0
3Declare Variable
Name
test
Value
0
4Declare Variable
Type
Boolean
Name
hasRotated
Value
false
5Change Variable
Variable
newRotation
Value
mod(piece.piece.rotation + rotateBy + 4, 4)
6First Kick RowFunction
Action Name
kicksStart
kind
piece.piece.kind
rotation
piece.piece.rotation
rotateBy
rotateBy
7Change Variable
Variable
firstTestRow
Value
kicksStart.value
8Change Variable
Variable
test
Value
0
9Change Variable
Variable
hasRotated
Value
false
10WhilehasRotated == false && test < data('Kicks Layout', 0, 'testsPerRotation')
Each time
11Piece FitsFunction
Action Name
roomAfterRotation
kind
piece.piece.kind
rotation
newRotation
column
piece.piece.column + data('Kicks', firstTestRow + test, 'columnShift')
row
piece.piece.row + data('Kicks', firstTestRow + test, 'rowShift')
12IfroomAfterRotation.value == true
Then
13Change Component Value
Component Value
piece.piece.column
Value
piece.piece.column + data('Kicks', firstTestRow + test, 'columnShift')
14Change Component Value
Component Value
piece.piece.row
Value
piece.piece.row + data('Kicks', firstTestRow + test, 'rowShift')
15Change Component Value
Component Value
piece.piece.rotation
Value
newRotation
16Change Variable
Variable
hasRotated
Value
true
17Change Component Value
Component Value
piece.piece.lastMoveWasRotation
Value
true
18Change Component Value
Component Value
piece.piece.lastKickTest
Value
test
19Change Variable
Variable
test
Operator
+=
Value
1
20IfhasRotated == true
Then
21Control Sound
Sound
Rotate Chime
22Find Landing RowFunction
piece
piece
23Trigger Custom Event
Custom Event
pieceMoved
24Trigger Custom Event on Object
Applies to
piece
Custom Event
pieceShifted

A.24 Show Drop Streaks

Built in Chapter 2, Rotating and Dropping.

Logic ComponentShow Drop StreaksAttach to: Falling Piece

Draws a hard drop: a streak over the rows each crystal of the piece crosses, in a lighter tint of its color, and a puff of sparks where it lands.

Attach toAny Object
DATA STRUCTURES
Pieceself.piece
SHARED VARIABLES
NameTypeKindStarting Value
streakObjectConstantNone
streakArtMetersNumberConstant6
sparksCellsAboveMiddleNumberConstant0.4
OBJECT KINDS
streakDrop Streak
On Hard Dropped
WhenhardDroppedCustom Event
1Ifself.piece.hardDropRows > 0
Then
2Declare Variable
Name
streakScale
Value
self.piece.hardDropRows + 1
3Change Variable
Variable
streakScale
Operator
*=
Value
data('Well Layout', 0, 'cellSize') / @self.streakArtMeters
4Repeat4times
Each time
5Crystal CellFunction
Action Name
droppedCrystal
kind
self.piece.kind
rotation
self.piece.rotation
crystal
local.index + 1
6Declare Variable
Name
crystalColumn
Value
self.piece.column + droppedCrystal.column
7Declare Variable
Name
crystalRow
Value
self.piece.landingRow + droppedCrystal.row
8Cell MiddleFunction
Action Name
streakMiddle
column
crystalColumn
row
crystalRow + self.piece.hardDropRows / 2
9Create Instance
Object to Create
@self.streak
X
streakMiddle.x
Y
streakMiddle.y
10Set Scale
Applies to
created
Vertical Scale
streakScale
11Change Sprite Tint Property
Applies to
created
Value
data('Piece Kinds', self.piece.kind - 1, 'streakColor')
12Change Sprite Tint Property
Applies to
created
Property
Enabled
Value
true
13Cell MiddleFunction
Action Name
sparksPlace
column
crystalColumn
row
crystalRow + @self.sparksCellsAboveMiddle
14Burst Particles
Particles
Drop Trail
Position Relative To
World
Z Index Offset
6
X
sparksPlace.x
Y
sparksPlace.y

A.25 Soft Drop Piece

Built in Chapter 2, Rotating and Dropping.

Logic ComponentSoft Drop PieceAttach to: Falling Piece

While Soft Drop is held, the falling piece falls speedUp times faster (at least one row every slowestSeconds); letting go returns it to its normal fall.

Attach toAny Object
DATA STRUCTURES
Pieceself.piece
Soft Drop Piece Dataself.softDropPieceData
SHARED VARIABLES
NameTypeKindStarting Value
speedUpNumberConstant20
slowestSecondsNumberConstant0.05
When Soft Drop Is Pressed
WhenCommand PressedCommand: Soft Drop
1Change Component Value
Component Value
self.softDropPieceData.isSoftDropping
Value
true
2Trigger Custom Event on Object
Custom Event
fallFaster
When Soft Drop Is Released
WhenCommand ReleasedCommand: Soft Drop
1Trigger Custom Event on Object
Custom Event
fallNormally
On Fall Normally
WhenfallNormallyCustom Event
1Change Component Value
Component Value
self.softDropPieceData.isSoftDropping
Value
false
2Start Recurring Timer
Timer Name
"gravity"
Repeat Every (s)
self.piece.fallSeconds
On Spawn Piece
WhenspawnPieceCustom Event
1Ifself.softDropPieceData.isSoftDropping == true
Then
2Trigger Custom Event on Object
Custom Event
fallFaster
On Fall Faster
WhenfallFasterCustom Event
1Declare Variable
Name
fasterSeconds
Value
0
2Change Variable
Variable
fasterSeconds
Value
self.piece.fallSeconds / @self.speedUp
3IffasterSeconds > @self.slowestSeconds
Then
4Change Variable
Variable
fasterSeconds
Value
@self.slowestSeconds
5Start Recurring Timer
Timer Name
"gravity"
Repeat Every (s)
fasterSeconds
On Piece Fell
WhenpieceFellCustom Event
1Ifself.softDropPieceData.isSoftDropping == true
Then
2Trigger Custom Event
Custom Event
softDropRow
On Game Resumed
WhengameResumedCustom Event
1Ifself.softDropPieceData.isSoftDropping == true
Then
2Trigger Custom Event on Object
Custom Event
fallNormally

A.26 Clear Full Lines

Built in Chapter 3, Clearing Lines.

Logic ComponentClear Full LinesAttach to: Glass Well

The line clear: after each lock it marks the full lines (they shatter); clearSeconds later every row that stays moves down into the lowest free row and the rows left at the top are emptied; entrySeconds after that (or after a lock with no full line) it asks for the next piece.

Attach toAny Object
DATA STRUCTURES
Well Stateself.wellState
Clear Full Lines Dataself.clearFullLinesData
SHARED VARIABLES
NameTypeKindStarting Value
clearSecondsNumberConstant0.42
entrySecondsNumberConstant0.06
shakePerLineNumberConstant0.003
shakeSecondsNumberConstant0.28
flashColorColorConstant#c9f6ff
flashSecondsNumberConstant0.25
pieceObjectConstantNone
twistShakeNumberConstant0.004
OBJECT KINDS
pieceFalling Piece
On Piece Locked
WhenpieceLockedCustom Event
1Change Component Value
Component Value
self.wellState.linesCleared
Value
0
2Repeatdata('Well Layout', 0, 'rows')times
Each time
3Declare Variable
Name
checkRow
Value
local.index
4Row Is FullFunction
Action Name
checkedRow
row
checkRow
5IfcheckedRow.value == true
Then
6Change Component Value
Component Value
self.wellState.linesCleared
Value
self.wellState.linesCleared + 1
7Mark Full LineFunction
row
checkRow
8Cell MiddleFunction
Action Name
fullRowMiddle
column
(data('Well Layout', 0, 'columns') - 1) / 2
row
checkRow
9Burst Particles
Particles
Row Sparkle
Position Relative To
World
X
fullRowMiddle.x
Y
fullRowMiddle.y
Z Index Offset
6
10Trigger Custom Event
Custom Event
lockChecked
11Ifself.wellState.linesCleared > 0
Then
12Trigger Custom Event
Custom Event
wellChanged
13Change Component Value
Component Value
self.clearFullLinesData.shakeIntensity
Value
@self.shakePerLine * self.wellState.linesCleared
14If@self.piece.piece.twist > 0
Then
15Change Component Value
Component Value
self.clearFullLinesData.shakeIntensity
Operator
+=
Value
@self.twistShake
16Camera Shake
Intensity
self.clearFullLinesData.shakeIntensity
Seconds
@self.shakeSeconds
17Ifself.wellState.linesCleared == 4
Then
18Camera Flash
Color
@self.flashColor
Seconds
@self.flashSeconds
19Change Component Value
Component Value
self.clearFullLinesData.hasPendingClear
Value
true
20Trigger Custom Event
Custom Event
linesCleared
21Start Recurring Timer
Timer Name
"clearDelay"
Repeat Every (s)
@self.clearSeconds
Ring Once
Yes
22Otherwise
23Start Recurring Timer
Timer Name
"entryDelay"
Repeat Every (s)
@self.entrySeconds
Ring Once
Yes
On the Clear Delay Timer
WhenRecurring TimerTimer name: clearDelay
1Declare Variable
Name
targetRow
Value
0
2Change Variable
Variable
targetRow
Value
0
3Repeatdata('Well Layout', 0, 'rows')times
Each time
4Declare Variable
Name
checkRow
Value
local.index
5Well Cell IndexFunction
Action Name
rowStart
column
0
row
checkRow
6Ifdata('Well', rowStart.value, 'isClearing') == false
Then
7Move Row DownFunction
fromRow
checkRow
toRow
targetRow
8Change Variable
Variable
targetRow
Operator
+=
Value
1
9WhiletargetRow < data('Well Layout', 0, 'rows')
Each time
10Empty RowFunction
row
targetRow
11Change Variable
Variable
targetRow
Operator
+=
Value
1
12Trigger Custom Event
Custom Event
wellChanged
13Trigger Custom Event on Object
Custom Event
settleClear
14Start Recurring Timer
Timer Name
"entryDelay"
Repeat Every (s)
@self.entrySeconds
Ring Once
Yes
On the Entry Delay Timer
WhenRecurring TimerTimer name: entryDelay
1Trigger Custom Event
Custom Event
nextPieceDue
On Settle Clear
WhensettleClearCustom Event
1Ifself.clearFullLinesData.hasPendingClear == true
Then
2Change Component Value
Component Value
self.clearFullLinesData.hasPendingClear
Value
false
3Declare Variable
Name
remainingCrystals
Value
0
4Repeatdata('Well Layout', 0, 'rows') * data('Well Layout', 0, 'columns')times
Each time
5Ifdata('Well', local.index, 'kind') > 0 && data('Well', local.index, 'isClearing') == false
Then
6Change Variable
Variable
remainingCrystals
Operator
+=
Value
1
7IfremainingCrystals == 0
Then
8Trigger Custom Event
Custom Event
wellEmptied

A.27 Count Lines

Built in Chapter 3, Clearing Lines.

Logic ComponentCount LinesAttach to: Game Rules

Adds the lines the well cleared to the lines count (the Project Global lines).

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
wellObjectConstantNone
OBJECT KINDS
wellGlass Well
When the Scene Starts
WhenScene Start
1Change Variable
Variable
$lines
Value
0
On Lines Cleared
WhenlinesClearedCustom Event
1Change Variable
Variable
$lines
Operator
+=
Value
@self.well.wellState.linesCleared
2Ifdata('Modes', global('mode') - 1, 'stopsAtGoal') == true && $lines > data('Modes', global('mode') - 1, 'goalLines')
Then
3Change Variable
Variable
$lines
Value
data('Modes', global('mode') - 1, 'goalLines')
On Game Over
WhengameOverCustom Event
1Set Logic State
Logic Component
Count Lines
State
Disable

A.28 Empty Row (Function)

Built in Chapter 3, Clearing Lines.

FunctionEmpty Row

Empties every cell of a well row: no crystal (kind 0), not clearing. Row 0 is the bottom row.

PARAMETERS
NameTypeStarts at
rowNumber0
ACTIONS
1Declare Variable
Name
cellIndex
Value
0
2Repeatdata('Well Layout', 0, 'columns')times
Each time
3Well Cell IndexFunction
Action Name
emptiedCell
column
local.index
row
row
4Change Variable
Variable
cellIndex
Value
emptiedCell.value
5Set Data Cell
Table
Well
Row
cellIndex
Column
"kind"
6Set Data Cell
Table
Well
Row
cellIndex
Column
"isClearing"
Value
"false"

A.29 Mark Full Line (Function)

Built in Chapter 3, Clearing Lines.

FunctionMark Full Line

Marks every cell of a full well row as clearing (the Well table's isClearing), so its crystals shatter. Row 0 is the bottom row.

PARAMETERS
NameTypeStarts at
rowNumber0
ACTIONS
1Declare Variable
Name
cellIndex
Value
0
2Repeatdata('Well Layout', 0, 'columns')times
Each time
3Well Cell IndexFunction
Action Name
markedCell
column
local.index
row
row
4Change Variable
Variable
cellIndex
Value
markedCell.value
5Set Data Cell
Table
Well
Row
cellIndex
Column
"isClearing"
Value
"true"

A.30 Move Row Down (Function)

Built in Chapter 3, Clearing Lines.

FunctionMove Row Down

Copies every crystal of one well row (fromRow) into a lower row (toRow); the copied cells are not clearing. Row 0 is the bottom row.

PARAMETERS
NameTypeStarts at
fromRowNumber0
toRowNumber0
ACTIONS
1Declare Variable
Name
cellIndex
Value
0
2Declare Variable
Name
movedKind
Value
0
3Repeatdata('Well Layout', 0, 'columns')times
Each time
4Well Cell IndexFunction
Action Name
movedFromCell
column
local.index
row
fromRow
5Well Cell IndexFunction
Action Name
movedToCell
column
local.index
row
toRow
6Change Variable
Variable
movedKind
Value
data('Well', movedFromCell.value, 'kind')
7Change Variable
Variable
cellIndex
Value
movedToCell.value
8Set Data Cell
Table
Well
Row
cellIndex
Column
"kind"
Value
movedKind
9Set Data Cell
Table
Well
Row
cellIndex
Column
"isClearing"
Value
"false"

A.31 Row Is Full (Function)

Built in Chapter 3, Clearing Lines.

FunctionRow Is Full

Answers whether every cell of a well row holds a crystal (Well, Well Layout columns). Row 0 is the bottom row.

PARAMETERS
NameTypeStarts at
rowNumber0
RETURN TYPEBoolean
ACTIONS
1Declare Variable
Name
checkColumn
Value
0
2Declare Variable
Name
filledCount
Value
0
3Declare Variable
Type
Boolean
Name
isFull
Value
false
4Change Variable
Variable
filledCount
Value
0
5Change Variable
Variable
checkColumn
Value
0
6WhilecheckColumn < data('Well Layout', 0, 'columns')
Each time
7Well Cell IndexFunction
Action Name
countedCell
column
checkColumn
row
row
8Ifdata('Well', countedCell.value, 'kind') != 0
Then
9Change Variable
Variable
filledCount
Operator
+=
Value
1
10Change Variable
Variable
checkColumn
Operator
+=
Value
1
11Change Variable
Variable
isFull
Value
false
12IffilledCount == data('Well Layout', 0, 'columns')
Then
13Change Variable
Variable
isFull
Value
true
14Return
Value
isFull

A.32 Add A Shuffled Bag (Function)

Built in Chapter 4, The Queue and Hold.

FunctionAdd A Shuffled Bag

Writes one bag into the Queue table from place firstPlace on: one piece of each kind (Piece Kinds), shuffled so every order is equally likely.

PARAMETERS
NameTypeStarts at
firstPlaceNumber0
ACTIONS
1Declare Variable
Name
placeRow
Value
0
2Declare Variable
Name
placeKind
Value
0
3Declare Variable
Name
shuffleIndex
Value
0
4Declare Variable
Name
swapRow
Value
0
5Declare Variable
Name
otherRow
Value
0
6Declare Variable
Name
swapKind
Value
0
7Declare Variable
Name
otherKind
Value
0
8RepeatdataCount('Piece Kinds')times
Each time
9Change Variable
Variable
placeRow
Value
firstPlace + local.index
10Change Variable
Variable
placeKind
Value
local.index + 1
11Set Data Cell
Table
Queue
Row
placeRow
Column
"piece"
Value
placeKind
12Change Variable
Variable
shuffleIndex
Value
dataCount('Piece Kinds') - 1
13WhileshuffleIndex > 0
Each time
14Generate Random Integer
Action Name
swapPlace
Maximum
shuffleIndex
15Change Variable
Variable
swapRow
Value
firstPlace + shuffleIndex
16Change Variable
Variable
otherRow
Value
firstPlace + swapPlace.value
17Change Variable
Variable
swapKind
Value
data('Queue', swapRow, 'piece')
18Change Variable
Variable
otherKind
Value
data('Queue', otherRow, 'piece')
19Set Data Cell
Table
Queue
Row
swapRow
Column
"piece"
Value
otherKind
20Set Data Cell
Table
Queue
Row
otherRow
Column
"piece"
Value
swapKind
21Change Variable
Variable
shuffleIndex
Operator
-=
Value
1

A.33 Deal Pieces

Built in Chapter 4, The Queue and Hold.

Logic ComponentDeal PiecesAttach to: Piece Queue

Keeps the Queue table full of pieces from shuffled bags of seven: deals two bags at the start, takes the first piece off whenever one is dealt, and adds a bag whenever fewer than seven are left.

Attach toAny Object
DATA STRUCTURES
Deal Pieces Dataself.dealPiecesData
When the Scene Starts
WhenScene Start
1Reset Data Table
Table
Queue
When Created
WhenCreate
1Change Component Value
Component Value
self.dealPiecesData.queueLength
Value
0
2Repeat2times
Each time
3Add A Shuffled BagFunction
firstPlace
self.dealPiecesData.queueLength
4Change Component Value
Component Value
self.dealPiecesData.queueLength
Operator
+=
Value
dataCount('Piece Kinds')
On Piece Dealt
WhenpieceDealtCustom Event
1Declare Variable
Name
placeRow
Value
0
2Change Variable
Variable
placeRow
Value
0
3WhileplaceRow < (self.dealPiecesData.queueLength - 1)
Each time
4Declare Variable
Name
placeKind
Value
data('Queue', placeRow + 1, 'piece')
5Set Data Cell
Table
Queue
Row
placeRow
Column
"piece"
Value
placeKind
6Change Variable
Variable
placeRow
Operator
+=
Value
1
7Set Data Cell
Table
Queue
Row
placeRow
Column
"piece"
8Change Component Value
Component Value
self.dealPiecesData.queueLength
Operator
-=
Value
1
9Ifself.dealPiecesData.queueLength < dataCount('Piece Kinds')
Then
10Add A Shuffled BagFunction
firstPlace
self.dealPiecesData.queueLength
11Change Component Value
Component Value
self.dealPiecesData.queueLength
Operator
+=
Value
dataCount('Piece Kinds')
12Trigger Custom Event
Custom Event
queueChanged
On Play Started
WhenplayStartedCustom Event
1Trigger Custom Event
Custom Event
nextPieceDue

A.34 Hold Piece

Built in Chapter 4, The Queue and Hold.

Logic ComponentHold PieceAttach to: Falling Piece

When Hold is pressed (once per piece): puts the falling piece away; the first time the next piece comes from the Queue, after that the held piece comes back in its place.

Attach toAny Object
DATA STRUCTURES
Pieceself.piece
Hold Piece Dataself.holdPieceData
When Hold Is Pressed
WhenCommand PressedCommand: Hold
1Ifself.piece.hasHeld == false
Then
2Change Component Value
Component Value
self.piece.hasHeld
Value
true
3Control Sound
Sound
Hold Swish
4Stop Recurring Timer
Timer Name
"gravity"
5Stop Recurring Timer
Timer Name
"lockDelay"
6Ifself.piece.heldKind == 0
Then
7Change Component Value
Component Value
self.piece.heldKind
Value
self.piece.kind
8Trigger Custom Event on Object
Custom Event
nextPieceDue
9Otherwise
10Change Component Value
Component Value
self.holdPieceData.comingBack
Value
self.piece.heldKind
11Change Component Value
Component Value
self.piece.heldKind
Value
self.piece.kind
12Change Component Value
Component Value
self.piece.kind
Value
self.holdPieceData.comingBack
13Trigger Custom Event on Object
Custom Event
spawnPiece
14Trigger Custom Event
Custom Event
holdChanged

A.35 Preview Crystal Place (Function)

Built in Chapter 4, The Queue and Hold.

FunctionPreview Crystal Place

Answers where one crystal of a piece (rotation up) sits in a preview box (Preview Slots), the piece centered in the box at the box's cell size: x and y in meters.

PARAMETERS
NameTypeStarts at
kindNumber1
crystalNumber1
slotNumber0
RETURN TYPEPreview Crystal Place Result (a Data Structure)
ACTIONS
1Declare Variable
Name
offsetColumns
Value
0
2Declare Variable
Name
offsetRows
Value
0
3Crystal CellFunction
Action Name
previewCell
kind
kind
rotation
0
crystal
crystal
4Change Variable
Variable
offsetColumns
Value
previewCell.column + 0.5
5Change Variable
Variable
offsetColumns
Operator
-=
Value
data('Piece Kinds', kind - 1, 'middleColumn')
6Change Variable
Variable
offsetRows
Value
previewCell.row + 0.5
7Change Variable
Variable
offsetRows
Operator
-=
Value
data('Piece Kinds', kind - 1, 'middleRow')
8Change Variable
Variable
offsetColumns
Operator
*=
Value
data('Preview Slots', slot, 'cellSize')
9Change Variable
Variable
offsetRows
Operator
*=
Value
data('Preview Slots', slot, 'cellSize')
10Return
x
data('Preview Slots', slot, 'middleX') + offsetColumns
y
data('Preview Slots', slot, 'middleY') + offsetRows

A.36 Show Preview Crystal

Built in Chapter 4, The Queue and Hold.

Logic ComponentShow Preview CrystalAttach to: Preview Crystal

One crystal of a preview: the piece in its Queue place, or the held piece in the Hold box (Preview Slots), centered in its box at that box's cell size; hidden while there is no piece; the held piece dims once Hold was used for the falling piece.

Attach toAny Object
DATA STRUCTURES
Show Preview Crystal Dataself.showPreviewCrystalData
SHARED VARIABLES
NameTypeKindStarting Value
pieceObjectConstantNone
usedAlphaNumberConstant0.35
PER INSTANCE VARIABLES
NameTypeStarting Value
slotNumber0
crystalNumber1
OBJECT KINDS
pieceFalling Piece
When Created
WhenCreate
1Declare Variable
Name
boxScale
Value
0
2Change Variable
Variable
boxScale
Value
data('Preview Slots', self.slot, 'cellSize')
3Change Variable
Variable
boxScale
Operator
/=
Value
data('Well Layout', 0, 'cellSize')
4Set Scale
Horizontal Scale
boxScale
Vertical Scale
boxScale
5Trigger Custom Event on Object
Custom Event
queueChanged
On Queue Changed
WhenqueueChangedCustom Event
1Ifdata('Preview Slots', self.slot, 'isHold') == true
Then
2Change Component Value
Component Value
self.showPreviewCrystalData.previewKind
Value
@self.piece.piece.heldKind
3Otherwise
4Change Component Value
Component Value
self.showPreviewCrystalData.previewKind
Value
data('Queue', data('Preview Slots', self.slot, 'queuePlace'), 'piece')
5Ifself.showPreviewCrystalData.previewKind > 0
Then
6Preview Crystal PlaceFunction
Action Name
myPlace
kind
self.showPreviewCrystalData.previewKind
crystal
self.crystal
slot
self.slot
7Set Position
X
myPlace.x
Y
myPlace.y
8Set Frame
Frame
data('Piece Kinds', self.showPreviewCrystalData.previewKind - 1, 'frame')
9Ifdata('Preview Slots', self.slot, 'isHold') == true && @self.piece.piece.hasHeld == true
Then
10Set Alpha
Alpha
@self.usedAlpha
11Otherwise
12Set Alpha
13Set Visible
Visible
Yes
14Otherwise
15Set Visible
Visible
No
On Hold Changed
WhenholdChangedCustom Event
1Trigger Custom Event on Object
Custom Event
queueChanged
On Game Over
WhengameOverCustom Event
1Set Visible
Visible
No

A.37 Check Twist

Built in Chapter 5, Scoring and Levels.

Logic ComponentCheck TwistAttach to: Falling Piece

As the piece locks: a T whose last action was a rotation asks Twist Kind what it locks as (none, mini or full twist) and keeps the answer in the piece's twist; any other piece locks as no twist.

Attach toAny Object
DATA STRUCTURES
Pieceself.piece
On Lock Piece
WhenlockPieceCustom Event
1Change Component Value
Component Value
self.piece.twist
Value
0
2Ifdata('Piece Kinds', self.piece.kind - 1, 'canTwist') == true && self.piece.lastMoveWasRotation == true
Then
3Twist KindFunction
Action Name
lockedAs
rotation
self.piece.rotation
column
self.piece.column
row
self.piece.row
lastKickTest
self.piece.lastKickTest
4Change Component Value
Component Value
self.piece.twist
Value
lockedAs.value

A.38 Count Combo

Built in Chapter 5, Scoring and Levels.

Logic ComponentCount ComboAttach to: Game Rules

Keeps the combo (clears in a row) and the best combo of the game, and scores comboPoints x combo x level from the second clear in a row.

Attach toAny Object
DATA STRUCTURES
Scoring Stateself.scoring
SHARED VARIABLES
NameTypeKindStarting Value
wellObjectConstantNone
comboPointsNumberConstant50
OBJECT KINDS
wellGlass Well
On Clear Scored
WhenclearScoredCustom Event
1If@self.well.wellState.linesCleared > 0
Then
2Change Component Value
Component Value
self.scoring.combo
Value
self.scoring.combo + 1
3Ifself.scoring.combo > self.scoring.bestCombo
Then
4Change Component Value
Component Value
self.scoring.bestCombo
Value
self.scoring.combo
5Ifself.scoring.combo >= 1
Then
6Change Variable
Variable
$score
Operator
+=
Value
@self.comboPoints * self.scoring.combo * global('currentLevel')
7Trigger Custom Event
Custom Event
comboScored
8Otherwise
9Change Component Value
Component Value
self.scoring.combo
Value
-1
On Game Over
WhengameOverCustom Event
1Set Logic State
Logic Component
Count Combo
State
Disable

A.39 Count Level

Built in Chapter 5, Scoring and Levels.

Logic ComponentCount LevelAttach to: Game Rules

Raises the level (the Project Global currentLevel) by one for every linesPerLevel lines from the level the game started at ($firstLevel), up to the last row of Levels, and says so.

Attach toAny Object
DATA STRUCTURES
Count Level Dataself.countLevelData
SHARED VARIABLES
NameTypeKindStarting Value
linesPerLevelNumberConstant10
lastLevelNumberConstant20
When the Scene Starts
WhenScene Start
1Ifdata('Modes', global('mode') - 1, 'startsAtChosenLevel') == true
Then
2Change Variable
Variable
$firstLevel
Value
$startLevel
3Otherwise
4Change Variable
Variable
$firstLevel
Value
1
5Change Variable
Variable
$currentLevel
Value
$firstLevel
On Lines Cleared
WhenlinesClearedCustom Event
1Ifdata('Modes', global('mode') - 1, 'levelClimbs') == true
Then
2Change Component Value
Component Value
self.countLevelData.reachedLevel
Value
global('firstLevel') + floor(global('lines') / @self.linesPerLevel)
3Ifself.countLevelData.reachedLevel > @self.lastLevel
Then
4Change Component Value
Component Value
self.countLevelData.reachedLevel
Value
@self.lastLevel
5Ifself.countLevelData.reachedLevel > global('currentLevel')
Then
6Change Variable
Variable
$currentLevel
Value
self.countLevelData.reachedLevel
7Trigger Custom Event
Custom Event
levelUp
On Game Over
WhengameOverCustom Event
1Set Logic State
Logic Component
Count Level
State
Disable

A.40 Fade Out Message

Built in Chapter 5, Scoring and Levels.

Logic ComponentFade Out MessageAttach to: Clear Name, Combo Text, Back-To-Back Text, All Clear, Level Up Text, Fresh Start Text, Go

A message on the screen: when it is shown (messageShown) it stays showSeconds and fades out over its last fadeSeconds; shown again, it starts over.

Attach toAny Object
PER INSTANCE VARIABLES
NameTypeStarting Value
showSecondsNumber1.8
fadeSecondsNumber0.33
When Created
WhenCreate
1Set Visible
Visible
No
On Message Shown
WhenmessageShownCustom Event
1Control Tween
Which
Value
Value
self.transform.opacity
2Set Alpha
3Set Visible
Visible
Yes
4Start Recurring Timer
Timer Name
"fadeStart"
Repeat Every (s)
self.showSeconds - self.fadeSeconds
Ring Once
Yes
5Start Recurring Timer
Timer Name
"hide"
Repeat Every (s)
self.showSeconds
Ring Once
Yes
On the Fade Start Timer
WhenRecurring TimerTimer name: fadeStart
1Tween
Value
self.transform.opacity
Target
0
Duration
self.fadeSeconds
On the Hide Timer
WhenRecurring TimerTimer name: hide
1Set Visible
Visible
No

A.41 Keep Bests

Built in Chapter 5, Scoring and Levels.

Logic ComponentKeep BestsAttach to: Game Rules

Each mode's best: reads the four kept bests when a game begins (Read The Bests) and keeps a new best of the mode played: the highest score (Marathon and Ultra when the game ends, Zen when it is left) or the fastest finished time (Sprint 40).

Attach toAny Object
DATA STRUCTURES
Scoring Stateself.scoring
When the Scene Starts
WhenScene Start
1Read The BestsFunction
When Created
WhenCreate
1Ifdata('Modes', global('mode') - 1, 'bestKey') == "bestMarathon"
Then
2Switch Mode
Event
On Game Over
Mode
Keep A Marathon Best
3Ifdata('Modes', global('mode') - 1, 'bestKey') == "bestSprint"
Then
4Switch Mode
Event
On Mode Finished
Mode
Keep A Sprint Best
5Ifdata('Modes', global('mode') - 1, 'bestKey') == "bestUltra"
Then
6Switch Mode
Event
On Game Over
Mode
Keep An Ultra Best
7Ifdata('Modes', global('mode') - 1, 'bestKey') == "bestZen"
Then
8Switch Mode
Event
On Game Left
Mode
Keep A Zen Best
On Game Over
WhengameOverCustom Event
ModeKeep A Marathon Best
1If$score > $bestMarathonScore
Then
2Change Variable
Variable
$bestMarathonScore
Value
$score
3Save Persistent Value
Action Name
bestMarathonWrite
Key
"bestMarathon"
Value
global('bestMarathonScore')
4Change Component Value
Component Value
self.scoring.isNewBest
Value
true
On Game Over
WhengameOverCustom Event
ModeKeep An Ultra Best
1If$score > $bestUltraScore
Then
2Change Variable
Variable
$bestUltraScore
Value
$score
3Save Persistent Value
Action Name
bestUltraWrite
Key
"bestUltra"
Value
global('bestUltraScore')
4Change Component Value
Component Value
self.scoring.isNewBest
Value
true
On Mode Finished
WhenmodeFinishedCustom Event
ModeKeep A Sprint Best
1Time PlayedFunction
Action Name
sprintTime
2If$bestSprintTime == 0 || sprintTime.value < $bestSprintTime
Then
3Change Variable
Variable
$bestSprintTime
Value
sprintTime.value
4Save Persistent Value
Action Name
bestSprintWrite
Key
"bestSprint"
Value
global('bestSprintTime')
5Change Component Value
Component Value
self.scoring.isNewBest
Value
true
On Game Left
WhengameLeftCustom Event
ModeKeep A Zen Best
1If$score > $bestZenScore
Then
2Change Variable
Variable
$bestZenScore
Value
$score
3Save Persistent Value
Action Name
bestZenWrite
Key
"bestZen"
Value
global('bestZenScore')
WhenOn Game Over(the same Event)
ModeNo Score Best (Starting Mode) (no blocks: it does nothing)
WhenOn Mode Finished(the same Event)
ModeNo Time Best (Starting Mode) (no blocks: it does nothing)
WhenOn Game Left(the same Event)
ModeNothing To Keep (Starting Mode) (no blocks: it does nothing)

A.42 Score Points

Built in Chapter 5, Scoring and Levels.

Logic ComponentScore PointsAttach to: Game Rules

Adds to the score (the Project Global score): each lock's clear (Clear Names points x level), and soft and hard drop rows.

Attach toAny Object
DATA STRUCTURES
Scoring Stateself.scoring
SHARED VARIABLES
NameTypeKindStarting Value
wellObjectConstantNone
pieceObjectConstantNone
softDropPointsNumberConstant1
hardDropPointsNumberConstant2
backToBackTimesNumberConstant1.5
OBJECT KINDS
wellGlass Well
pieceFalling Piece
When the Scene Starts
WhenScene Start
1Change Variable
Variable
$score
Value
0
On Lock Checked
WhenlockCheckedCustom Event
1Declare Variable
Name
clearPoints
Value
0
2Change Component Value
Component Value
self.scoring.lastClearRow
Value
@self.piece.piece.twist * 5 + @self.well.wellState.linesCleared
3Change Component Value
Component Value
self.scoring.isBackToBack
Value
false
4If@self.well.wellState.linesCleared > 0
Then
5Ifdata('Clear Names', self.scoring.lastClearRow, 'isDifficult') == true
Then
6Change Component Value
Component Value
self.scoring.isBackToBack
Value
self.scoring.isBackToBackReady
7Change Component Value
Component Value
self.scoring.isBackToBackReady
Value
true
8Otherwise
9Change Component Value
Component Value
self.scoring.isBackToBackReady
Value
false
10Change Variable
Variable
clearPoints
Value
data('Clear Names', self.scoring.lastClearRow, 'points')
11Change Variable
Variable
clearPoints
Operator
*=
Value
$currentLevel
12Ifself.scoring.isBackToBack == true
Then
13Change Variable
Variable
clearPoints
Operator
*=
Value
@self.backToBackTimes
14Change Variable
Variable
$score
Operator
+=
Value
floor(clearPoints)
15Trigger Custom Event
Custom Event
clearScored
On Well Emptied
WhenwellEmptiedCustom Event
1Declare Variable
Name
allClearBonus
Value
0
2Change Variable
Variable
allClearBonus
Value
data('Clear Names', @self.well.wellState.linesCleared, 'allClearPoints')
3Change Variable
Variable
allClearBonus
Operator
*=
Value
$currentLevel
4Change Variable
Variable
$score
Operator
+=
Value
allClearBonus
On Soft Drop Row
WhensoftDropRowCustom Event
1Change Variable
Variable
$score
Operator
+=
Value
@self.softDropPoints
On Hard Dropped
WhenhardDroppedCustom Event
1Change Variable
Variable
$score
Operator
+=
Value
@self.piece.piece.hardDropRows * @self.hardDropPoints
On Game Over
WhengameOverCustom Event
1Set Logic State
Logic Component
Score Points
State
Disable

A.43 Show All Clear

Built in Chapter 5, Scoring and Levels.

Logic ComponentShow All ClearAttach to: All Clear

Celebrates an all clear: shows "ALL CLEAR!", plays All Clear Fanfare, flashes the screen, bursts sparkleCount Sparkle Shower over the well and Crystal Fountain under its floor.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
flashColorColorConstant#e8fdff
flashSecondsNumberConstant0.45
sparkleCountNumberConstant70
fountainRowNumberConstant-0.813
On Well Emptied
WhenwellEmptiedCustom Event
1Control Sound
Sound
All Clear Fanfare
2Camera Flash
Color
@self.flashColor
Seconds
@self.flashSeconds
3Cell MiddleFunction
Action Name
wellMiddle
column
(data('Well Layout', 0, 'columns') - 1) / 2
row
(data('Well Layout', 0, 'visibleRows') - 1) / 2
4Burst Particles
Particles
Sparkle Shower
Position Relative To
World
X
wellMiddle.x
Y
wellMiddle.y
Count
@self.sparkleCount
Z Index Offset
7
5Cell MiddleFunction
Action Name
wellFloor
column
(data('Well Layout', 0, 'columns') - 1) / 2
row
@self.fountainRow
6Burst Particles
Particles
Crystal Fountain
Position Relative To
World
X
wellFloor.x
Y
wellFloor.y
Z Index Offset
7
7Trigger Custom Event on Object
Custom Event
messageShown

A.44 Show Back-To-Back

Built in Chapter 5, Scoring and Levels.

Logic ComponentShow Back-To-BackAttach to: Back-To-Back Text

Announces a back-to-back clear: shows "BACK-TO-BACK" with Back-to-Back Sparkle.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
rulesObjectConstantNone
OBJECT KINDS
rulesGame Rules
On Clear Scored
WhenclearScoredCustom Event
1If@self.rules.scoring.isBackToBack == true
Then
2Control Sound
Sound
Back-to-Back Sparkle
3Trigger Custom Event on Object
Custom Event
messageShown

A.45 Show Clear Name

Built in Chapter 5, Scoring and Levels.

Logic ComponentShow Clear NameAttach to: Clear Name

Announces each clear: its name (Clear Names) in the Clear Name Text field clearName, which the template of this text shows ({clearName}), and its sound; a lock with no name says nothing.

Attach toAny Object
DATA STRUCTURES
Clear Name Textself.shown
SHARED VARIABLES
NameTypeKindStarting Value
rulesObjectConstantNone
OBJECT KINDS
rulesGame Rules
On Clear Scored
WhenclearScoredCustom Event
1Change Component Value
Component Value
self.shown.clearName
Value
data('Clear Names', @self.rules.scoring.lastClearRow, 'name')
2Ifself.shown.clearName != ""
Then
3Control Sound
Sound
data('Clear Names', @self.rules.scoring.lastClearRow, 'sound')
4Trigger Custom Event on Object
Custom Event
messageShown

A.46 Show Combo

Built in Chapter 5, Scoring and Levels.

Logic ComponentShow ComboAttach to: Combo Text

Announces a combo: its count in the Combo Text Count field comboCount, which the template of this text shows (COMBO x{comboCount}), with Combo Chime.

Attach toAny Object
DATA STRUCTURES
Combo Text Countself.shown
SHARED VARIABLES
NameTypeKindStarting Value
rulesObjectConstantNone
OBJECT KINDS
rulesGame Rules
On Combo Scored
WhencomboScoredCustom Event
1Change Component Value
Component Value
self.shown.comboCount
Value
@self.rules.scoring.combo
2Control Sound
Sound
Combo Chime
3Trigger Custom Event on Object
Custom Event
messageShown

A.47 Show Level Up

Built in Chapter 5, Scoring and Levels.

Logic ComponentShow Level UpAttach to: Level Up Text

Celebrates a new level: shows "LEVEL n" (its template reads currentLevel), plays Level Up and bursts sparkleCount Sparkle Shower over the well.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
sparkleCountNumberConstant50
On Level Up
WhenlevelUpCustom Event
1Control Sound
Sound
Level Up
2Cell MiddleFunction
Action Name
levelUpMiddle
column
(data('Well Layout', 0, 'columns') - 1) / 2
row
(data('Well Layout', 0, 'visibleRows') - 1) / 2
3Burst Particles
Particles
Sparkle Shower
Position Relative To
World
X
levelUpMiddle.x
Y
levelUpMiddle.y
Count
@self.sparkleCount
Z Index Offset
7
4Trigger Custom Event on Object
Custom Event
messageShown

A.48 Twist Kind (Function)

Built in Chapter 5, Scoring and Levels.

FunctionTwist Kind

Answers what a T locks as at this cell and rotation (0 none, 1 mini, 2 full twist): with at least 3 of its box's 4 corners filled (Twist Corners, Well Cell Filled) it is a twist, full when both front corners are filled or its last rotation used the last kick test (lastKickTest), otherwise a mini.

PARAMETERS
NameTypeStarts at
rotationNumber0
columnNumber0
rowNumber0
lastKickTestNumber0
RETURN TYPENumber
ACTIONS
1Declare Variable
Name
twist
Value
0
2Declare Variable
Name
cornerRow
Value
0
3Declare Variable
Name
cornerFromFront
Value
0
4Declare Variable
Name
filledCorners
Value
0
5Declare Variable
Name
filledFrontCorners
Value
0
6Change Variable
Variable
twist
Value
0
7Change Variable
Variable
filledCorners
Value
0
8Change Variable
Variable
filledFrontCorners
Value
0
9Repeat4times
Each time
10Change Variable
Variable
cornerRow
Value
local.index
11Change Variable
Variable
cornerFromFront
Value
mod(cornerRow - rotation + 4, 4)
12Well Cell FilledFunction
Action Name
cornerCheck
column
column + data('Twist Corners', cornerRow, 'column')
row
row + data('Twist Corners', cornerRow, 'row')
13IfcornerCheck.value == true
Then
14Change Variable
Variable
filledCorners
Operator
+=
Value
1
15IfcornerCheck.value == true && cornerFromFront <= 1
Then
16Change Variable
Variable
filledFrontCorners
Operator
+=
Value
1
17IffilledCorners >= 3
Then
18IffilledFrontCorners >= 2 || lastKickTest == (data('Kicks Layout', 0, 'testsPerRotation') - 1)
Then
19Change Variable
Variable
twist
Value
2
20Otherwise
21Change Variable
Variable
twist
Value
1
22Return
Value
twist

A.49 Check Top Out

Built in Chapter 6, Game Over and Results.

Logic ComponentCheck Top OutAttach to: Game Rules

Ends the game when the player tops out: a new piece with no room where it appears, or a piece that locked wholly in the hidden rows without clearing a line (a lock out).

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
pieceObjectConstantNone
wellObjectConstantNone
shakeStrengthNumberConstant0.01
shakeSecondsNumberConstant0.5
OBJECT KINDS
pieceFalling Piece
wellGlass Well
When the Scene Starts
WhenScene Start
1Set Game State
Game State
Playing
2Ifdata('Modes', global('mode') - 1, 'freshStart') == true
Then
3Switch Mode
Event
On Topped Out
Mode
Start Afresh
On Piece Blocked
WhenpieceBlockedCustom Event
1Trigger Custom Event on Object
Custom Event
toppedOut
On Lock Checked
WhenlockCheckedCustom Event
1If@self.well.wellState.linesCleared == 0 && @self.piece.piece.crystalsInView == 0
Then
2Trigger Custom Event on Object
Custom Event
toppedOut
On Topped Out
WhentoppedOutCustom Event
ModeEnd The Game (Starting Mode)
1Set Game State
Game State
Game Over
2Control Sound
Sound
Game Over Jingle
3Camera Shake
Intensity
@self.shakeStrength
Seconds
@self.shakeSeconds
4Trigger Custom Event
Custom Event
gameLost
5Trigger Custom Event
Custom Event
gameOver
On Game Over
WhengameOverCustom Event
1Set Logic State
Logic Component
Check Top Out
State
Disable
On Topped Out
WhentoppedOutCustom Event
ModeStart Afresh
1Trigger Custom Event
Custom Event
freshStart

A.50 Choose Panel Choice (Function)

Built in Chapter 6, Game Over and Results.

FunctionChoose Panel Choice

Makes choice the chosen choice of a panel (its Panel State chosen) and tells the highlights. The only writer of chosen.

PARAMETERS
NameTypeStarts at
panelObjectStructural
Required Components
Slot NamepanelState
Component TypeData Structure
Required SchemaPanel State
choiceNumber0
ACTIONS
1Change Component Value
Component Value
panel.panelState.chosen
Value
choice
2Trigger Custom Event
Custom Event
panelChoiceChanged

A.51 Count Clears

Built in Chapter 6, Game Over and Results.

Logic ComponentCount ClearsAttach to: Game Rules

Counts the game's cascades (four-line clears) and twists for the results.

Attach toAny Object
DATA STRUCTURES
Scoring Stateself.scoring
SHARED VARIABLES
NameTypeKindStarting Value
pieceObjectConstantNone
OBJECT KINDS
pieceFalling Piece
On Clear Scored
WhenclearScoredCustom Event
1Ifdata('Clear Names', self.scoring.lastClearRow, 'isCascade') == true
Then
2Change Component Value
Component Value
self.scoring.cascades
Value
self.scoring.cascades + 1
3If@self.piece.piece.twist > 0
Then
4Change Component Value
Component Value
self.scoring.twists
Value
self.scoring.twists + 1
On Game Over
WhengameOverCustom Event
1Set Logic State
Logic Component
Count Clears
State
Disable

A.52 Open Results

Built in Chapter 6, Game Over and Results.

Logic ComponentOpen ResultsAttach to: Game Rules

Opens the results panel resultsDelaySeconds after the game ends (resultsShown).

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
resultsDelaySecondsNumberConstant1.6
resultsPanelObjectConstantNone
OBJECT KINDS
resultsPanelObjects with Panel State
When the Scene Starts
WhenScene Start
1Set Input Context Active
Input Context
Menus
Active
No
On Game Over
WhengameOverCustom Event
1Start Recurring Timer
Timer Name
"resultsDelay"
Repeat Every (s)
@self.resultsDelaySeconds
Ring Once
Yes
2Set Input Context Active
Input Context
Play
Active
No
On the Results Delay Timer
WhenRecurring TimerTimer name: resultsDelay
1Switch Mode
Event
When Back Is Pressed
Mode
Back To The Menu
2Set Input Context Active
Input Context
Menus
3Set Input Context Active
Input Context
Play
Active
No
4Trigger Custom Event on Object
Applies to
@self.resultsPanel
Custom Event
panelOpened
5Trigger Custom Event
Custom Event
resultsShown
When Back Is Pressed
WhenCommand PressedCommand: Back
ModeBack To The Menu
1Control Sound
Sound
Menu Back
2Back To The MenuFunction
When Back Is Pressed
WhenCommand PressedCommand: Back
ModeWhile The Results Are Closed (Starting Mode)
(no Actions)

A.53 Panel Choice

Built in Chapter 6, Game Over and Results.

Logic ComponentPanel ChoiceAttach to: PLAY AGAIN Button, MARATHON Button, SPRINT 40 Button, ULTRA Button, ZEN Button, HOW TO PLAY Button, QUIT Button, BACK TO MENU Button, RESUME Button, RESTART Button, MAIN MENU Button

One choice of a panel: while the panel is open, Confirm runs it when it is the chosen choice; the mouse over it chooses it, and a click on it runs it. Running it plays Menu Select and tells its own button (choiceRun), whose other Logic does the work of the choice. While the How to Play panel covers the Main Menu, the choices do nothing, and Confirm on the chosen one closes it.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
panelObjectConstantNone
choiceNumberConstant0
OBJECT KINDS
panelObjects with Panel State
When Created
WhenCreate
1Change Component Value
Component Value
@self.panel.panelState.choiceCount
Operator
+=
Value
1
When Confirm Is Pressed
WhenCommand PressedCommand: Confirm
ModeRun If Chosen (Starting Mode)
1If@self.panel.panelState.isOpen == true && @self.panel.panelState.chosen == @self.choice
Then
2Control Sound
Sound
Menu Select
3Trigger Custom Event on Object
Custom Event
choiceRun
On Mouse Enter
WhenMouse Enter
ModeChoose This One (Starting Mode)
1If@self.panel.panelState.chosen != @self.choice
Then
2Choose Panel ChoiceFunction
panel
@self.panel
choice
@self.choice
3Control Sound
Sound
Menu Bubble
When Left Is Clicked
WhenMouse Pressed on ObjectMouse button: left
ModeRun This One (Starting Mode)
1Choose Panel ChoiceFunction
panel
@self.panel
choice
@self.choice
2Control Sound
Sound
Menu Select
3Trigger Custom Event on Object
Custom Event
choiceRun
On How to Play Opened
WhenhowToPlayOpenedCustom Event
1Switch Mode
Event
When Confirm Is Pressed
Mode
While Help Is Open
2Switch Mode
Event
On Mouse Enter
Mode
While Help Is Open
3Switch Mode
Event
When Left Is Clicked
Mode
While Help Is Open
On How to Play Closed
WhenhowToPlayClosedCustom Event
1Switch Mode
Event
When Confirm Is Pressed
Mode
Run If Chosen
2Switch Mode
Event
On Mouse Enter
Mode
Choose This One
3Switch Mode
Event
When Left Is Clicked
Mode
Run This One
When Confirm Is Pressed
WhenCommand PressedCommand: Confirm
ModeWhile Help Is Open
1If@self.panel.panelState.chosen == @self.choice
Then
2Close How To PlayFunction
WhenOn Mouse Enter(the same Event)
ModeWhile Help Is Open (no blocks: it does nothing)
WhenWhen Left Is Clicked(the same Event)
ModeWhile Help Is Open (no blocks: it does nothing)

A.54 Panel Choices

Built in Chapter 6, Game Over and Results.

Logic ComponentPanel ChoicesAttach to: Results Panel, Main Menu Flow, Pause Panel

A panel of choices: opens on its chosen choice when told (panelOpened; the top one unless the Logic that opens it chose another), closes when told (panelClosed), going back to its top choice, and while open Up / Down choose the choice above or below, going round at either end, with Menu Bubble.

Attach toAny Object
DATA STRUCTURES
Panel Stateself.panelState
On Panel Opened
WhenpanelOpenedCustom Event
1Change Component Value
Component Value
self.panelState.isOpen
Value
true
2Choose Panel ChoiceFunction
panel
self
choice
self.panelState.chosen
On Panel Closed
WhenpanelClosedCustom Event
1Change Component Value
Component Value
self.panelState.isOpen
Value
false
2Change Component Value
Component Value
self.panelState.chosen
Value
0
3Trigger Custom Event
Custom Event
panelChoiceChanged
When Menu Navigate Up Is Pressed
When2D Direction PressedCommand: Menu NavigateDirection: Up
ModeChoose The One Above (Starting Mode)
1Ifself.panelState.isOpen == true
Then
2Choose Panel ChoiceFunction
panel
self
choice
mod(self.panelState.chosen - 1 + self.panelState.choiceCount, self.panelState.choiceCount)
3Control Sound
Sound
Menu Bubble
When Menu Navigate Down Is Pressed
When2D Direction PressedCommand: Menu NavigateDirection: Down
ModeChoose The One Below (Starting Mode)
1Ifself.panelState.isOpen == true
Then
2Choose Panel ChoiceFunction
panel
self
choice
mod(self.panelState.chosen + 1, self.panelState.choiceCount)
3Control Sound
Sound
Menu Bubble
On How to Play Opened
WhenhowToPlayOpenedCustom Event
1Switch Mode
Event
When Menu Navigate Up Is Pressed
Mode
While Help Is Open
2Switch Mode
Event
When Menu Navigate Down Is Pressed
Mode
While Help Is Open
On How to Play Closed
WhenhowToPlayClosedCustom Event
1Switch Mode
Event
When Menu Navigate Up Is Pressed
Mode
Choose The One Above
2Switch Mode
Event
When Menu Navigate Down Is Pressed
Mode
Choose The One Below
WhenWhen Menu Navigate Up Is Pressed(the same Event)
ModeWhile Help Is Open (no blocks: it does nothing)
WhenWhen Menu Navigate Down Is Pressed(the same Event)
ModeWhile Help Is Open (no blocks: it does nothing)

A.55 Play Again

Built in Chapter 6, Game Over and Results.

Logic ComponentPlay AgainAttach to: PLAY AGAIN Button

What the PLAY AGAIN choice does: starts a new game of the same mode (Start A New Game).

Attach toAny Object
On Choice Run
WhenchoiceRunCustom Event
1Start A New GameFunction

A.56 Show Game Record

Built in Chapter 6, Game Over and Results.

Logic ComponentShow Game RecordAttach to: Result TIME Value, Result CASCADES Value, Result TWISTS Value, Result BEST COMBO Value

For a results value: copies the record of the game from Game Rules into its Game Record Text (timeMinutes, timeSeconds, cascades, twists, bestCombo), which the template of the text reads.

Attach toAny Object
DATA STRUCTURES
Game Record Textself.shown
SHARED VARIABLES
NameTypeKindStarting Value
rulesObjectConstantNone
OBJECT KINDS
rulesGame Rules
On Results Shown
WhenresultsShownCustom Event
1Change Component Value
Component Value
self.shown.timeMinutes
Value
floor(@self.rules.scoring.playedSeconds / 60)
2Change Component Value
Component Value
self.shown.timeSeconds
Value
@self.rules.scoring.playedSeconds - self.shown.timeMinutes * 60
3Change Component Value
Component Value
self.shown.cascades
Value
@self.rules.scoring.cascades
4Change Component Value
Component Value
self.shown.twists
Value
@self.rules.scoring.twists
5Change Component Value
Component Value
self.shown.bestCombo
Value
@self.rules.scoring.bestCombo

A.57 Show New Best

Built in Chapter 6, Game Over and Results.

Logic ComponentShow New BestAttach to: New Best

Says "NEW PERSONAL BEST!" on the results panel when the game that ended beat the best kept on this device.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
rulesObjectConstantNone
OBJECT KINDS
rulesGame Rules
When Created
WhenCreate
1Set Visible
Visible
No
On Results Shown
WhenresultsShownCustom Event
1If@self.rules.scoring.isNewBest == true
Then
2Set Visible
Visible
Yes

A.58 Show When Panel Choice

Built in Chapter 6, Game Over and Results.

Logic ComponentShow When Panel ChoiceAttach to: PLAY AGAIN Highlight, MARATHON Highlight, SPRINT 40 Highlight, ULTRA Highlight, ZEN Highlight, HOW TO PLAY Highlight, QUIT Highlight, Start Level Label, Start Level Left Key, Start Level Value, Start Level Right Key, BACK TO MENU Highlight, Menu Best Marathon, Menu Best Ultra, Menu Best Zen, RESUME Highlight, RESTART Highlight, MAIN MENU Highlight

The highlight over one choice of a panel: shown while its panel is open and its choice is the chosen one, hidden otherwise.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
panelObjectConstantNone
PER INSTANCE VARIABLES
NameTypeStarting Value
choiceNumber0
OBJECT KINDS
panelObjects with Panel State
When Created
WhenCreate
1Trigger Custom Event on Object
Custom Event
panelChoiceChanged
On Panel Choice Changed
WhenpanelChoiceChangedCustom Event
1If@self.panel.panelState.isOpen == true && @self.panel.panelState.chosen == self.choice
Then
2Set Visible
Visible
Yes
3Otherwise
4Set Visible
Visible
No

A.59 Show With Results

Built in Chapter 6, Game Over and Results.

Logic ComponentShow With ResultsAttach to: Results Veil, Results Panel, Results Title, Result SCORE, Result SCORE Value, Result LINES, Result LINES Value, Result LEVEL, Result LEVEL Value, Result TIME, Result TIME Value, Result CASCADES, Result CASCADES Value, Result TWISTS, Result TWISTS Value, Result BEST COMBO, Result BEST COMBO Value, PLAY AGAIN Button, PLAY AGAIN Label, BACK TO MENU Button, BACK TO MENU Label

One part of the results panel: hidden during play, shown at shownAlpha when the results open.

Attach toAny Object
PER INSTANCE VARIABLES
NameTypeStarting Value
shownAlphaNumber1
When Created
WhenCreate
1Set Visible
Visible
No
On Results Shown
WhenresultsShownCustom Event
1Set Alpha
Alpha
self.shownAlpha
2Set Visible
Visible
Yes

A.60 Start A New Game (Function)

Built in Chapter 6, Game Over and Results.

FunctionStart A New Game

Starts the same game again: Restart Scene. Each part of the game sets itself back at Scene Start.

ACTIONS
1Restart Scene

A.61 Time The Game

Built in Chapter 6, Game Over and Results.

Logic ComponentTime The GameAttach to: Game Rules

Times the game: the clock the stats panel shows ($clockStart, $clockOn, $clockHeld: the time played is ($playTime - $clockStart) x $clockOn + $clockHeld, standing still while the game is paused and after the end) and the time played kept for the results.

Attach toAny Object
DATA STRUCTURES
Scoring Stateself.scoring
When the Scene Starts
WhenScene Start
1Change Variable
Variable
$clockOn
Value
0
2Change Variable
Variable
$clockHeld
Value
0
On Game Over
WhengameOverCustom Event
1Time PlayedFunction
Action Name
playedAtTheEnd
2Change Component Value
Component Value
self.scoring.playedSeconds
Value
playedAtTheEnd.value
3Ifdata('Modes', global('mode') - 1, 'timeLimit') > 0 && self.scoring.playedSeconds > data('Modes', global('mode') - 1, 'timeLimit')
Then
4Change Component Value
Component Value
self.scoring.playedSeconds
Value
data('Modes', global('mode') - 1, 'timeLimit')
5Change Variable
Variable
$clockHeld
Value
self.scoring.playedSeconds
6Change Variable
Variable
$clockOn
Value
0
On Play Started
WhenplayStartedCustom Event
1Change Variable
Variable
$clockStart
Value
$playTime
2Change Variable
Variable
$clockOn
Value
1
3Switch Mode
Event
On Game Paused
Mode
Stop The Clock
4Switch Mode
Event
On Game Resumed
Mode
Start The Clock Again
On Game Paused
WhengamePausedCustom Event
ModeClock Not Running (Starting Mode)
(no Actions)
On Game Paused
WhengamePausedCustom Event
ModeStop The Clock
1Time PlayedFunction
Action Name
playedBeforeThePause
2Change Variable
Variable
$clockHeld
Value
playedBeforeThePause.value
3Change Variable
Variable
$clockOn
Value
0
On Game Resumed
WhengameResumedCustom Event
ModeClock Not Running (Starting Mode)
(no Actions)
On Game Resumed
WhengameResumedCustom Event
ModeStart The Clock Again
1Change Variable
Variable
$clockStart
Value
$playTime
2Change Variable
Variable
$clockOn
Value
1

A.62 Back To The Menu (Function)

Built in Chapter 7, Title and Main Menu.

FunctionBack To The Menu

Leaves the game for the Main Menu (fading 0.4 s).

ACTIONS
1Go to Scene
Scene
Main Menu
Transition
Fade

A.64 Close How To Play (Function)

Built in Chapter 7, Title and Main Menu.

FunctionClose How To Play

Closes the How to Play panel with "Menu Back" (howToPlayClosed).

ACTIONS
1Control Sound
Sound
Menu Back
2Trigger Custom Event
Custom Event
howToPlayClosed

A.65 Drift Down

Built in Chapter 7, Title and Main Menu.

Logic ComponentDrift DownAttach to: Drifting Crystal

A crystal of a random color, size, see-through and spin, falling; back to the top, as a new color, when it leaves the bottom.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
slowestFallNumberConstant1.6
fastestFallNumberConstant2.7
fastestSpinNumberConstant40
smallestScaleNumberConstant0.9
largestScaleNumberConstant1.7
faintestNumberConstant0.55
clearestNumberConstant0.9
leftmostNumberConstant1.875
rightmostNumberConstant58.125
topStartNumberConstant36.563
When Created
WhenCreate
1Generate Random Integer
Action Name
colorRow
Maximum
dataCount('Piece Kinds') - 1
2Set Frame
Frame
data('Piece Kinds', colorRow.value, 'frame')
3Generate Random Number
Action Name
crystalScale
Minimum
@self.smallestScale
Maximum
@self.largestScale
4Set Scale
Horizontal Scale
crystalScale.value
Vertical Scale
crystalScale.value
5Generate Random Number
Action Name
crystalAlpha
Minimum
@self.faintest
Maximum
@self.clearest
6Set Alpha
Alpha
crystalAlpha.value
7Generate Random Number
Action Name
crystalSpin
Minimum
-@self.fastestSpin
Maximum
@self.fastestSpin
8Set Spin
Spin
crystalSpin.value
9Generate Random Number
Action Name
crystalFall
Minimum
@self.slowestFall
Maximum
@self.fastestFall
10Set Velocity
X Velocity
0
Y Velocity
-crystalFall.value
When Leaving the View
WhenLeave View
1Generate Random Number
Action Name
crystalX
Minimum
@self.leftmost
Maximum
@self.rightmost
2Set Position
X
crystalX.value
Y
@self.topStart
3Generate Random Integer
Action Name
newColorRow
Maximum
dataCount('Piece Kinds') - 1
4Set Frame
Frame
data('Piece Kinds', newColorRow.value, 'frame')

A.66 Game Music

Built in Chapter 7, Title and Main Menu.

Logic ComponentGame MusicAttach to: Game Rules

Plays the mode's music while a game is played: Zen Tide in Zen (Modes calmTheme), the Game Theme otherwise.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
musicFadeSecondsNumberConstant0.5
When the Scene Starts
WhenScene Start
1Ifdata('Modes', global('mode') - 1, 'calmTheme') == true
Then
2Control Sound
Operation
Crossfade Music
Sound
Zen Tide (Zen Theme)
Crossfade Seconds
@self.musicFadeSeconds
3Otherwise
4Control Sound
Operation
Crossfade Music
Sound
Crystal Current (Game Theme)
Crossfade Seconds
@self.musicFadeSeconds
On Game Over
WhengameOverCustom Event
1Ifdata('Modes', global('mode') - 1, 'calmTheme') == true
Then
2Control Sound
Operation
Stop
Sound
Zen Tide (Zen Theme)
3Otherwise
4Control Sound
Operation
Stop
Sound
Crystal Current (Game Theme)

A.67 Go To The Main Menu (Function)

Built in Chapter 7, Title and Main Menu.

FunctionGo To The Main Menu

Leaves the Title for the Main Menu ("Menu Select", fading 0.4 s).

ACTIONS
1Control Sound
Sound
Menu Select
2Go to Scene
Scene
Main Menu
Transition
Fade

A.68 Go To The Title (Function)

Built in Chapter 7, Title and Main Menu.

FunctionGo To The Title

Leaves the Main Menu for the Title ("Menu Back", fading 0.4 s).

ACTIONS
1Control Sound
Sound
Menu Back
2Go to Scene
Scene
Title
Transition
Fade

A.69 Hide With Help

Built in Chapter 7, Title and Main Menu.

Logic ComponentHide With HelpAttach to: Menu Hint Up Key, Menu Hint Down Key, Menu Hint CHOOSE, Menu Hint Enter Key, Menu Hint PLAY, Menu Hint Esc Key, Menu Hint BACK

A part of the menu hidden while the How to Play panel is open (the key hints along the bottom).

Attach toAny Object
On How to Play Opened
WhenhowToPlayOpenedCustom Event
1Set Visible
Visible
No
On How to Play Closed
WhenhowToPlayClosedCustom Event
1Set Visible
Visible
Yes

A.70 Leave The Results

Built in Chapter 7, Title and Main Menu.

Logic ComponentLeave The ResultsAttach to: BACK TO MENU Button

What the BACK TO MENU choice of the results does: goes back to the Main Menu (Back To The Menu).

Attach toAny Object
On Choice Run
WhenchoiceRunCustom Event
1Back To The MenuFunction

A.72 Open How To Play

Built in Chapter 7, Title and Main Menu.

Logic ComponentOpen How To PlayAttach to: HOW TO PLAY Button

What the HOW TO PLAY choice does: opens the How to Play panel (howToPlayOpened).

Attach toAny Object
On Choice Run
WhenchoiceRunCustom Event
1Trigger Custom Event
Custom Event
howToPlayOpened

A.73 Quit The Game

Built in Chapter 7, Title and Main Menu.

Logic ComponentQuit The GameAttach to: QUIT Button

What the QUIT choice does: ends the game. End Game closes the window (or stops the published game in a browser).

Attach toAny Object
On Choice Run
WhenchoiceRunCustom Event
1End Game

A.74 Rise And Sway

Built in Chapter 7, Title and Main Menu.

Logic ComponentRise And SwayAttach to: Rising Bubble

A soap bubble: a random size (bigger ones rise faster and show more), rising and swaying side to side; back to the bottom when it leaves the top.

Attach toAny Object
DATA STRUCTURES
Rise And Sway Dataself.riseAndSwayData
SHARED VARIABLES
NameTypeKindStarting Value
smallestSizeNumberConstant0.22
largestSizeNumberConstant0.85
riseSpeedNumberConstant0.656
risePerSizeNumberConstant2.156
swaySpeedNumberConstant0.75
swaySecondsNumberConstant4.5
leftmostNumberConstant1.406
rightmostNumberConstant58.594
bottomStartNumberConstant-3.75
When Created
WhenCreate
1Generate Random Number
Action Name
bubbleSize
Minimum
@self.smallestSize
Maximum
@self.largestSize
2Set Scale
Horizontal Scale
bubbleSize.value
Vertical Scale
bubbleSize.value
3Set Alpha
Alpha
0.35 + bubbleSize.value * 0.55
4Change Component Value
Component Value
self.riseAndSwayData.rising
Value
@self.riseSpeed + bubbleSize.value * @self.risePerSize
5Set Velocity
X Velocity
@self.swaySpeed
Y Velocity
self.riseAndSwayData.rising
6Start Recurring Timer
Timer Name
"sway"
Repeat Every (s)
@self.swaySeconds
When Leaving the View
WhenLeave View
1Generate Random Number
Action Name
bubbleX
Minimum
@self.leftmost
Maximum
@self.rightmost
2Set Position
X
bubbleX.value
Y
@self.bottomStart
On the Sway Timer
WhenRecurring TimerTimer name: sway
ModeSwaying Right (Starting Mode)
1Set Velocity
X Velocity
-@self.swaySpeed
Y Velocity
self.riseAndSwayData.rising
2Switch Mode
Event
On the Sway Timer
Mode
Swaying Left
On the Sway Timer
WhenRecurring TimerTimer name: sway
ModeSwaying Left
1Set Velocity
X Velocity
@self.swaySpeed
Y Velocity
self.riseAndSwayData.rising
2Switch Mode
Event
On the Sway Timer
Mode
Swaying Right

A.75 Show Menu Info

Built in Chapter 7, Title and Main Menu.

Logic ComponentShow Menu InfoAttach to: Info Title, Info Line 1, Info Line 2, Info Line 3, Menu Best Label

One text of the info panel of the Main Menu: shows its column (title, line1, line2, line3 or bestLabel) of Menu Choices for the chosen choice, in the Menu Info Text field infoText that its template reads.

Attach toAny Object
DATA STRUCTURES
Menu Info Textself.shown
SHARED VARIABLES
NameTypeKindStarting Value
columnTextConstanttitle
On Menu Choice Changed
WhenmenuChoiceChangedCustom Event
1Change Component Value
Component Value
self.shown.infoText
Value
data('Menu Choices', global('menuChoice'), @self.column)
2Ifself.shown.infoText != ""
Then
3Set Visible
Visible
Yes
4Otherwise
5Set Visible
Visible
No

A.76 Show With Help

Built in Chapter 7, Title and Main Menu.

Logic ComponentShow With HelpAttach to: Help Veil, Help Panel, Help Title, Help Keys 0-0 0, Help Keys 0-0 1, Help Action 0-0, Help Keys 0-1 0, Help Action 0-1, Help Keys 0-2 0, Help Action 0-2, Help Keys 0-3 0, Help Keys 0-3 1, Help Action 0-3, Help Keys 1-0 0, Help Keys 1-0 1, Help Action 1-0, Help Keys 1-1 0, Help Keys 1-1 1, Help Action 1-1, Help Keys 1-2 0, Help Action 1-2, Help Keys 1-3 0, Help Keys 1-3 1, Help Action 1-3, Help Back 0, Help Back 1, Help Back 2, Help Back 3

One part of the How to Play panel: hidden while the menu is open, shown at shownAlpha while the panel is open.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
shownAlphaNumberConstant1
When Created
WhenCreate
1Set Visible
Visible
No
On How to Play Opened
WhenhowToPlayOpenedCustom Event
1Set Alpha
Alpha
@self.shownAlpha
2Set Visible
Visible
Yes
On How to Play Closed
WhenhowToPlayClosedCustom Event
1Set Visible
Visible
No

A.77 Start The Chosen Mode

Built in Chapter 7, Title and Main Menu.

Logic ComponentStart The Chosen ModeAttach to: MARATHON Button, SPRINT 40 Button, ULTRA Button, ZEN Button

What a mode choice (MARATHON, SPRINT 40, ULTRA, ZEN) does: starts a game of the mode of the chosen choice (Menu Choices): keeps it in $mode and goes to the Gameplay Scene.

Attach toAny Object
On Choice Run
WhenchoiceRunCustom Event
1Change Variable
Variable
$mode
Value
data('Menu Choices', $menuChoice, 'mode')
2Go to Scene
Scene
Gameplay
Transition
Fade
Transition Seconds
0.5

A.78 Title Controls

Built in Chapter 7, Title and Main Menu.

Logic ComponentTitle ControlsAttach to: Title Flow

The Title's keys: the menus have the controls; Confirm or a left click goes to the Main Menu. Starts the Menu Theme.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
musicFadeSecondsNumberConstant0.5
When the Scene Starts
WhenScene Start
1Set Input Context Active
Input Context
Menus
2Set Input Context Active
Input Context
Play
Active
No
3Control Sound
Operation
Crossfade Music
Sound
Aurora Glass (Menu Theme)
Crossfade Seconds
@self.musicFadeSeconds
When Confirm Is Pressed
WhenCommand PressedCommand: Confirm
1Go To The Main MenuFunction
When the Left Mouse Button Is Pressed
WhenMouse PressMouse button: left
1Go To The Main MenuFunction

A.79 Count Pieces

Built in Chapter 8, Four Ways to Play.

Logic ComponentCount PiecesAttach to: Game Rules

Counts the pieces locked in this game ($piecesPlaced), shown on the stats panel.

Attach toAny Object
When the Scene Starts
WhenScene Start
1Change Variable
Variable
$piecesPlaced
Value
0
On Piece Placed
WhenpiecePlacedCustom Event
1Change Variable
Variable
$piecesPlaced
Operator
+=
Value
1
On Game Over
WhengameOverCustom Event
1Set Logic State
Logic Component
Count Pieces
State
Disable

A.80 Finish The Mode

Built in Chapter 8, Four Ways to Play.

Logic ComponentFinish The ModeAttach to: Game Rules

Finishes the mode at its goal lines or when its time limit is up (Modes): Game Over, Victory Jingle, Crystal Fountain and Sparkle Shower, modeFinished and gameOver.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
wellObjectConstantNone
sparkleCountNumberConstant80
fountainCountNumberConstant120
fountainRowNumberConstant-0.813
OBJECT KINDS
wellGlass Well
On Play Started
WhenplayStartedCustom Event
1Ifdata('Modes', global('mode') - 1, 'timeLimit') > 0
Then
2Start Recurring Timer
Timer Name
"timeUp"
Repeat Every (s)
data('Modes', global('mode') - 1, 'timeLimit')
Ring Once
Yes
On Lines Cleared
WhenlinesClearedCustom Event
1Ifdata('Modes', global('mode') - 1, 'goalLines') > 0 && $lines >= data('Modes', global('mode') - 1, 'goalLines')
Then
2Trigger Custom Event on Object
Custom Event
goalReached
On the Time Up Timer
WhenRecurring TimerTimer name: timeUp
1Trigger Custom Event on Object
Custom Event
goalReached
On Goal Reached
WhengoalReachedCustom Event
1Trigger Custom Event on Object
Applies to
@self.well
Custom Event
settleClear
2Set Game State
Game State
Game Over
3Control Sound
Sound
Victory Jingle
4Cell MiddleFunction
Action Name
finishMiddle
column
(data('Well Layout', 0, 'columns') - 1) / 2
row
(data('Well Layout', 0, 'visibleRows') - 1) / 2
5Burst Particles
Particles
Sparkle Shower
Position Relative To
World
X
finishMiddle.x
Y
finishMiddle.y
Count
@self.sparkleCount
Z Index Offset
7
6Cell MiddleFunction
Action Name
finishFloor
column
(data('Well Layout', 0, 'columns') - 1) / 2
row
@self.fountainRow
7Burst Particles
Particles
Crystal Fountain
Position Relative To
World
X
finishFloor.x
Y
finishFloor.y
Count
@self.fountainCount
Z Index Offset
7
8Trigger Custom Event
Custom Event
modeFinished
9Trigger Custom Event
Custom Event
gameOver
On Game Over
WhengameOverCustom Event
1Set Logic State
Logic Component
Finish The Mode
State
Disable

A.81 Read The Bests (Function)

Built in Chapter 8, Four Ways to Play.

FunctionRead The Bests

Reads the four bests kept on this device (0 when none yet) into $bestMarathonScore, $bestSprintTime (seconds), $bestUltraScore and $bestZenScore.

ACTIONS
1Load Persistent Value
Action Name
bestMarathonRead
Key
"bestMarathon"
Default
0
2Change Variable
Variable
$bestMarathonScore
Value
bestMarathonRead.value
3Load Persistent Value
Action Name
bestSprintRead
Key
"bestSprint"
Default
0
4Change Variable
Variable
$bestSprintTime
Value
bestSprintRead.value
5Load Persistent Value
Action Name
bestUltraRead
Key
"bestUltra"
Default
0
6Change Variable
Variable
$bestUltraScore
Value
bestUltraRead.value
7Load Persistent Value
Action Name
bestZenRead
Key
"bestZen"
Default
0
8Change Variable
Variable
$bestZenScore
Value
bestZenRead.value

A.82 Show Fresh Start

Built in Chapter 8, Four Ways to Play.

Logic ComponentShow Fresh StartAttach to: Fresh Start Text

Shows "FRESH START" when Zen starts afresh (Fade Out Message on the same text hides it again).

Attach toAny Object
On Fresh Start
WhenfreshStartCustom Event
1Trigger Custom Event on Object
Custom Event
messageShown

A.83 Show In Mode Row

Built in Chapter 8, Four Ways to Play.

Logic ComponentShow In Mode RowAttach to: LINES Label, LINES Value, LEVEL Label, LEVEL Value, Best Score, GOAL Label, GOAL Value, LINES LEFT Label, LINES LEFT Value, TIME Label, TIME Value, TIME LEFT Label, TIME LEFT Value, RESETS Label, RESETS Value, Best Ultra, Best Zen

A text of the stats panel shown only when the mode's row of Modes, in column, names row (for example levelRow = GOAL).

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
columnTextConstantlevelRow
rowTextConstantLEVEL
When Created
WhenCreate
1Ifdata('Modes', global('mode') - 1, @self.column) == @self.row
Then
2Set Visible
Visible
Yes
3Otherwise
4Set Visible
Visible
No

A.84 Show Lines Left

Built in Chapter 8, Four Ways to Play.

Logic ComponentShow Lines LeftAttach to: LINES LEFT Value

Shows how many lines are left to the goal of the mode (Modes goalLines - $lines, not below 0) in the Lines Left Text field linesLeft, which its template reads ({linesLeft}).

Attach toAny Object
DATA STRUCTURES
Lines Left Textself.shown
When Created
WhenCreate
1Change Component Value
Component Value
self.shown.linesLeft
Value
data('Modes', global('mode') - 1, 'goalLines')
On Lines Cleared
WhenlinesClearedCustom Event
1Change Component Value
Component Value
self.shown.linesLeft
Value
data('Modes', global('mode') - 1, 'goalLines') - global('lines')
2Ifself.shown.linesLeft < 0
Then
3Change Component Value
Component Value
self.shown.linesLeft
Value
0

A.85 Show Menu Sprint Best

Built in Chapter 8, Four Ways to Play.

Logic ComponentShow Menu Sprint BestAttach to: Menu Best Time, Menu Best Time None

A text of the Main Menu's info panel for Sprint 40: shown while its choice is chosen and a time is kept (whenKept true: the time) or none is yet (whenKept false: NO TIME YET).

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
choiceNumberConstant1
whenKeptBooleanConstantYes
On Menu Choice Changed
WhenmenuChoiceChangedCustom Event
1Declare Variable
Type
Boolean
Name
isKept
Value
false
2Change Variable
Variable
isKept
Value
global('bestSprintTime') > 0
3If$menuChoice == @self.choice && isKept == @self.whenKept
Then
4Set Visible
Visible
Yes
5Otherwise
6Set Visible
Visible
No

A.86 Show Mode Goal

Built in Chapter 8, Four Ways to Play.

Logic ComponentShow Mode GoalAttach to: GOAL Value

Shows the lines that finish the mode (Modes goalLines) in the Goal Text field goalLines, which its template reads ({goalLines} LINES).

Attach toAny Object
DATA STRUCTURES
Goal Textself.shown
When Created
WhenCreate
1Change Component Value
Component Value
self.shown.goalLines
Value
data('Modes', global('mode') - 1, 'goalLines')

A.87 Show Mode Name

Built in Chapter 8, Four Ways to Play.

Logic ComponentShow Mode NameAttach to: Mode Name

Shows the name of the mode being played (Modes, row $mode - 1): writes it into the Mode Name Text field modeName, which the template of the text ({modeName}) reads.

Attach toAny Object
DATA STRUCTURES
Mode Name Textself.shown
When Created
WhenCreate
1Change Component Value
Component Value
self.shown.modeName
Value
data('Modes', global('mode') - 1, 'name')

A.88 Show Result Title

Built in Chapter 8, Four Ways to Play.

Logic ComponentShow Result TitleAttach to: Results Title

The results title: GAME OVER, or the finishing title of the mode (Modes finishTitle) when the mode was finished, in the Result Title Text field resultTitle that the template of the text shows.

Attach toAny Object
DATA STRUCTURES
Result Title Textself.shown
On Mode Finished
WhenmodeFinishedCustom Event
1Change Component Value
Component Value
self.shown.resultTitle
Value
data('Modes', global('mode') - 1, 'finishTitle')

A.89 Show Sprint Best

Built in Chapter 8, Four Ways to Play.

Logic ComponentShow Sprint BestAttach to: Best Time, Best Time None

A text of the PERSONAL BEST panel in Sprint 40: shown when a time is kept (whenKept true: the time) or when none is (whenKept false: --:--).

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
whenKeptBooleanConstantYes
When Created
WhenCreate
1Declare Variable
Type
Boolean
Name
isKept
Value
false
2Change Variable
Variable
isKept
Value
global('bestSprintTime') > 0
3Ifdata('Modes', global('mode') - 1, 'bestKey') == "bestSprint" && isKept == @self.whenKept
Then
4Set Visible
Visible
Yes
5Otherwise
6Set Visible
Visible
No

A.90 Show Time Limit

Built in Chapter 8, Four Ways to Play.

Logic ComponentShow Time LimitAttach to: TIME LEFT Value

Holds the time limit of the mode (Modes timeLimit) in the Time Limit Text field timeLimit, for the TIME LEFT template, which takes the time played from it.

Attach toAny Object
DATA STRUCTURES
Time Limit Textself.shown
When Created
WhenCreate
1Change Component Value
Component Value
self.shown.timeLimit
Value
data('Modes', global('mode') - 1, 'timeLimit')

A.91 Start Afresh

Built in Chapter 8, Four Ways to Play.

Logic ComponentStart AfreshAttach to: Game Rules

Zen's fresh start: empties the well, counts a reset ($resets), plays All Clear Fanfare and bursts sparkleCount Sparkle Shower over the well.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
sparkleCount2NumberConstant70
When the Scene Starts
WhenScene Start
1Change Variable
Variable
$resets
Value
0
On Fresh Start
WhenfreshStartCustom Event
1Empty The WellFunction
2Trigger Custom Event
Custom Event
wellChanged
3Trigger Custom Event
Custom Event
wellReset
4Change Variable
Variable
$resets
Operator
+=
Value
1
5Control Sound
Sound
All Clear Fanfare
6Cell MiddleFunction
Action Name
freshMiddle
column
(data('Well Layout', 0, 'columns') - 1) / 2
row
(data('Well Layout', 0, 'visibleRows') - 1) / 2
7Burst Particles
Particles
Sparkle Shower
Position Relative To
World
X
freshMiddle.x
Y
freshMiddle.y
Count
@self.sparkleCount2
Z Index Offset
7

A.92 Time Played (Function)

Built in Chapter 8, Four Ways to Play.

FunctionTime Played

Answers the time played so far in this game, in seconds: while the clock runs ($clockOn 1), the play clock since $clockStart plus the time kept before ($clockHeld); otherwise the time kept.

RETURN TYPENumber
ACTIONS
1Declare Variable
Name
seconds
Value
0
2If$clockOn == 1
Then
3Change Variable
Variable
seconds
Value
global('playTime') - global('clockStart') + global('clockHeld')
4Otherwise
5Change Variable
Variable
seconds
Value
$clockHeld
6Return
Value
seconds

A.93 Count Down

Built in Chapter 9, Countdown and Pause.

Logic ComponentCount DownAttach to: Game Rules

Counts down before play: $countdown from countdownSeconds to 1, one a second, each with Countdown Beep; then Countdown Go, the play controls on, and playStarted to everyone.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
countdownSecondsNumberConstant3
When the Scene Starts
WhenScene Start
1Set Input Context Active
Input Context
Play
Active
No
2Change Variable
Variable
$countdown
Value
@self.countdownSeconds
3Start Recurring Timer
Timer Name
"countdownBegins"
First Delay (s)
0
Ring Once
Yes
On the Countdown Begins Timer
WhenRecurring TimerTimer name: countdownBegins
1Control Sound
Sound
Countdown Beep
2Start Recurring Timer
Timer Name
"countdownTick"
On the Countdown Tick Timer
WhenRecurring TimerTimer name: countdownTick
1Change Variable
Variable
$countdown
Operator
-=
Value
1
2If$countdown > 0
Then
3Control Sound
Sound
Countdown Beep
4Otherwise
5Stop Recurring Timer
Timer Name
"countdownTick"
6Control Sound
Sound
Countdown Go
7Set Input Context Active
Input Context
Play
8Trigger Custom Event
Custom Event
playStarted

A.94 Go On Playing

Built in Chapter 9, Countdown and Pause.

Logic ComponentGo On PlayingAttach to: RESUME Button

What the RESUME choice does: goes on from the pause (Resume The Game).

Attach toAny Object
On Choice Run
WhenchoiceRunCustom Event
1Resume The GameFunction

A.95 Leave For The Menu

Built in Chapter 9, Countdown and Pause.

Logic ComponentLeave For The MenuAttach to: MAIN MENU Button

What the MAIN MENU choice of the pause does: leaves the game: ends the pause, then goes back to the Main Menu (Back To The Menu).

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
wellObjectConstantNone
OBJECT KINDS
wellGlass Well
On Choice Run
WhenchoiceRunCustom Event
1Trigger Custom Event on Object
Applies to
@self.well
Custom Event
settleClear
2Trigger Custom Event
Custom Event
gameLeft
3Set Game Paused
Paused (1 pause / 0 resume)
0
4Back To The MenuFunction

A.96 Pause The Game

Built in Chapter 9, Countdown and Pause.

Logic ComponentPause The GameAttach to: Game Rules

Pauses the game with Set Game Paused when Pause is pressed (during the countdown or play, not after the end), with Pause Chime and the menu controls; Back resumes it.

Attach toAny Object
SHARED VARIABLES
NameTypeKindStarting Value
pausePanelObjectConstantNone
OBJECT KINDS
pausePanelObjects with Panel State
When the Scene Starts
WhenScene Start
1Set Input Context Active
Input Context
Pause
When Pause Is Pressed
WhenCommand PressedCommand: Pause
1Set Game Paused
2Control Sound
Sound
Pause Chime
3Set Input Context Active
Input Context
Menus
On Game Paused
WhengamePausedCustom Event
1Switch Mode
Event
When Back Is Pressed
Mode
Resume
2Trigger Custom Event on Object
Applies to
@self.pausePanel
Custom Event
panelOpened
On Game Resumed
WhengameResumedCustom Event
1Switch Mode
Event
When Back Is Pressed
Mode
While Playing
2Trigger Custom Event on Object
Applies to
@self.pausePanel
Custom Event
panelClosed
When Back Is Pressed
WhenCommand PressedCommand: Back
ModeWhile Playing (Starting Mode)
(no Actions)
When Back Is Pressed
WhenCommand PressedCommand: Back
ModeResume
1Control Sound
Sound
Menu Select
2Resume The GameFunction
On Game Over
WhengameOverCustom Event
1Set Input Context Active
Input Context
Pause
Active
No

A.97 Restart The Mode

Built in Chapter 9, Countdown and Pause.

Logic ComponentRestart The ModeAttach to: RESTART Button

What the RESTART choice does: starts the same mode again from the pause: ends the pause, then starts a new game (Start A New Game).

Attach toAny Object
On Choice Run
WhenchoiceRunCustom Event
1Set Game Paused
Paused (1 pause / 0 resume)
0
2Start A New GameFunction

A.98 Resume The Game (Function)

Built in Chapter 9, Countdown and Pause.

FunctionResume The Game

Goes on from the pause: the menu controls go off and Set Game Paused ends the pause (the engine then sends gameResumed).

ACTIONS
1Set Input Context Active
Input Context
Menus
Active
false
2Set Game Paused
Paused (1 pause / 0 resume)
0

A.99 Show During Countdown

Built in Chapter 9, Countdown and Pause.

Logic ComponentShow During CountdownAttach to: Ready, Countdown

A text of the countdown (READY, the number): shown from the start of the game until play begins (playStarted).

Attach toAny Object
When Created
WhenCreate
1Set Visible
Visible
Yes
On Play Started
WhenplayStartedCustom Event
1Set Visible
Visible
No

A.100 Show Go

Built in Chapter 9, Countdown and Pause.

Logic ComponentShow GoAttach to: Go

Shows "GO!" when play begins (Fade Out Message on the same text hides it again).

Attach toAny Object
On Play Started
WhenplayStartedCustom Event
1Trigger Custom Event on Object
Custom Event
messageShown

A.101 Show While Paused

Built in Chapter 9, Countdown and Pause.

Logic ComponentShow While PausedAttach to: Pause Veil, Pause Panel, Pause Title, RESUME Button, RESUME Label, RESTART Button, RESTART Label, MAIN MENU Button, MAIN MENU Label, Pause Hint Enter Key, Pause Hint CONFIRM, Pause Hint Esc Key, Pause Hint RESUME

One part of the pause panel: hidden while the game is played, shown at shownAlpha while it is paused.

Attach toAny Object
PER INSTANCE VARIABLES
NameTypeStarting Value
shownAlphaNumber1
When Created
WhenCreate
1Set Visible
Visible
No
On Game Paused
WhengamePausedCustom Event
1Set Alpha
Alpha
self.shownAlpha
2Set Visible
Visible
Yes
On Game Resumed
WhengameResumedCustom Event
1Set Visible
Visible
No