Morphic Tiles
Table of Contents
Current Page
Introduction
Abstraction and Architecture
Specifying and Executing a Tile
Control Structures
New Page
Button
Button
Basic Tiles
Primitive Tiles
There are two basic forms of primitive tiles: MorphScriptTiles and MorphSenseTiles. An MorphScriptTile performs an action on a Morph (setFill, go, turn, etc). A MorphSenseTile takes a measurement on a morph (fill, rotation, position, etc) and returns the result for an evaluation. Further, there are UI widget tiles (color picker, rotation setter, text and number input) which permit a user to provide an input parameter for a MorphScriptTile
Architecture and Implementation
The partitioning of Scratch control structures into primitive control structures and scheduling control structures dictates an architecture and an implementation. A primitive tile executes in zero time, as does a sequence of primitive tiles. A primitive script is a sequence of primitive tiles. A script is a sequence of one or more primitive scripts, each of which may be guarded by a control structure. A control structure has both an initiation and a termination; either may be empty. If both are empty the script is just the single primitive script. A script without an initiation guard cannot be preceded by a script without a termination guard; a script without a termination guard cannot be followed by a script without an initiation guard. Use of these two rules makes the partition of any sequence of tiles into scripts unique: there's only one way to partition a sequence of tiles into scripts.
// Main execute loop for a script. Note that all of the logic is built into tile.eval() and tile.continue() this.executeScriptBody = function() { for(; this.activeTileNumber < this.tiles.length; this.activeTileNumber++) { var tile = this.tiles[this.activeTileNumber] tile.eval() if (!tile.continue(this)) return; } } // A repeat_n block has two tiles: a startTile and an endTile. It's an object like this: { countLimit: aNumber, // when this counter expires. This must be >= 0 counter: 0, // current value of the counter. Initially, 0 script: scriptContainingThisTile, // object which is the script containing this tile startTile: { // The start tile of the block. Just sets the counter to 0 on eval eval: function() { counter = 0; }, continue: function(aScript) { return true; // always execute the next tile } }, endTile: { // the end tile of the block. increments the counter and checks to see what the next tile number should be eval: function() { counter++; if (counter == countLimit()) { script.activeTileNumber = script.tileNumber(this) + 1; } else { script.activeTileNumber = script.tileNumber(startTile) + 1; } } continue: function() { return false; } } } // A repeat_until block is very similar to a repeat_n block. The key difference is that it checks to see if the ending event has occured. It's an object like this: { event: anEvent; // the event script: scriptContainingThisTile, // object which is the script containing this tile startTile: { // The start tile of the block. eval: function() { }, continue: function(aScript) { return true; // always execute the next tile } }, endTile: { // the end tile of the block. checks the event to see what the next tile number should be eval: function() { var done = event.hasOccured(); if (done) { script.activeTileNumber = script.tileNumber(this) + 1; } else { script.activeTileNumber = script.tileNumber(startTile) + 1; } } continue: function() { return false; } } } // A wait block just waits for a timer. eval() of the startTile just calculates the end time; continue() // of the endTile just determines if the time has passed { duration: aTimeInMilliseconds, // duration of the wait -- must be > 0 (in fact, must be a multiple of the basic iteration time of this loop endTime: aTimeInMilliseconds, // when the timer ends startTile: { eval: function() { endTime = Date.now() + 1000 } continue: function() { return true; } }, endTile: { eval: function() {} continue: function() { return Date.now() >= endTime } } } // wait_event is just as simple { event: anEvent; // the event to wait on startTile: { eval: function() { } continue: function() { return true; } }, endTile: { eval: function() {} continue: function() { return event.hasOccured() } } } // Finally, forever is just a simplification of repeat: { script: scriptContainingThisTile, // object which is the script containing this tile startTile: { // The start tile of the block. eval: function() { }, continue: function(aScript) { return true; // always execute the next tile } }, endTile: { // the end tile of the block. sets the next tile to the first tile after the start block eval: function() { script.activeTileNumber = script.tileNumber(startTile) + 1; } continue: function() { return false; } } }
Activation, Termination, and Body for Scratch Scheduling Constructs
ConstructActivationTerminationBody
repeat kprevious completed; counter = 0++counter; counter==kany
repeat_untilprevious completedevent occursany
foreverprevious completedfalseany
wait tprevious completed; timer = 0timer = tnone
wait_untilprevious completedevent occursnone
primitiveprevious completedtrueany