- Learn
- Build a Game
- Crystal Cascade
- Appendices
- A Logic Reference
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.
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.
Any ObjectWell Celldata('Well Layout', 0, 'visibleRows')times- Name
cellRow- Value
local.index
data('Well Layout', 0, 'columns')times- Action Name
newCellMiddle- column
local.index- row
cellRow
- Object to Create
@self.wellCell- X
newCellMiddle.x- Y
newCellMiddle.y
A.2 Cell At (Function)
Built in Chapter 1, Falling Crystals.
Answers which well cell is under a point in the world (meters): its column from the left and row from the bottom (Well Layout).
- Name
cellSize- Value
0
- Name
column- Value
0
- Name
row- Value
0
- Variable
cellSize- Value
data('Well Layout', 0, 'cellSize')
- Variable
column- Value
floor((x - data('Well Layout', 0, 'left')) / cellSize)
- Variable
row- Value
floor((y - data('Well Layout', 0, 'bottom')) / cellSize)
- column
column- row
row
A.3 Cell Middle (Function)
Built in Chapter 1, Falling Crystals.
Answers where the middle of a well cell is in the world (meters), from its column and row (Well Layout).
- Name
cellSize- Value
0
- Name
x- Value
0
- Name
y- Value
0
- Variable
cellSize- Value
data('Well Layout', 0, 'cellSize')
- Variable
x- Value
data('Well Layout', 0, 'left') + (column + 0.5) * cellSize
- Variable
y- Value
data('Well Layout', 0, 'bottom') + (row + 0.5) * cellSize
- x
x- y
y
A.4 Crystal Cell (Function)
Built in Chapter 1, Falling Crystals.
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).
- Name
shapeRow- Value
0
- Name
column- Value
0
- Name
row- Value
0
- Name
rotationColumn- Value
0
- Name
rotationRow- Value
0
- Name
rotatedColumn- Value
0
- Variable
shapeRow- Value
(kind - 1) * 4 + crystal - 1
- Variable
column- Value
data('Piece Shapes', shapeRow, 'column')
- Variable
row- Value
data('Piece Shapes', shapeRow, 'row')
- Variable
rotationColumn- Value
data('Piece Kinds', kind - 1, 'rotationColumn')
- Variable
rotationRow- Value
data('Piece Kinds', kind - 1, 'rotationRow')
rotationtimes- Variable
rotatedColumn- Value
rotationColumn + (row - rotationRow)
- Variable
row- Value
rotationRow - (column - rotationColumn)
- Variable
column- Value
rotatedColumn
- column
column- row
row
A.5 Empty The Well (Function)
Built in Chapter 1, Falling Crystals.
Makes the Well table one empty row per cell of the well (Well Layout: columns x rows), or empties the rows it already has.
data('Well Layout', 0, 'columns') * data('Well Layout', 0, 'rows')times- Action Name
addedRow- Table
Well- Row
blockLocal("index")- Values
{"kind":"0","isClearing":"false"}
A.6 Lock Piece
Built in Chapter 1, Falling Crystals.
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.
Any Objectself.pieceGame Rules- Name
lockedKind- Value
0
- Timer Name
"gravity"
- Timer Name
"lockDelay"
- Variable
lockedKind- Value
self.piece.kind
- Component Value
self.piece.crystalsInView- Value
0
4times- Action Name
lockedCrystal- kind
self.piece.kind- rotation
self.piece.rotation- crystal
local.index + 1
- Action Name
lockedCell- column
self.piece.column + lockedCrystal.column- row
self.piece.row + lockedCrystal.row
- Name
cellIndex- Value
lockedCell.value
- Table
Well- Row
cellIndex- Column
"kind"- Value
lockedKind
(self.piece.row + lockedCrystal.row) < data('Well Layout', 0, 'visibleRows')- Component Value
self.piece.crystalsInView- Value
self.piece.crystalsInView + 1
- Sound
Lock Click
- Logic Component
Piece Gravity- State
Disable
- Logic Component
Move Piece- State
Disable
- Logic Component
Rotate Piece- State
Disable
- Logic Component
Hard Drop Piece- State
Disable
- Logic Component
Hold Piece- State
Disable
- Component Value
self.piece.hasHeld- Value
false
- Custom Event
holdChanged
- Applies to
@self.rules- Custom Event
piecePlaced
- Custom Event
pieceLocked
- Custom Event
crystalsLocked
A.7 Move Piece
Built in Chapter 1, Falling Crystals.
Moves the falling piece one column in its moveDirection when asked (moveOnce, from Read The Move Keys), if the piece fits there.
Any Objectself.piece- Action Name
roomBeside- piece
self- columnShift
self.piece.moveDirection- rowShift
0
roomBeside.value == true- Component Value
self.piece.column- Value
self.piece.column + self.piece.moveDirection
- Component Value
self.piece.lastMoveWasRotation- Value
false
- Sound
Move Tick
- piece
self
- Custom Event
pieceMoved
- Custom Event
pieceShifted
A.8 Piece Fits (Function)
Built in Chapter 1, Falling Crystals.
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).
- Type
Boolean- Name
fits- Value
true
- Name
crystalColumn- Value
0
- Name
crystalRow- Value
0
- Variable
fits- Value
true
4times- Action Name
testedCrystal- kind
kind- rotation
rotation- crystal
local.index + 1
- Variable
crystalColumn- Value
column + testedCrystal.column
- Variable
crystalRow- Value
row + testedCrystal.row
- Action Name
testedCell- column
crystalColumn- row
crystalRow
testedCell.value == true- Variable
fits- Value
false
- Value
fits
A.9 Piece Fits Here (Function)
Built in Chapter 1, Falling Crystals.
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.
pieceData StructurePiece- Type
Boolean- Name
fits- Value
true
- Action Name
shiftedPiece- kind
piece.piece.kind- rotation
piece.piece.rotation- column
piece.piece.column + columnShift- row
piece.piece.row + rowShift
- Variable
fits- Value
shiftedPiece.value
- Value
fits
A.10 Piece Gravity
Built in Chapter 1, Falling Crystals.
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.
Any Objectself.piecedata('Modes', global('mode') - 1, 'fallSeconds') > 0- Component Value
self.piece.fallSeconds- Value
data('Modes', global('mode') - 1, 'fallSeconds')
- Name
levelsUp- Value
global('currentLevel') - 1
- Component Value
self.piece.fallSeconds- Value
pow(@self.curveStartSeconds - levelsUp * @self.curveStepSeconds, levelsUp)
- Timer Name
"gravity"- Repeat Every (s)
self.piece.fallSeconds
- Event
On the Gravity Timer- Mode
Falling
- Component Value
self.piece.lowestRow- Value
self.piece.row
- Component Value
self.piece.lockResets- Value
0
- Component Value
self.piece.hasTouchedDown- Value
false
- Component Value
self.piece.isLockDelayOver- Value
false
- Action Name
roomBelowOnGravity- piece
self- columnShift
0- rowShift
-1
roomBelowOnGravity.value == true- Component Value
self.piece.row- Value
self.piece.row - 1
- Component Value
self.piece.lastMoveWasRotation- Value
false
- piece
self
- Custom Event
pieceMoved
- Custom Event
pieceFell
- Action Name
roomBelowAfterFall- piece
self- columnShift
0- rowShift
-1
roomBelowAfterFall.value == false- Custom Event
pieceLanded
- Custom Event
pieceLanded
- Event
On the Gravity Timer- Mode
Resting
self.piece.hasTouchedDown == false- Component Value
self.piece.hasTouchedDown- Value
true
- Timer Name
"lockDelay"- Repeat Every (s)
self.piece.lockDelaySeconds- Ring Once
Yes
- Custom Event
lockDelayStarted
self.piece.isLockDelayOver == true- Custom Event
lockPiece
- Component Value
self.piece.isLockDelayOver- Value
true
- Action Name
roomBelowAfterDelay- piece
self- columnShift
0- rowShift
-1
roomBelowAfterDelay.value == true- Event
On the Gravity Timer- Mode
Falling
- Custom Event
lockPiece
- piece
self
self.piece.hasTouchedDown == trueself.piece.lockResets < @self.lockResetLimit- Component Value
self.piece.lockResets- Value
self.piece.lockResets + 1
- Component Value
self.piece.isLockDelayOver- Value
false
- Timer Name
"lockDelay"- Repeat Every (s)
self.piece.lockDelaySeconds- Ring Once
Yes
- Custom Event
lockDelayStarted
- Action Name
roomBelowAfterShift- piece
self- columnShift
0- rowShift
-1
roomBelowAfterShift.value == true- Event
On the Gravity Timer- Mode
Falling
- Custom Event
pieceLanded
- Logic Component
Piece Gravity- State
Disable
A.11 Read The Move Keys
Built in Chapter 1, Falling Crystals.
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.
Any Objectself.pieceself.readTheMoveKeysData- Component Value
self.readTheMoveKeysData.isLeftHeld- Value
true
- Component Value
self.piece.moveDirection- Value
-1
- Custom Event
moveOnce
- Timer Name
"autoRepeat"- Repeat Every (s)
@self.autoRepeatSeconds- First Delay (s)
@self.autoRepeatDelaySeconds
- Component Value
self.readTheMoveKeysData.isRightHeld- Value
true
- Component Value
self.piece.moveDirection- Value
1
- Custom Event
moveOnce
- Timer Name
"autoRepeat"- Repeat Every (s)
@self.autoRepeatSeconds- First Delay (s)
@self.autoRepeatDelaySeconds
- Component Value
self.readTheMoveKeysData.isLeftHeld- Value
false
self.piece.moveDirection == (-1) && self.readTheMoveKeysData.isRightHeld == true- Component Value
self.piece.moveDirection- Value
1
- Timer Name
"autoRepeat"- Repeat Every (s)
@self.autoRepeatSeconds- First Delay (s)
@self.autoRepeatDelaySeconds
self.piece.moveDirection == (-1)- Component Value
self.piece.moveDirection- Value
0
- Timer Name
"autoRepeat"
- Component Value
self.readTheMoveKeysData.isRightHeld- Value
false
self.piece.moveDirection == 1 && self.readTheMoveKeysData.isLeftHeld == true- Component Value
self.piece.moveDirection- Value
-1
- Timer Name
"autoRepeat"- Repeat Every (s)
@self.autoRepeatSeconds- First Delay (s)
@self.autoRepeatDelaySeconds
self.piece.moveDirection == 1- Component Value
self.piece.moveDirection- Value
0
- Timer Name
"autoRepeat"
- Custom Event
moveOnce
- Component Value
self.readTheMoveKeysData.isLeftHeld- Value
false
- Component Value
self.readTheMoveKeysData.isRightHeld- Value
false
- Component Value
self.piece.moveDirection- Value
0
- Timer Name
"autoRepeat"
A.12 Show Piece Crystal
Built in Chapter 1, Falling Crystals.
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.
Any ObjectFalling Piece- Which
Value- Value
self.transform.opacity
- Action Name
thisCrystal- kind
@self.piece.piece.kind- rotation
@self.piece.piece.rotation- crystal
self.crystal
- Name
cellColumn- Value
@self.piece.piece.column + thisCrystal.column
- Name
cellRow- Value
@self.piece.piece.row + thisCrystal.row
self.showsLanding == true- Variable
cellRow- Value
@self.piece.piece.landingRow + thisCrystal.row
- Action Name
thisCellMiddle- column
cellColumn- row
cellRow
- X
thisCellMiddle.x- Y
thisCellMiddle.y
- Frame
data('Piece Kinds', @self.piece.piece.kind - 1, 'frame')
cellRow < data('Well Layout', 0, 'visibleRows')- Visible
Yes
- Visible
No
self.showsLanding == false- Action Name
roomBelowDimmingPiece- piece
@self.piece- columnShift
0- rowShift
-1
roomBelowDimmingPiece.value == false- Value
self.transform.opacity- Target
@self.dimmedAlpha- Duration
@self.piece.piece.lockDelaySeconds
- Visible
No
- Visible
No
A.13 Show Well Cell
Built in Chapter 1, Falling Crystals.
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.
Any Objectself.showWellCellData- Action Name
myCell- x
self.transform.position.x- y
self.transform.position.y
- Action Name
thisCellIndex- column
myCell.column- row
myCell.row
- Component Value
self.showWellCellData.cellIndex- Value
thisCellIndex.value
- Custom Event
wellChanged
self.showWellCellData.shownKind == 0 && data('Well', self.showWellCellData.cellIndex, 'kind') != 0- Horizontal Scale
@self.popScale- Vertical Scale
@self.popScale
- Value
self.transform.scale- Target
1- Duration
@self.popSeconds- Ease
Quad Out
- Particles
Lock Glint- Z Index Offset
6
- Custom Event
wellChanged
data('Well', self.showWellCellData.cellIndex, 'isClearing') == true && self.showWellCellData.isShowingShatter == false- Particles
Crystal Shards- Z Index Offset
6- Tint
data('Piece Kinds', data('Well', self.showWellCellData.cellIndex, 'kind') - 1, 'color')
- Component Value
self.showWellCellData.isShowingShatter- Value
data('Well', self.showWellCellData.cellIndex, 'isClearing')
- Component Value
self.showWellCellData.shownKind- Value
data('Well', self.showWellCellData.cellIndex, 'kind')
self.showWellCellData.isShowingShatter == true- Frame
data('Crystal Frames', 0, 'shatter')
- Frame
self.showWellCellData.shownKind
- Name
waitSeconds- Value
0
- Name
rowFromBottom- Value
0
- Variable
rowFromBottom- Value
floor(self.showWellCellData.cellIndex / data('Well Layout', 0, 'columns'))
- Variable
waitSeconds- Value
@self.stoneDelaySeconds + rowFromBottom * @self.stoneRowSeconds
- Timer Name
"turnToStone"- Repeat Every (s)
waitSeconds- Ring Once
Yes
self.showWellCellData.shownKind != 0- Frame
data('Crystal Frames', 0, 'stone')
A.14 Spawn Piece
Built in Chapter 1, Falling Crystals.
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.
Any Objectself.piece- Component Value
self.piece.rotation- Value
0
- Component Value
self.piece.lastMoveWasRotation- Value
false
- Component Value
self.piece.lastKickTest- Value
0
- Component Value
self.piece.column- Value
@self.startColumn
- Component Value
self.piece.row- Value
data('Well Layout', 0, 'rows') - 4
- Action Name
roomForNewPiece- piece
self- columnShift
0- rowShift
0
roomForNewPiece.value == true- Logic Component
Hold Piece
- Logic Component
Piece Gravity
- Logic Component
Move Piece
- Logic Component
Rotate Piece
- Logic Component
Hard Drop Piece
- Action Name
roomBelowNewPiece- piece
self- columnShift
0- rowShift
-1
roomBelowNewPiece.value == true- Component Value
self.piece.row- Value
self.piece.row - 1
- piece
self
- Custom Event
pieceMoved
- Component Value
self.piece.isBlocked- Value
true
- Custom Event
pieceBlocked
- Action Name
isPlaying- Game State
Playing
isPlaying.value == true- Component Value
self.piece.kind- Value
data('Queue', 0, 'piece')
- Custom Event
pieceDealt
- Custom Event
spawnPiece
self.piece.isBlocked == true- Component Value
self.piece.isBlocked- Value
false
- Custom Event
spawnPiece
A.15 Well Cell Filled (Function)
Built in Chapter 1, Falling Crystals.
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.
- Type
Boolean- Name
isFilled- Value
false
- Variable
isFilled- Value
false
column < 0 || column >= data('Well Layout', 0, 'columns') || row < 0- Variable
isFilled- Value
true
- Action Name
testedCellIndex- column
column- row
row
row < data('Well Layout', 0, 'rows') && data('Well', testedCellIndex.value, 'kind') != 0- Variable
isFilled- Value
true
- Value
isFilled
A.16 Well Cell Index (Function)
Built in Chapter 1, Falling Crystals.
Answers which row of the Well table holds the well cell at this column and row (row * columns + column, Well Layout).
- Value
row * data('Well Layout', 0, 'columns') + column
A.17 Fade Away
Built in Chapter 2, Rotating and Dropping.
A short-lived effect: it fades out over fadeSeconds and removes itself after removeSeconds.
Any Object- Alpha
@self.startAlpha
- Value
self.transform.opacity- Target
0- Duration
@self.fadeSeconds- Ease
Quad in
- Timer Name
"remove"- Repeat Every (s)
@self.removeSeconds- Ring Once
Yes
A.18 Find Landing Row (Function)
Built in Chapter 2, Rotating and Dropping.
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.
pieceData StructurePiece- Type
Boolean- Name
canFall- Value
true
- Component Value
piece.piece.landingRow- Value
piece.piece.row
- Variable
canFall- Value
true
canFall == true- Action Name
roomUnderLanding- kind
piece.piece.kind- rotation
piece.piece.rotation- column
piece.piece.column- row
piece.piece.landingRow - 1
roomUnderLanding.value == true- Component Value
piece.piece.landingRow- Value
piece.piece.landingRow - 1
- Variable
canFall- Value
false
A.19 First Kick Row (Function)
Built in Chapter 2, Rotating and Dropping.
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).
- Name
firstTestRow- Value
0
rotateBy == 2- Variable
firstTestRow- Value
data('Kicks Layout', 0, 'firstHalfRotationRow')
- Variable
firstTestRow- Operator
+=- Value
rotation * data('Kicks Layout', 0, 'testsPerRotation')
- Variable
firstTestRow- Value
data('Piece Kinds', kind - 1, 'firstKickRow')
- Variable
firstTestRow- Operator
+=- Value
rotation * 2 * data('Kicks Layout', 0, 'testsPerRotation')
rotateBy == (-1)- Variable
firstTestRow- Operator
+=- Value
data('Kicks Layout', 0, 'testsPerRotation')
- Value
firstTestRow
A.20 Hard Drop Piece
Built in Chapter 2, Rotating and Dropping.
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.
Any Objectself.piece- Component Value
self.piece.hardDropRows- Value
self.piece.row - self.piece.landingRow
self.piece.hardDropRows > 0- Component Value
self.piece.lastMoveWasRotation- Value
false
- Custom Event
hardDropped
- Component Value
self.piece.row- Value
self.piece.landingRow
- Custom Event
pieceMoved
- Sound
Hard Drop
- Intensity
@self.shakeStrength- Seconds
@self.shakeSeconds
- Custom Event
lockPiece
A.21 Note Lowest Row (Function)
Built in Chapter 2, Rotating and Dropping.
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.
pieceData StructurePiecepiece.piece.row < piece.piece.lowestRow- Component Value
piece.piece.lowestRow- Value
piece.piece.row
- Component Value
piece.piece.lockResets- Value
0
- Component Value
piece.piece.hasTouchedDown- Value
false
- Component Value
piece.piece.isLockDelayOver- Value
false
- Applies to
piece- Timer Name
"lockDelay"
A.22 Rotate Piece
Built in Chapter 2, Rotating and Dropping.
Rotates the falling piece when a Rotate key is pressed: clockwise, counterclockwise or 180 degrees (Rotate With Kicks).
Any Objectself.piece- piece
self- rotateBy
1
- piece
self- rotateBy
-1
- piece
self- rotateBy
2
A.23 Rotate With Kicks (Function)
Built in Chapter 2, Rotating and Dropping.
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.
pieceData StructurePiece- Name
newRotation- Value
0
- Name
firstTestRow- Value
0
- Name
test- Value
0
- Type
Boolean- Name
hasRotated- Value
false
- Variable
newRotation- Value
mod(piece.piece.rotation + rotateBy + 4, 4)
- Action Name
kicksStart- kind
piece.piece.kind- rotation
piece.piece.rotation- rotateBy
rotateBy
- Variable
firstTestRow- Value
kicksStart.value
- Variable
test- Value
0
- Variable
hasRotated- Value
false
hasRotated == false && test < data('Kicks Layout', 0, 'testsPerRotation')- 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')
roomAfterRotation.value == true- Component Value
piece.piece.column- Value
piece.piece.column + data('Kicks', firstTestRow + test, 'columnShift')
- Component Value
piece.piece.row- Value
piece.piece.row + data('Kicks', firstTestRow + test, 'rowShift')
- Component Value
piece.piece.rotation- Value
newRotation
- Variable
hasRotated- Value
true
- Component Value
piece.piece.lastMoveWasRotation- Value
true
- Component Value
piece.piece.lastKickTest- Value
test
- Variable
test- Operator
+=- Value
1
hasRotated == true- Sound
Rotate Chime
- piece
piece
- Custom Event
pieceMoved
- Applies to
piece- Custom Event
pieceShifted
A.24 Show Drop Streaks
Built in Chapter 2, Rotating and Dropping.
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.
Any Objectself.pieceDrop Streakself.piece.hardDropRows > 0- Name
streakScale- Value
self.piece.hardDropRows + 1
- Variable
streakScale- Operator
*=- Value
data('Well Layout', 0, 'cellSize') / @self.streakArtMeters
4times- Action Name
droppedCrystal- kind
self.piece.kind- rotation
self.piece.rotation- crystal
local.index + 1
- Name
crystalColumn- Value
self.piece.column + droppedCrystal.column
- Name
crystalRow- Value
self.piece.landingRow + droppedCrystal.row
- Action Name
streakMiddle- column
crystalColumn- row
crystalRow + self.piece.hardDropRows / 2
- Object to Create
@self.streak- X
streakMiddle.x- Y
streakMiddle.y
- Applies to
created- Vertical Scale
streakScale
- Applies to
created- Value
data('Piece Kinds', self.piece.kind - 1, 'streakColor')
- Applies to
created- Property
Enabled- Value
true
- Action Name
sparksPlace- column
crystalColumn- row
crystalRow + @self.sparksCellsAboveMiddle
- 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.
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.
Any Objectself.pieceself.softDropPieceData- Component Value
self.softDropPieceData.isSoftDropping- Value
true
- Custom Event
fallFaster
- Custom Event
fallNormally
- Component Value
self.softDropPieceData.isSoftDropping- Value
false
- Timer Name
"gravity"- Repeat Every (s)
self.piece.fallSeconds
self.softDropPieceData.isSoftDropping == true- Custom Event
fallFaster
- Name
fasterSeconds- Value
0
- Variable
fasterSeconds- Value
self.piece.fallSeconds / @self.speedUp
fasterSeconds > @self.slowestSeconds- Variable
fasterSeconds- Value
@self.slowestSeconds
- Timer Name
"gravity"- Repeat Every (s)
fasterSeconds
self.softDropPieceData.isSoftDropping == true- Custom Event
softDropRow
self.softDropPieceData.isSoftDropping == true- Custom Event
fallNormally
A.26 Clear Full Lines
Built in Chapter 3, Clearing Lines.
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.
Any Objectself.wellStateself.clearFullLinesDataFalling Piece- Component Value
self.wellState.linesCleared- Value
0
data('Well Layout', 0, 'rows')times- Name
checkRow- Value
local.index
- Action Name
checkedRow- row
checkRow
checkedRow.value == true- Component Value
self.wellState.linesCleared- Value
self.wellState.linesCleared + 1
- row
checkRow
- Action Name
fullRowMiddle- column
(data('Well Layout', 0, 'columns') - 1) / 2- row
checkRow
- Particles
Row Sparkle- Position Relative To
World- X
fullRowMiddle.x- Y
fullRowMiddle.y- Z Index Offset
6
- Custom Event
lockChecked
self.wellState.linesCleared > 0- Custom Event
wellChanged
- Component Value
self.clearFullLinesData.shakeIntensity- Value
@self.shakePerLine * self.wellState.linesCleared
@self.piece.piece.twist > 0- Component Value
self.clearFullLinesData.shakeIntensity- Operator
+=- Value
@self.twistShake
- Intensity
self.clearFullLinesData.shakeIntensity- Seconds
@self.shakeSeconds
self.wellState.linesCleared == 4- Color
@self.flashColor- Seconds
@self.flashSeconds
- Component Value
self.clearFullLinesData.hasPendingClear- Value
true
- Custom Event
linesCleared
- Timer Name
"clearDelay"- Repeat Every (s)
@self.clearSeconds- Ring Once
Yes
- Timer Name
"entryDelay"- Repeat Every (s)
@self.entrySeconds- Ring Once
Yes
- Name
targetRow- Value
0
- Variable
targetRow- Value
0
data('Well Layout', 0, 'rows')times- Name
checkRow- Value
local.index
- Action Name
rowStart- column
0- row
checkRow
data('Well', rowStart.value, 'isClearing') == false- fromRow
checkRow- toRow
targetRow
- Variable
targetRow- Operator
+=- Value
1
targetRow < data('Well Layout', 0, 'rows')- row
targetRow
- Variable
targetRow- Operator
+=- Value
1
- Custom Event
wellChanged
- Custom Event
settleClear
- Timer Name
"entryDelay"- Repeat Every (s)
@self.entrySeconds- Ring Once
Yes
- Custom Event
nextPieceDue
self.clearFullLinesData.hasPendingClear == true- Component Value
self.clearFullLinesData.hasPendingClear- Value
false
- Name
remainingCrystals- Value
0
data('Well Layout', 0, 'rows') * data('Well Layout', 0, 'columns')timesdata('Well', local.index, 'kind') > 0 && data('Well', local.index, 'isClearing') == false- Variable
remainingCrystals- Operator
+=- Value
1
remainingCrystals == 0- Custom Event
wellEmptied
A.27 Count Lines
Built in Chapter 3, Clearing Lines.
Adds the lines the well cleared to the lines count (the Project Global lines).
Any ObjectGlass Well- Variable
$lines- Value
0
- Variable
$lines- Operator
+=- Value
@self.well.wellState.linesCleared
data('Modes', global('mode') - 1, 'stopsAtGoal') == true && $lines > data('Modes', global('mode') - 1, 'goalLines')- Variable
$lines- Value
data('Modes', global('mode') - 1, 'goalLines')
- Logic Component
Count Lines- State
Disable
A.28 Empty Row (Function)
Built in Chapter 3, Clearing Lines.
Empties every cell of a well row: no crystal (kind 0), not clearing. Row 0 is the bottom row.
- Name
cellIndex- Value
0
data('Well Layout', 0, 'columns')times- Action Name
emptiedCell- column
local.index- row
row
- Variable
cellIndex- Value
emptiedCell.value
- Table
Well- Row
cellIndex- Column
"kind"
- Table
Well- Row
cellIndex- Column
"isClearing"- Value
"false"
A.29 Mark Full Line (Function)
Built in Chapter 3, Clearing Lines.
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.
- Name
cellIndex- Value
0
data('Well Layout', 0, 'columns')times- Action Name
markedCell- column
local.index- row
row
- Variable
cellIndex- Value
markedCell.value
- Table
Well- Row
cellIndex- Column
"isClearing"- Value
"true"
A.30 Move Row Down (Function)
Built in Chapter 3, Clearing Lines.
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.
- Name
cellIndex- Value
0
- Name
movedKind- Value
0
data('Well Layout', 0, 'columns')times- Action Name
movedFromCell- column
local.index- row
fromRow
- Action Name
movedToCell- column
local.index- row
toRow
- Variable
movedKind- Value
data('Well', movedFromCell.value, 'kind')
- Variable
cellIndex- Value
movedToCell.value
- Table
Well- Row
cellIndex- Column
"kind"- Value
movedKind
- Table
Well- Row
cellIndex- Column
"isClearing"- Value
"false"
A.31 Row Is Full (Function)
Built in Chapter 3, Clearing Lines.
Answers whether every cell of a well row holds a crystal (Well, Well Layout columns). Row 0 is the bottom row.
- Name
checkColumn- Value
0
- Name
filledCount- Value
0
- Type
Boolean- Name
isFull- Value
false
- Variable
filledCount- Value
0
- Variable
checkColumn- Value
0
checkColumn < data('Well Layout', 0, 'columns')- Action Name
countedCell- column
checkColumn- row
row
data('Well', countedCell.value, 'kind') != 0- Variable
filledCount- Operator
+=- Value
1
- Variable
checkColumn- Operator
+=- Value
1
- Variable
isFull- Value
false
filledCount == data('Well Layout', 0, 'columns')- Variable
isFull- Value
true
- Value
isFull
A.32 Add A Shuffled Bag (Function)
Built in Chapter 4, The Queue and Hold.
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.
- Name
placeRow- Value
0
- Name
placeKind- Value
0
- Name
shuffleIndex- Value
0
- Name
swapRow- Value
0
- Name
otherRow- Value
0
- Name
swapKind- Value
0
- Name
otherKind- Value
0
dataCount('Piece Kinds')times- Variable
placeRow- Value
firstPlace + local.index
- Variable
placeKind- Value
local.index + 1
- Table
Queue- Row
placeRow- Column
"piece"- Value
placeKind
- Variable
shuffleIndex- Value
dataCount('Piece Kinds') - 1
shuffleIndex > 0- Action Name
swapPlace- Maximum
shuffleIndex
- Variable
swapRow- Value
firstPlace + shuffleIndex
- Variable
otherRow- Value
firstPlace + swapPlace.value
- Variable
swapKind- Value
data('Queue', swapRow, 'piece')
- Variable
otherKind- Value
data('Queue', otherRow, 'piece')
- Table
Queue- Row
swapRow- Column
"piece"- Value
otherKind
- Table
Queue- Row
otherRow- Column
"piece"- Value
swapKind
- Variable
shuffleIndex- Operator
-=- Value
1
A.33 Deal Pieces
Built in Chapter 4, The Queue and Hold.
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.
Any Objectself.dealPiecesData- Table
Queue
- Component Value
self.dealPiecesData.queueLength- Value
0
2times- firstPlace
self.dealPiecesData.queueLength
- Component Value
self.dealPiecesData.queueLength- Operator
+=- Value
dataCount('Piece Kinds')
- Name
placeRow- Value
0
- Variable
placeRow- Value
0
placeRow < (self.dealPiecesData.queueLength - 1)- Name
placeKind- Value
data('Queue', placeRow + 1, 'piece')
- Table
Queue- Row
placeRow- Column
"piece"- Value
placeKind
- Variable
placeRow- Operator
+=- Value
1
- Table
Queue- Row
placeRow- Column
"piece"
- Component Value
self.dealPiecesData.queueLength- Operator
-=- Value
1
self.dealPiecesData.queueLength < dataCount('Piece Kinds')- firstPlace
self.dealPiecesData.queueLength
- Component Value
self.dealPiecesData.queueLength- Operator
+=- Value
dataCount('Piece Kinds')
- Custom Event
queueChanged
- Custom Event
nextPieceDue
A.34 Hold Piece
Built in Chapter 4, The Queue and Hold.
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.
Any Objectself.pieceself.holdPieceDataself.piece.hasHeld == false- Component Value
self.piece.hasHeld- Value
true
- Sound
Hold Swish
- Timer Name
"gravity"
- Timer Name
"lockDelay"
self.piece.heldKind == 0- Component Value
self.piece.heldKind- Value
self.piece.kind
- Custom Event
nextPieceDue
- Component Value
self.holdPieceData.comingBack- Value
self.piece.heldKind
- Component Value
self.piece.heldKind- Value
self.piece.kind
- Component Value
self.piece.kind- Value
self.holdPieceData.comingBack
- Custom Event
spawnPiece
- Custom Event
holdChanged
A.35 Preview Crystal Place (Function)
Built in Chapter 4, The Queue and Hold.
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.
- Name
offsetColumns- Value
0
- Name
offsetRows- Value
0
- Action Name
previewCell- kind
kind- rotation
0- crystal
crystal
- Variable
offsetColumns- Value
previewCell.column + 0.5
- Variable
offsetColumns- Operator
-=- Value
data('Piece Kinds', kind - 1, 'middleColumn')
- Variable
offsetRows- Value
previewCell.row + 0.5
- Variable
offsetRows- Operator
-=- Value
data('Piece Kinds', kind - 1, 'middleRow')
- Variable
offsetColumns- Operator
*=- Value
data('Preview Slots', slot, 'cellSize')
- Variable
offsetRows- Operator
*=- Value
data('Preview Slots', slot, 'cellSize')
- 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.
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.
Any Objectself.showPreviewCrystalDataFalling Piece- Name
boxScale- Value
0
- Variable
boxScale- Value
data('Preview Slots', self.slot, 'cellSize')
- Variable
boxScale- Operator
/=- Value
data('Well Layout', 0, 'cellSize')
- Horizontal Scale
boxScale- Vertical Scale
boxScale
- Custom Event
queueChanged
data('Preview Slots', self.slot, 'isHold') == true- Component Value
self.showPreviewCrystalData.previewKind- Value
@self.piece.piece.heldKind
- Component Value
self.showPreviewCrystalData.previewKind- Value
data('Queue', data('Preview Slots', self.slot, 'queuePlace'), 'piece')
self.showPreviewCrystalData.previewKind > 0- Action Name
myPlace- kind
self.showPreviewCrystalData.previewKind- crystal
self.crystal- slot
self.slot
- X
myPlace.x- Y
myPlace.y
- Frame
data('Piece Kinds', self.showPreviewCrystalData.previewKind - 1, 'frame')
data('Preview Slots', self.slot, 'isHold') == true && @self.piece.piece.hasHeld == true- Alpha
@self.usedAlpha
- Visible
Yes
- Visible
No
- Custom Event
queueChanged
- Visible
No
A.37 Check Twist
Built in Chapter 5, Scoring and Levels.
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.
Any Objectself.piece- Component Value
self.piece.twist- Value
0
data('Piece Kinds', self.piece.kind - 1, 'canTwist') == true && self.piece.lastMoveWasRotation == true- Action Name
lockedAs- rotation
self.piece.rotation- column
self.piece.column- row
self.piece.row- lastKickTest
self.piece.lastKickTest
- Component Value
self.piece.twist- Value
lockedAs.value
A.38 Count Combo
Built in Chapter 5, Scoring and Levels.
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.
Any Objectself.scoringGlass Well@self.well.wellState.linesCleared > 0- Component Value
self.scoring.combo- Value
self.scoring.combo + 1
self.scoring.combo > self.scoring.bestCombo- Component Value
self.scoring.bestCombo- Value
self.scoring.combo
self.scoring.combo >= 1- Variable
$score- Operator
+=- Value
@self.comboPoints * self.scoring.combo * global('currentLevel')
- Custom Event
comboScored
- Component Value
self.scoring.combo- Value
-1
- Logic Component
Count Combo- State
Disable
A.39 Count Level
Built in Chapter 5, Scoring and Levels.
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.
Any Objectself.countLevelDatadata('Modes', global('mode') - 1, 'startsAtChosenLevel') == true- Variable
$firstLevel- Value
$startLevel
- Variable
$firstLevel- Value
1
- Variable
$currentLevel- Value
$firstLevel
data('Modes', global('mode') - 1, 'levelClimbs') == true- Component Value
self.countLevelData.reachedLevel- Value
global('firstLevel') + floor(global('lines') / @self.linesPerLevel)
self.countLevelData.reachedLevel > @self.lastLevel- Component Value
self.countLevelData.reachedLevel- Value
@self.lastLevel
self.countLevelData.reachedLevel > global('currentLevel')- Variable
$currentLevel- Value
self.countLevelData.reachedLevel
- Custom Event
levelUp
- Logic Component
Count Level- State
Disable
A.40 Fade Out Message
Built in Chapter 5, Scoring and Levels.
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.
Any Object- Visible
No
- Which
Value- Value
self.transform.opacity
- Visible
Yes
- Timer Name
"fadeStart"- Repeat Every (s)
self.showSeconds - self.fadeSeconds- Ring Once
Yes
- Timer Name
"hide"- Repeat Every (s)
self.showSeconds- Ring Once
Yes
- Value
self.transform.opacity- Target
0- Duration
self.fadeSeconds
- Visible
No
A.41 Keep Bests
Built in Chapter 5, Scoring and Levels.
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).
Any Objectself.scoringdata('Modes', global('mode') - 1, 'bestKey') == "bestMarathon"- Event
On Game Over- Mode
Keep A Marathon Best
data('Modes', global('mode') - 1, 'bestKey') == "bestSprint"- Event
On Mode Finished- Mode
Keep A Sprint Best
data('Modes', global('mode') - 1, 'bestKey') == "bestUltra"- Event
On Game Over- Mode
Keep An Ultra Best
data('Modes', global('mode') - 1, 'bestKey') == "bestZen"- Event
On Game Left- Mode
Keep A Zen Best
$score > $bestMarathonScore- Variable
$bestMarathonScore- Value
$score
- Action Name
bestMarathonWrite- Key
"bestMarathon"- Value
global('bestMarathonScore')
- Component Value
self.scoring.isNewBest- Value
true
$score > $bestUltraScore- Variable
$bestUltraScore- Value
$score
- Action Name
bestUltraWrite- Key
"bestUltra"- Value
global('bestUltraScore')
- Component Value
self.scoring.isNewBest- Value
true
- Action Name
sprintTime
$bestSprintTime == 0 || sprintTime.value < $bestSprintTime- Variable
$bestSprintTime- Value
sprintTime.value
- Action Name
bestSprintWrite- Key
"bestSprint"- Value
global('bestSprintTime')
- Component Value
self.scoring.isNewBest- Value
true
$score > $bestZenScore- Variable
$bestZenScore- Value
$score
- Action Name
bestZenWrite- Key
"bestZen"- Value
global('bestZenScore')
A.42 Score Points
Built in Chapter 5, Scoring and Levels.
Adds to the score (the Project Global score): each lock's clear (Clear Names points x level), and soft and hard drop rows.
Any Objectself.scoringGlass WellFalling Piece- Variable
$score- Value
0
- Name
clearPoints- Value
0
- Component Value
self.scoring.lastClearRow- Value
@self.piece.piece.twist * 5 + @self.well.wellState.linesCleared
- Component Value
self.scoring.isBackToBack- Value
false
@self.well.wellState.linesCleared > 0data('Clear Names', self.scoring.lastClearRow, 'isDifficult') == true- Component Value
self.scoring.isBackToBack- Value
self.scoring.isBackToBackReady
- Component Value
self.scoring.isBackToBackReady- Value
true
- Component Value
self.scoring.isBackToBackReady- Value
false
- Variable
clearPoints- Value
data('Clear Names', self.scoring.lastClearRow, 'points')
- Variable
clearPoints- Operator
*=- Value
$currentLevel
self.scoring.isBackToBack == true- Variable
clearPoints- Operator
*=- Value
@self.backToBackTimes
- Variable
$score- Operator
+=- Value
floor(clearPoints)
- Custom Event
clearScored
- Name
allClearBonus- Value
0
- Variable
allClearBonus- Value
data('Clear Names', @self.well.wellState.linesCleared, 'allClearPoints')
- Variable
allClearBonus- Operator
*=- Value
$currentLevel
- Variable
$score- Operator
+=- Value
allClearBonus
- Variable
$score- Operator
+=- Value
@self.softDropPoints
- Variable
$score- Operator
+=- Value
@self.piece.piece.hardDropRows * @self.hardDropPoints
- Logic Component
Score Points- State
Disable
A.43 Show All Clear
Built in Chapter 5, Scoring and Levels.
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.
Any Object- Sound
All Clear Fanfare
- Color
@self.flashColor- Seconds
@self.flashSeconds
- Action Name
wellMiddle- column
(data('Well Layout', 0, 'columns') - 1) / 2- row
(data('Well Layout', 0, 'visibleRows') - 1) / 2
- Particles
Sparkle Shower- Position Relative To
World- X
wellMiddle.x- Y
wellMiddle.y- Count
@self.sparkleCount- Z Index Offset
7
- Action Name
wellFloor- column
(data('Well Layout', 0, 'columns') - 1) / 2- row
@self.fountainRow
- Particles
Crystal Fountain- Position Relative To
World- X
wellFloor.x- Y
wellFloor.y- Z Index Offset
7
- Custom Event
messageShown
A.44 Show Back-To-Back
Built in Chapter 5, Scoring and Levels.
Announces a back-to-back clear: shows "BACK-TO-BACK" with Back-to-Back Sparkle.
Any ObjectGame Rules@self.rules.scoring.isBackToBack == true- Sound
Back-to-Back Sparkle
- Custom Event
messageShown
A.45 Show Clear Name
Built in Chapter 5, Scoring and Levels.
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.
Any Objectself.shownGame Rules- Component Value
self.shown.clearName- Value
data('Clear Names', @self.rules.scoring.lastClearRow, 'name')
self.shown.clearName != ""- Sound
data('Clear Names', @self.rules.scoring.lastClearRow, 'sound')
- Custom Event
messageShown
A.46 Show Combo
Built in Chapter 5, Scoring and Levels.
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.
Any Objectself.shownGame Rules- Component Value
self.shown.comboCount- Value
@self.rules.scoring.combo
- Sound
Combo Chime
- Custom Event
messageShown
A.47 Show Level Up
Built in Chapter 5, Scoring and Levels.
Celebrates a new level: shows "LEVEL n" (its template reads currentLevel), plays Level Up and bursts sparkleCount Sparkle Shower over the well.
Any Object- Sound
Level Up
- Action Name
levelUpMiddle- column
(data('Well Layout', 0, 'columns') - 1) / 2- row
(data('Well Layout', 0, 'visibleRows') - 1) / 2
- Particles
Sparkle Shower- Position Relative To
World- X
levelUpMiddle.x- Y
levelUpMiddle.y- Count
@self.sparkleCount- Z Index Offset
7
- Custom Event
messageShown
A.48 Twist Kind (Function)
Built in Chapter 5, Scoring and Levels.
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.
- Name
twist- Value
0
- Name
cornerRow- Value
0
- Name
cornerFromFront- Value
0
- Name
filledCorners- Value
0
- Name
filledFrontCorners- Value
0
- Variable
twist- Value
0
- Variable
filledCorners- Value
0
- Variable
filledFrontCorners- Value
0
4times- Variable
cornerRow- Value
local.index
- Variable
cornerFromFront- Value
mod(cornerRow - rotation + 4, 4)
- Action Name
cornerCheck- column
column + data('Twist Corners', cornerRow, 'column')- row
row + data('Twist Corners', cornerRow, 'row')
cornerCheck.value == true- Variable
filledCorners- Operator
+=- Value
1
cornerCheck.value == true && cornerFromFront <= 1- Variable
filledFrontCorners- Operator
+=- Value
1
filledCorners >= 3filledFrontCorners >= 2 || lastKickTest == (data('Kicks Layout', 0, 'testsPerRotation') - 1)- Variable
twist- Value
2
- Variable
twist- Value
1
- Value
twist
A.49 Check Top Out
Built in Chapter 6, Game Over and Results.
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).
Any ObjectFalling PieceGlass Well- Game State
Playing
data('Modes', global('mode') - 1, 'freshStart') == true- Event
On Topped Out- Mode
Start Afresh
- Custom Event
toppedOut
@self.well.wellState.linesCleared == 0 && @self.piece.piece.crystalsInView == 0- Custom Event
toppedOut
- Game State
Game Over
- Sound
Game Over Jingle
- Intensity
@self.shakeStrength- Seconds
@self.shakeSeconds
- Custom Event
gameLost
- Custom Event
gameOver
- Logic Component
Check Top Out- State
Disable
- Custom Event
freshStart
A.50 Choose Panel Choice (Function)
Built in Chapter 6, Game Over and Results.
Makes choice the chosen choice of a panel (its Panel State chosen) and tells the highlights. The only writer of chosen.
panelStateData StructurePanel State- Component Value
panel.panelState.chosen- Value
choice
- Custom Event
panelChoiceChanged
A.51 Count Clears
Built in Chapter 6, Game Over and Results.
Counts the game's cascades (four-line clears) and twists for the results.
Any Objectself.scoringFalling Piecedata('Clear Names', self.scoring.lastClearRow, 'isCascade') == true- Component Value
self.scoring.cascades- Value
self.scoring.cascades + 1
@self.piece.piece.twist > 0- Component Value
self.scoring.twists- Value
self.scoring.twists + 1
- Logic Component
Count Clears- State
Disable
A.52 Open Results
Built in Chapter 6, Game Over and Results.
Opens the results panel resultsDelaySeconds after the game ends (resultsShown).
Any ObjectObjects with Panel State- Input Context
Menus- Active
No
- Timer Name
"resultsDelay"- Repeat Every (s)
@self.resultsDelaySeconds- Ring Once
Yes
- Input Context
Play- Active
No
- Event
When Back Is Pressed- Mode
Back To The Menu
- Input Context
Menus
- Input Context
Play- Active
No
- Applies to
@self.resultsPanel- Custom Event
panelOpened
- Custom Event
resultsShown
- Sound
Menu Back
A.53 Panel Choice
Built in Chapter 6, Game Over and Results.
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.
Any ObjectObjects with Panel State- Component Value
@self.panel.panelState.choiceCount- Operator
+=- Value
1
@self.panel.panelState.isOpen == true && @self.panel.panelState.chosen == @self.choice- Sound
Menu Select
- Custom Event
choiceRun
@self.panel.panelState.chosen != @self.choice- panel
@self.panel- choice
@self.choice
- Sound
Menu Bubble
- panel
@self.panel- choice
@self.choice
- Sound
Menu Select
- Custom Event
choiceRun
- Event
When Confirm Is Pressed- Mode
While Help Is Open
- Event
On Mouse Enter- Mode
While Help Is Open
- Event
When Left Is Clicked- Mode
While Help Is Open
- Event
When Confirm Is Pressed- Mode
Run If Chosen
- Event
On Mouse Enter- Mode
Choose This One
- Event
When Left Is Clicked- Mode
Run This One
@self.panel.panelState.chosen == @self.choiceA.54 Panel Choices
Built in Chapter 6, Game Over and Results.
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.
Any Objectself.panelState- Component Value
self.panelState.isOpen- Value
true
- panel
self- choice
self.panelState.chosen
- Component Value
self.panelState.isOpen- Value
false
- Component Value
self.panelState.chosen- Value
0
- Custom Event
panelChoiceChanged
self.panelState.isOpen == true- panel
self- choice
mod(self.panelState.chosen - 1 + self.panelState.choiceCount, self.panelState.choiceCount)
- Sound
Menu Bubble
self.panelState.isOpen == true- panel
self- choice
mod(self.panelState.chosen + 1, self.panelState.choiceCount)
- Sound
Menu Bubble
- Event
When Menu Navigate Up Is Pressed- Mode
While Help Is Open
- Event
When Menu Navigate Down Is Pressed- Mode
While Help Is Open
- Event
When Menu Navigate Up Is Pressed- Mode
Choose The One Above
- Event
When Menu Navigate Down Is Pressed- Mode
Choose The One Below
A.55 Play Again
Built in Chapter 6, Game Over and Results.
What the PLAY AGAIN choice does: starts a new game of the same mode (Start A New Game).
Any ObjectA.56 Show Game Record
Built in Chapter 6, Game Over and Results.
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.
Any Objectself.shownGame Rules- Component Value
self.shown.timeMinutes- Value
floor(@self.rules.scoring.playedSeconds / 60)
- Component Value
self.shown.timeSeconds- Value
@self.rules.scoring.playedSeconds - self.shown.timeMinutes * 60
- Component Value
self.shown.cascades- Value
@self.rules.scoring.cascades
- Component Value
self.shown.twists- Value
@self.rules.scoring.twists
- Component Value
self.shown.bestCombo- Value
@self.rules.scoring.bestCombo
A.57 Show New Best
Built in Chapter 6, Game Over and Results.
Says "NEW PERSONAL BEST!" on the results panel when the game that ended beat the best kept on this device.
Any ObjectGame Rules- Visible
No
@self.rules.scoring.isNewBest == true- Visible
Yes
A.58 Show When Panel Choice
Built in Chapter 6, Game Over and Results.
The highlight over one choice of a panel: shown while its panel is open and its choice is the chosen one, hidden otherwise.
Any ObjectObjects with Panel State- Custom Event
panelChoiceChanged
@self.panel.panelState.isOpen == true && @self.panel.panelState.chosen == self.choice- Visible
Yes
- Visible
No
A.59 Show With Results
Built in Chapter 6, Game Over and Results.
One part of the results panel: hidden during play, shown at shownAlpha when the results open.
Any Object- Visible
No
- Alpha
self.shownAlpha
- Visible
Yes
A.60 Start A New Game (Function)
Built in Chapter 6, Game Over and Results.
Starts the same game again: Restart Scene. Each part of the game sets itself back at Scene Start.
A.61 Time The Game
Built in Chapter 6, Game Over and Results.
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.
Any Objectself.scoring- Variable
$clockOn- Value
0
- Variable
$clockHeld- Value
0
- Action Name
playedAtTheEnd
- Component Value
self.scoring.playedSeconds- Value
playedAtTheEnd.value
data('Modes', global('mode') - 1, 'timeLimit') > 0 && self.scoring.playedSeconds > data('Modes', global('mode') - 1, 'timeLimit')- Component Value
self.scoring.playedSeconds- Value
data('Modes', global('mode') - 1, 'timeLimit')
- Variable
$clockHeld- Value
self.scoring.playedSeconds
- Variable
$clockOn- Value
0
- Variable
$clockStart- Value
$playTime
- Variable
$clockOn- Value
1
- Event
On Game Paused- Mode
Stop The Clock
- Event
On Game Resumed- Mode
Start The Clock Again
- Action Name
playedBeforeThePause
- Variable
$clockHeld- Value
playedBeforeThePause.value
- Variable
$clockOn- Value
0
- Variable
$clockStart- Value
$playTime
- Variable
$clockOn- Value
1
A.63 Blink
Built in Chapter 7, Title and Main Menu.
Pulses this picture or text between dimAlpha and full every period seconds (a fade down, then up).
Any Object- Timer Name
"blink"- Repeat Every (s)
@self.period / 2
- Value
self.transform.opacity- Target
@self.dimAlpha- Duration
@self.period / 2- Ease
Quad in Out
- Value
self.transform.opacity- Target
1- Duration
@self.period / 2- Ease
Quad in Out
- Event
On the Blink Timer- Mode
Brightening
- Value
self.transform.opacity- Target
@self.dimAlpha- Duration
@self.period / 2- Ease
Quad in Out
- Event
On the Blink Timer- Mode
Dimming
A.64 Close How To Play (Function)
Built in Chapter 7, Title and Main Menu.
Closes the How to Play panel with "Menu Back" (howToPlayClosed).
- Sound
Menu Back
- Custom Event
howToPlayClosed
A.65 Drift Down
Built in Chapter 7, Title and Main Menu.
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.
Any Object- Action Name
colorRow- Maximum
dataCount('Piece Kinds') - 1
- Frame
data('Piece Kinds', colorRow.value, 'frame')
- Action Name
crystalScale- Minimum
@self.smallestScale- Maximum
@self.largestScale
- Horizontal Scale
crystalScale.value- Vertical Scale
crystalScale.value
- Action Name
crystalAlpha- Minimum
@self.faintest- Maximum
@self.clearest
- Alpha
crystalAlpha.value
- Action Name
crystalSpin- Minimum
-@self.fastestSpin- Maximum
@self.fastestSpin
- Spin
crystalSpin.value
- Action Name
crystalFall- Minimum
@self.slowestFall- Maximum
@self.fastestFall
- X Velocity
0- Y Velocity
-crystalFall.value
- Action Name
crystalX- Minimum
@self.leftmost- Maximum
@self.rightmost
- X
crystalX.value- Y
@self.topStart
- Action Name
newColorRow- Maximum
dataCount('Piece Kinds') - 1
- Frame
data('Piece Kinds', newColorRow.value, 'frame')
A.66 Game Music
Built in Chapter 7, Title and Main Menu.
Plays the mode's music while a game is played: Zen Tide in Zen (Modes calmTheme), the Game Theme otherwise.
Any Objectdata('Modes', global('mode') - 1, 'calmTheme') == true- Operation
Crossfade Music- Sound
Zen Tide (Zen Theme)- Crossfade Seconds
@self.musicFadeSeconds
- Operation
Crossfade Music- Sound
Crystal Current (Game Theme)- Crossfade Seconds
@self.musicFadeSeconds
data('Modes', global('mode') - 1, 'calmTheme') == true- Operation
Stop- Sound
Zen Tide (Zen Theme)
- Operation
Stop- Sound
Crystal Current (Game Theme)
A.68 Go To The Title (Function)
Built in Chapter 7, Title and Main Menu.
Leaves the Main Menu for the Title ("Menu Back", fading 0.4 s).
- Sound
Menu Back
- Scene
Title- Transition
Fade
A.69 Hide With Help
Built in Chapter 7, Title and Main Menu.
A part of the menu hidden while the How to Play panel is open (the key hints along the bottom).
Any Object- Visible
No
- Visible
Yes
A.70 Leave The Results
Built in Chapter 7, Title and Main Menu.
What the BACK TO MENU choice of the results does: goes back to the Main Menu (Back To The Menu).
Any ObjectA.72 Open How To Play
Built in Chapter 7, Title and Main Menu.
What the HOW TO PLAY choice does: opens the How to Play panel (howToPlayOpened).
Any Object- Custom Event
howToPlayOpened
A.73 Quit The Game
Built in Chapter 7, Title and Main Menu.
What the QUIT choice does: ends the game. End Game closes the window (or stops the published game in a browser).
Any ObjectA.74 Rise And Sway
Built in Chapter 7, Title and Main Menu.
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.
Any Objectself.riseAndSwayData- Action Name
bubbleSize- Minimum
@self.smallestSize- Maximum
@self.largestSize
- Horizontal Scale
bubbleSize.value- Vertical Scale
bubbleSize.value
- Alpha
0.35 + bubbleSize.value * 0.55
- Component Value
self.riseAndSwayData.rising- Value
@self.riseSpeed + bubbleSize.value * @self.risePerSize
- X Velocity
@self.swaySpeed- Y Velocity
self.riseAndSwayData.rising
- Timer Name
"sway"- Repeat Every (s)
@self.swaySeconds
- Action Name
bubbleX- Minimum
@self.leftmost- Maximum
@self.rightmost
- X
bubbleX.value- Y
@self.bottomStart
- X Velocity
-@self.swaySpeed- Y Velocity
self.riseAndSwayData.rising
- Event
On the Sway Timer- Mode
Swaying Left
- X Velocity
@self.swaySpeed- Y Velocity
self.riseAndSwayData.rising
- Event
On the Sway Timer- Mode
Swaying Right
A.76 Show With Help
Built in Chapter 7, Title and Main Menu.
One part of the How to Play panel: hidden while the menu is open, shown at shownAlpha while the panel is open.
Any Object- Visible
No
- Alpha
@self.shownAlpha
- Visible
Yes
- Visible
No
A.77 Start The Chosen Mode
Built in Chapter 7, Title and Main Menu.
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.
Any Object- Variable
$mode- Value
data('Menu Choices', $menuChoice, 'mode')
- Scene
Gameplay- Transition
Fade- Transition Seconds
0.5
A.78 Title Controls
Built in Chapter 7, Title and Main Menu.
The Title's keys: the menus have the controls; Confirm or a left click goes to the Main Menu. Starts the Menu Theme.
Any Object- Input Context
Menus
- Input Context
Play- Active
No
- Operation
Crossfade Music- Sound
Aurora Glass (Menu Theme)- Crossfade Seconds
@self.musicFadeSeconds
A.79 Count Pieces
Built in Chapter 8, Four Ways to Play.
Counts the pieces locked in this game ($piecesPlaced), shown on the stats panel.
Any Object- Variable
$piecesPlaced- Value
0
- Variable
$piecesPlaced- Operator
+=- Value
1
- Logic Component
Count Pieces- State
Disable
A.80 Finish The Mode
Built in Chapter 8, Four Ways to Play.
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.
Any ObjectGlass Welldata('Modes', global('mode') - 1, 'timeLimit') > 0- Timer Name
"timeUp"- Repeat Every (s)
data('Modes', global('mode') - 1, 'timeLimit')- Ring Once
Yes
data('Modes', global('mode') - 1, 'goalLines') > 0 && $lines >= data('Modes', global('mode') - 1, 'goalLines')- Custom Event
goalReached
- Custom Event
goalReached
- Applies to
@self.well- Custom Event
settleClear
- Game State
Game Over
- Sound
Victory Jingle
- Action Name
finishMiddle- column
(data('Well Layout', 0, 'columns') - 1) / 2- row
(data('Well Layout', 0, 'visibleRows') - 1) / 2
- Particles
Sparkle Shower- Position Relative To
World- X
finishMiddle.x- Y
finishMiddle.y- Count
@self.sparkleCount- Z Index Offset
7
- Action Name
finishFloor- column
(data('Well Layout', 0, 'columns') - 1) / 2- row
@self.fountainRow
- Particles
Crystal Fountain- Position Relative To
World- X
finishFloor.x- Y
finishFloor.y- Count
@self.fountainCount- Z Index Offset
7
- Custom Event
modeFinished
- Custom Event
gameOver
- Logic Component
Finish The Mode- State
Disable
A.81 Read The Bests (Function)
Built in Chapter 8, Four Ways to Play.
Reads the four bests kept on this device (0 when none yet) into $bestMarathonScore, $bestSprintTime (seconds), $bestUltraScore and $bestZenScore.
- Action Name
bestMarathonRead- Key
"bestMarathon"- Default
0
- Variable
$bestMarathonScore- Value
bestMarathonRead.value
- Action Name
bestSprintRead- Key
"bestSprint"- Default
0
- Variable
$bestSprintTime- Value
bestSprintRead.value
- Action Name
bestUltraRead- Key
"bestUltra"- Default
0
- Variable
$bestUltraScore- Value
bestUltraRead.value
- Action Name
bestZenRead- Key
"bestZen"- Default
0
- Variable
$bestZenScore- Value
bestZenRead.value
A.82 Show Fresh Start
Built in Chapter 8, Four Ways to Play.
Shows "FRESH START" when Zen starts afresh (Fade Out Message on the same text hides it again).
Any Object- Custom Event
messageShown
A.83 Show In Mode Row
Built in Chapter 8, Four Ways to Play.
A text of the stats panel shown only when the mode's row of Modes, in column, names row (for example levelRow = GOAL).
Any Objectdata('Modes', global('mode') - 1, @self.column) == @self.row- Visible
Yes
- Visible
No
A.84 Show Lines Left
Built in Chapter 8, Four Ways to Play.
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}).
Any Objectself.shown- Component Value
self.shown.linesLeft- Value
data('Modes', global('mode') - 1, 'goalLines')
- Component Value
self.shown.linesLeft- Value
data('Modes', global('mode') - 1, 'goalLines') - global('lines')
self.shown.linesLeft < 0- Component Value
self.shown.linesLeft- Value
0
A.86 Show Mode Goal
Built in Chapter 8, Four Ways to Play.
Shows the lines that finish the mode (Modes goalLines) in the Goal Text field goalLines, which its template reads ({goalLines} LINES).
Any Objectself.shown- 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.
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.
Any Objectself.shown- 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.
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.
Any Objectself.shown- 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.
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: --:--).
Any Object- Type
Boolean- Name
isKept- Value
false
- Variable
isKept- Value
global('bestSprintTime') > 0
data('Modes', global('mode') - 1, 'bestKey') == "bestSprint" && isKept == @self.whenKept- Visible
Yes
- Visible
No
A.90 Show Time Limit
Built in Chapter 8, Four Ways to Play.
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.
Any Objectself.shown- Component Value
self.shown.timeLimit- Value
data('Modes', global('mode') - 1, 'timeLimit')
A.91 Start Afresh
Built in Chapter 8, Four Ways to Play.
Zen's fresh start: empties the well, counts a reset ($resets), plays All Clear Fanfare and bursts sparkleCount Sparkle Shower over the well.
Any Object- Variable
$resets- Value
0
- Custom Event
wellChanged
- Custom Event
wellReset
- Variable
$resets- Operator
+=- Value
1
- Sound
All Clear Fanfare
- Action Name
freshMiddle- column
(data('Well Layout', 0, 'columns') - 1) / 2- row
(data('Well Layout', 0, 'visibleRows') - 1) / 2
- 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.
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.
- Name
seconds- Value
0
$clockOn == 1- Variable
seconds- Value
global('playTime') - global('clockStart') + global('clockHeld')
- Variable
seconds- Value
$clockHeld
- Value
seconds
A.93 Count Down
Built in Chapter 9, Countdown and Pause.
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.
Any Object- Input Context
Play- Active
No
- Variable
$countdown- Value
@self.countdownSeconds
- Timer Name
"countdownBegins"- First Delay (s)
0- Ring Once
Yes
- Sound
Countdown Beep
- Timer Name
"countdownTick"
- Variable
$countdown- Operator
-=- Value
1
$countdown > 0- Sound
Countdown Beep
- Timer Name
"countdownTick"
- Sound
Countdown Go
- Input Context
Play
- Custom Event
playStarted
A.94 Go On Playing
Built in Chapter 9, Countdown and Pause.
What the RESUME choice does: goes on from the pause (Resume The Game).
Any ObjectA.96 Pause The Game
Built in Chapter 9, Countdown and Pause.
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.
Any ObjectObjects with Panel State- Input Context
Pause
- Sound
Pause Chime
- Input Context
Menus
- Event
When Back Is Pressed- Mode
Resume
- Applies to
@self.pausePanel- Custom Event
panelOpened
- Event
When Back Is Pressed- Mode
While Playing
- Applies to
@self.pausePanel- Custom Event
panelClosed
- Sound
Menu Select
- Input Context
Pause- Active
No
A.97 Restart The Mode
Built in Chapter 9, Countdown and Pause.
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).
Any Object- Paused (1 pause / 0 resume)
0
A.98 Resume The Game (Function)
Built in Chapter 9, Countdown and Pause.
Goes on from the pause: the menu controls go off and Set Game Paused ends the pause (the engine then sends gameResumed).
- Input Context
Menus- Active
false
- Paused (1 pause / 0 resume)
0
A.99 Show During Countdown
Built in Chapter 9, Countdown and Pause.
A text of the countdown (READY, the number): shown from the start of the game until play begins (playStarted).
Any Object- Visible
Yes
- Visible
No
A.100 Show Go
Built in Chapter 9, Countdown and Pause.
Shows "GO!" when play begins (Fade Out Message on the same text hides it again).
Any Object- Custom Event
messageShown
A.101 Show While Paused
Built in Chapter 9, Countdown and Pause.
One part of the pause panel: hidden while the game is played, shown at shownAlpha while it is paused.
Any Object- Visible
No
- Alpha
self.shownAlpha
- Visible
Yes
- Visible
No
