.:: The Complete Ultimate Guide to Homemade Blocks ::.
I've seen many guides to making your own blocks. They are all usually long with many pictures and usually well-written too. But none of them have covered every aspect of this art. To save your time, I have divided this into many chapters out of which you may feel free to skip as many from the top as you need. To help you with that, there is a brief summary at the top of each chapter. There is also a glossary at the bottom for the confused block-builder.
Index
Chapter 1: Opening the system browser
If you know how to open the system browser using the scratch-R method, skip this section.
Chapter 2: The Blockspec
If you know what a blockspec is and know how to make a block appear in your desired pallet, skip this section
Chapter 3: Scripting
If you know how to make a block that works, skip this section.
Chapter 4: Advanced programming
This chapter teaches bits of advanced coding: self functions, temp variable usage, custom lists, and other stuff. This is purely optional.
Glossary
Thanks to sparks for his 'link the chapters' idea.
Last edited by Hardmath123 (2011-01-07 10:00:12)
Offline
This looks like an excellent tutorial! I think i'll read through it later and see if I can learn something new
I would suggest it might be a nice idea to nick the block library layout of linking posts to other posts, so you have a home post followed by links to the chapters, and then a "return to main post", previous chapter and next chapter buttons!
Good job!
Offline
sparks wrote:
This looks like an excellent tutorial! I think i'll read through it later and see if I can learn something new
![]()
I would suggest it might be a nice idea to nick the block library layout of linking posts to other posts, so you have a home post followed by links to the chapters, and then a "return to main post", previous chapter and next chapter buttons!
Good job!
Good Idea!
Offline
Chapter 1: Opening the system browser
Home^
In the top-left corner of the Scratch window, above the 8 different block types, a seemingly innocent Scratch logo has been drawn on. I bet you never could have imagined that logo was the key to all of Scratch. Shift-click the 'R' bit of the logo. You will get a menu. In that menu, one of the choices is 'turn off fill screen'. Click there.
You know how scratch always resizes to fit the whole window? Well, you have just turned that function off. So, as you can imagine, if you make the window bigger than the Scratch pane there will be a blank space between the pane and the rest of the window. Click there.
I bet you're thinking how you're going to remember all this. Don't worry. Once you do it twice, it becomes second nature. Anyway, when you click there, you get another menu. Click 'open', and in the new menu click 'browser'. Congratulationifications. You have opened the system browser. You are well on your way
By the way, if you are worried about the safety implications, just 2 things: in the scratch-R menu, never click save image for end-user. And always turn fill screen back on before quitting. Then you will never lose the real Scratch. Also, do only what has been done by other Scratchers until you feel confident with the Browser. Don't get all exploratory on it
Home^
Last edited by Hardmath123 (2011-01-07 09:56:07)
Offline
Chapter 2: The Blockspec
Home^
Now that you have the browser, let's make a block! Start by clicking on Scratch-objects in the list on the top-left. In the new list, click ScriptableScratchMorph, ScriptableStageMorph, or ScriptableSpriteMorph, preferably ScriptableScratchMorph. Now click the 'class' button. Then open blockspec in the new list and blockspec again in the last list.
Now, in the text editor on the bottom (known as the scripting pane), you will see a ton of scary-looking scripting. Let's break it down into a few parts: the opening, heading, and blockspecs.
The opening is:
blockSpecs
| t1 |
t1 _ #
Don't worry about it. It goes until it says ('control'. ('control' is the heading. Ahead of that are the blockspecs. Blockspecs are the things in individual brackets. Let's break one apart to see it part by part.
Scroll to where it says 'operators' (the next heading). Highlight the blockspec that says:
('join %s %s' #r #concatenate:with: 'hello ' 'world')
This is your join block. How does it work? Start with the part in single quotes. That is the text to be displayed on the block. So why doesn't the block say %s on it? %_ is an inserter. It's basically what you put values into manually, like the number inserter (%n - you can only input numbers), string input (%s - a string is a bunch of symbols, numerical or text), or color input (%c or %C - one shows the color picker, one doesn't). So join %s will be join [] where you can type anything in the []. You can make your inserters, but I will discuss that later.
All the inserters:
Credit to billyedward
a: attribute of another sprite, such as X position or size. b: a boolean inserter c: a colour picker that shows the menu. C: a colour picker that doesn't d: the sprite direction menu/numerical inserter. D: the menu for midi drums e: The broadcast message menu f: math function menu (with sin, abs, etc.) g: menu for the different graphic effects. h: numerical sensor board selector menu H: boolean sensor board selector menu i: midi instrument menu/numerical inserter k: menu for the names of the different keys, used in the key sensor blocks. l: menu with the costume names of the given sprite. L: list name menu. m: sprite list n: numerical inserter N: note name menu/inserter s: string inserter S: sound selector menu v: variable labels menu y: menu used to delete either a number of the last value or all
The next part is the hash followed by a letter (r, in this case). This defines what kind of block it is. Normal stack blocks (#-), reporters like ()+() (#r), booleans like <[] = []> (#b), and c stacks like [if <>] (#c) are the usual ones, but you can also have time-based blocks and special forms, both of which are hard to code. Don't worry about them.
After that you have another hash. This one tells what it broadcasts. What does that mean? Well, every Scratch block is like a broadcast block. It sends the broadcast, then Scratch carries out the scripts called by that broadcast. So, the stuff after the hash is like the name of the broadcast. It can use any symbol except space and colon (
. Colon is there if you need an inserter. As you can see in my example, concatenate:with: says to concatenate (fancy programmer's term for joining 2 strings) input 1 with input 2.
Lastly, you have some terms in single quotes. Those are for default inputs (like join block has default inputs hello and world). Type them in single quotes.
Now that you know what a blockspec is made up of, let's try to make our own. Let's make a ((3) squared) block. Try to make it, then check your answer by highlighting the spoiler below:
|('%n squared' #r #square: '3')|
Now that you have the block in the blockspec, press alt and click on the blockspecs. In the menu, click accept. Then type your initials in the space provided. Then open the pallet of blocks that you put your block in (control, operators, motion, etc.). If you were a good little Scratcher and followed all my instructions, you will be able to drag out your new block!
Home^
Last edited by Hardmath123 (2011-02-15 09:32:06)
Offline
Chapter 3: Scripting
Home^
If you try to use the new block you have made, you will see it doesn't. Instead, you get a pink menu. Click 'abandon' on that menu to close it.
Why doesn't it work? Well, Scratch could understand ((3) squared) in many ways. Maybe you mean a square-root, or maybe you mean draw a square that size in side length.
So, you obviously have to give some more information. This is the code.
To code a block, go to the morph that you put the blockspec in (see chapter 2 for details on that) and click instance instead of class. Now you have a whole other list of options. They are labelled '_ ops'. Choose which category your block fits into the best, or put it anywhere where you will remember where you put it (motion, sensing, etc.). Now you will get the last list. That is the list of all other codes in there. Don't worry about those yet. Instead, go to the bottom part (the scripting pane). As soon as you hover over there, the default text will get highlighted.
Now for the actual code! Codes are of the following format:
The broadcast (second hash). Once you're done, the computer automatically bolds this.
variables (convention is to use t1, t2, t3 etc. They are written between two '|'s and with spaces and the whole thing is tabbed (i.e. | t1 t2 | )
The coding.
So, a code could look like this:
doThis
| t1 |
[coding]
From now on, though, I won't bold the broadcast. And, I will write codes in code boxes which look like this:
code
Now, if a broadcast has a colon (inserter), you type t[a number] and a space after it:
square:t1
add:t1 to:t2
And Scratch automatically formats the rest.
So, so far the coding for our block is:
square: t1
CodingNotice that if there are no other variables, we completely omit the | t1 t2 | bit. And to be technical, those variables are called temps or temporary variables.
Now for the coding. Boolean and Reporter blocks both report things. In Scratch, to report something, you will use ^. So,
report:t1
^t1Will report the input value.
Most of the other commands are the same, but I'll go over them again:
t1*t2 - multiplies both values
t1 + t2 - adds both values
t1 - t2 - subtracts t2 from t1
t1 / t2 - divides t2 by t1
Since ^ reports, for t1^t2 we say t1 raisedTo: t2. And you thought programmers were creative with names.
Note that
a) t1 and t2 can be replaced by numbers (t1 / 5)
b) All brackets are round for arithmetic. Also, the computer may automatically omit some backers. That's ok, just continue.
So, now we can code our block!
Same story as the blockspecs: do it yourself and check against the spoiler:
|square:t1
^ (t1*t1)|
Yes, this does have an if function, too:
square:t1
t1=0 ifTrue: [^0].
[^(t1*t1)]with the format
(input 1) (either =/>/<) (input 2)
ifTrue: [action if true].
ifFalse: [action if false].If the input is already either going to be true or false,
(input)
ifTrue: [action if true]
ifFalse: [action if false].Got it? Good. Once you're done, alt-click and click accept. Now drag out you block and try it!
If it works, post it in sparks' block library (almost always at the top of Advanced Topics forums, I'm not gonna bother adding a link
).
Home^
Last edited by Hardmath123 (2011-01-07 09:56:48)
Offline
Chapter 4: Advanced programming
Home^
This chapter teaches bits of advanced coding: self functions, temp variable usage, custom lists, and other stuff. This is purely optional.
The Self function
If you want to carry out another block's task within your block, you need the Self coding. An example is if you want a block that gives 0 or 1 randomly. This needs the random block. So, you can say:
^ self randomFrom: 0 to: 1
The syntax is
self [broadcast with values after colons]
Remember, if you are using a broadcast to a block that is not included in the normal set, you must mention the coding for that block too.
Using Temps
Temporary variables are especially helpful for changing values. For example, if you want to make a block to report one divided by the input, but if the input is zero it makes the value 1 (so it doesn't report errors), you would use temporary variables. Here's how:
divErrorless: t1
| t2 |
t1 = 0
ifTrue: [t2 _ 1]
ifFalse: [t2 _ t1].
^ 1 / t2where _ sets the temp on the left to the value on the right.
In the system browser, by the way, _ makes an arrow like this : <-. Don't let that confuse you.
Custom lists
This section is sorta long, and is only there to make your blocks fancier. So I suggest you skip it if you are impatient
Say you are making a block called (get constant []) where in the input you input a constant (pi, phi, sqrt 2, i^i, etc.) and it gives out the value (3.141592653). Instead of making a string, you could make a custom list. Then they just choose it from a drop-down menu like the costumes menu.
To get a custom list, choose Scratch-Blocks from list 1 in the Browser, CommandBlockMorph from list 2, -- all -- from list 3 and uncoloredAgMorph: from list 4. You will get:
Code:
uncoloredArgMorphFor: t1 | t2 | t2 _ t1 at: 2. $a = t2 ifTrue: [^ AttributeArgMorph new choice: 'volume']. $b = t2 ifTrue: [^ BooleanArgMorph new]. $c = t2 ifTrue: [^ ColorArgMorph new showPalette: true]. $C = t2 ifTrue: [^ ColorArgMorph new showPalette: false]. $d = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '0'; menuSelector: #directionMenu]. $D = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '48'; menuSelector: #midiDrumMenu]. $e = t2 ifTrue: [^ EventTitleMorph new]. $f = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #mathFunctionNames; choice: 'sqrt']. $g = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #graphicEffectNames; choice: 'color']. $H = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #hookupSensorNames]. $h = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #hookupBooleanSensorNames]. $I = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '1'; menuSelector: #midiInstrumentMenu]. $i = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '1'; menuSelector: #listIndexMenu]. $k = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #keyNames; choice: 'space']. $L = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #listVarMenu]. $l = t2 ifTrue: [^ ChoiceOrExpressionArgMorph new getOptionsSelector: #costumeNames; choice: 'costume1']. $m = t2 ifTrue: [^ SpriteArgMorph new]. $M = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #motorNames]. $n = t2 ifTrue: [^ ExpressionArgMorph new numExpression: '10']. $N = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '60'; menuSelector: #noteSelector]. $s = t2 ifTrue: [^ ExpressionArgMorph new stringExpression: '']. $S = t2 ifTrue: [^ ChoiceOrExpressionArgMorph new getOptionsSelector: #soundNames; choice: 'pop']. $v = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #varNamesMenu; choice: '']. $W = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #motorDirection]. $x = t2 ifTrue: [^ ChoiceOrExpressionArgMorph new getOptionsSelector: #sceneNames; choice: '']. $y = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '1'; menuSelector: #listIndexForDeleteMenu]. ^ ExpressionArgMorph new numExpression: '10'
These are all the inserters. Let's look at one:
$f = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #mathFunctionNames;
choice: 'sqrt'].
This is the math functions inserter (abs, sqrt, sin, cos tan, asin, acos, attain etc.) $f = t2 ifTrue basically means if the inserter is %f (code for math functions), put the math functions list. #mathFunctionNames tells it where to get the list. Because -wait for it- it's like the broadcast system! The data is saved in Other ops, scriptableScratchMorph, Scratch-objects. If you open that up, you will find a block's coding named 'mathFunctionNames'. That's where it's saved. Choice is the preferred entry in the list. To make your own list, first delete all the coding and replace it with:
Code:
uncoloredArgMorphFor: t1 | t2 | t2 _ t1 at: 2. $a = t2 ifTrue: [^ AttributeArgMorph new choice: 'volume']. $b = t2 ifTrue: [^ BooleanArgMorph new]. $c = t2 ifTrue: [^ ColorArgMorph new showPalette: true]. $C = t2 ifTrue: [^ ColorArgMorph new showPalette: false]. $d = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '0'; menuSelector: #directionMenu]. $D = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '48'; menuSelector: #midiDrumMenu]. $e = t2 ifTrue: [^ EventTitleMorph new]. $f = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #mathFunctionNames; choice: 'sqrt']. $g = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #graphicEffectNames; choice: 'color']. $H = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #hookupSensorNames]. $h = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #hookupBooleanSensorNames]. $I = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '1'; menuSelector: #midiInstrumentMenu]. $i = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '1'; menuSelector: #listIndexMenu]. $k = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #keyNames; choice: 'space']. $L = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #listVarMenu]. $l = t2 ifTrue: [^ ChoiceOrExpressionArgMorph new getOptionsSelector: #costumeNames; choice: 'costume1']. $m = t2 ifTrue: [^ SpriteArgMorph new]. $M = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #motorNames]. $n = t2 ifTrue: [^ ExpressionArgMorph new numExpression: '10']. $N = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '60'; menuSelector: #noteSelector]. $s = t2 ifTrue: [^ ExpressionArgMorph new stringExpression: '']. $S = t2 ifTrue: [^ ChoiceOrExpressionArgMorph new getOptionsSelector: #soundNames; choice: 'pop']. $v = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #varNamesMenu; choice: '']. $W = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #motorDirection]. $x = t2 ifTrue: [^ ChoiceOrExpressionArgMorph new getOptionsSelector: #sceneNames; choice: '']. $X = t2 ifTrue: [^ ChoiceOrExpressionArgMorph new getOptionsSelector: #customList1; choice: '']. $y = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '1'; menuSelector: #listIndexForDeleteMenu]. ^ ExpressionArgMorph new numExpression: '10'
If you were careful, you may have noticed that this coding is the same, but with another line
$X = t2 ifTrue: [^ ChoiceOrExpressionArgMorph new getOptionsSelector: #customList1;
choice: ''].
This is your list. Now to customize it. Where it says #customList1 replace customList1 with what your list is (for example: listOfCardinalDirections or popularColorNames) and in the choice put the preferred choice (for example: North or Blue). Now alt-click and click accept.
Now, navigate to Other ops ops from scriptableScratchMorph from Scratch-objects and make a new coding of the form:
what you replaced 'customList1' with
^ #('entry 1' 'entry 2' 'etc.')alt-click and click accept.
Now, make a new block with the blockspec:
('%X' #- #testLists:)and code:
testLists: t1
t1 = t1 ifTrue: [^ self]Now, find that block. Ta-Da! Your custom list is on that block!
Home^
Last edited by Hardmath123 (2011-01-07 09:57:11)
Offline
Glossary
Home^
Congratulations! You have survived the Hardmath guide to custom blocks (considering I am a terrible author). This last chapter is an index tricky terms you may need to know. Enjoy!
Argument: Same as input (see below)
Blockspec: The coding for how a block looks. See Chapter 2.
Boolean: The hexagonal blocks that say either true or false.
Block library: An epic forum thread by sparks, a collection of many blocks made by the Scratchers for the Scratchers. Feel free to post your creations there, as he's nice enough to post anything, however simple. My first block was embarrassingly simple, but he took it in.
BYOB(3): A Scratch modification that lets you build your own blocks. Short for Build Your Own Blocks.
Input: What you feed a block (like in [move (10) steps], 10 is the input)
Mod: Modification to Scratch: Examples are Panther by a lot of people (
), BYOB by Jens, Bingo by LS97, BlockTalk by Jwosty, and Enchanting by I don't know.
Panther: A Scratch modification that lets you build your own blocks.
Reporter: A block that reports values (the oval ones). Like (x position).
String: A set of letters, numbers and symbols (including space). Examples are 'santa claus' '%%_123' and 'Hardmath123'. Always type these in single quotes (apostrophes).
Stack block: The rectangular blocks.
Squeak: The VM Scratch was built in
Smalltalk: The language Scratch was built in.
Home^
Last edited by Hardmath123 (2011-02-05 11:55:55)
Offline
Squeak: The VM
Smalltalk: The language
Squeak Smalltalk: The dialect used for Scratch
I think this is right. Somebody correct me if I am wrong.
Offline
Numbers do not get put in 's for blockspecs. That will turn it into a string insert even if you have %n. I think that argument is any insert in a block (string, num, dropdown, boolean, etc). That is available in Scratch-Blocks -> CommandBlockMorph instance -> private -> uncoloredArgMorphFor:. I always say to add a line instead of replace all. Is the * function (t1 * t2) or (t1*t2)? I agree with TheSuccesor about Squeak/Smalltalk.
Offline
There are a bunch of different args (short for arguments) that can be put in a block. They are:
AttributeArgMorph, which is the get attribute block. This is actually an advanced ChoiceArgMorph. BooleanArgMorph, which creates the boolean inserter. ChoiceArgMorph, which creates a dropdown menu. See ChoiceOrExpressionArgMorph. ChoiceOrExpressionArgMorph, which creates a dropdown menu which can have a reporter put in. See ChoiceArgMorph. ColorArgMorph, which makes the color box. It can either have showPalette: true, or showPalette: false. EventTitleMorph, which is the broadcast menu. EventHatMorph makes the when I receive hat block. ExpressionArgMorph, which creates a typing slot. Both %n and %s are ExpressionArgMorphs. See ExpressionArgMorphWithMenu. ExpressionArgMorphWithMenu, which makes a type slot with a dropdown. It is used in blocks such as: [point in direction (90)], (item (1) of (list) ). See ExpressionArgMorph. SpriteArgMorph, which makes all Sprite dropdown lists.
The others are for making the actual blocks, not inserts.
Offline
scimonster wrote:
There are a bunch of different args (short for arguments) that can be put in a block. They are:
Code:
AttributeArgMorph, which is the get attribute block. This is actually an advanced ChoiceArgMorph. BooleanArgMorph, which creates the boolean inserter. ChoiceArgMorph, which creates a dropdown menu. See ChoiceOrExpressionArgMorph. ChoiceOrExpressionArgMorph, which creates a dropdown menu which can have a reporter put in. See ChoiceArgMorph. ColorArgMorph, which makes the color box. It can either have showPalette: true, or showPalette: false. EventTitleMorph, which is the broadcast menu. EventHatMorph makes the when I receive hat block. ExpressionArgMorph, which creates a typing slot. Both %n and %s are ExpressionArgMorphs. See ExpressionArgMorphWithMenu. ExpressionArgMorphWithMenu, which makes a type slot with a dropdown. It is used in blocks such as: [point in direction (90)], (item (1) of (list) ). See ExpressionArgMorph. SpriteArgMorph, which makes all Sprite dropdown lists.The others are for making the actual blocks, not inserts.
Could you give that in more detail please (you know, the %_ you need to put in).
Offline
Hardmath123 wrote:
scimonster wrote:
There are a bunch of different args (short for arguments) that can be put in a block. They are:
Code:
AttributeArgMorph, which is the get attribute block. This is actually an advanced ChoiceArgMorph. BooleanArgMorph, which creates the boolean inserter. ChoiceArgMorph, which creates a dropdown menu. See ChoiceOrExpressionArgMorph. ChoiceOrExpressionArgMorph, which creates a dropdown menu which can have a reporter put in. See ChoiceArgMorph. ColorArgMorph, which makes the color box. It can either have showPalette: true, or showPalette: false. EventTitleMorph, which is the broadcast menu. EventHatMorph makes the when I receive hat block. ExpressionArgMorph, which creates a typing slot. Both %n and %s are ExpressionArgMorphs. See ExpressionArgMorphWithMenu. ExpressionArgMorphWithMenu, which makes a type slot with a dropdown. It is used in blocks such as: [point in direction (90)], (item (1) of (list) ). See ExpressionArgMorph. SpriteArgMorph, which makes all Sprite dropdown lists.The others are for making the actual blocks, not inserts.
Could you give that in more detail please (you know, the %_ you need to put in).
This is the types you can make. Then you have to choose a letter.
Offline
will custom blocks work when you put them on the srcatch website?
-----------------------------------------Offline
Bobsterman wrote:
will custom blocks work when you put them on the srcatch website?
No. They also won't work if downloaded by someone who has not made the adjustments.
Offline
floppy_gunk wrote:
Argument: Same as the input
Ah.
Offline
Harakou wrote:
Excellent guide!
Thanks!
Offline
TheSuccessor wrote:
Squeak: The VM
Smalltalk: The language
Squeak Smalltalk: The dialect used for Scratch
I think this is right. Somebody correct me if I am wrong.
Happy to do so
Squeak / Squeak Smalltalk: A dialect of Smalltalk (I would say the .NET for VB or C#)
Smalltalk: The basis of the language
SqueakVM: The VM (The 1MB EXE file)
MIT Squeak: A slightly edited version of Squeak to suit Scratch's programming needs.
Again, someone correct me if I'm wrong!
Offline
B_u_m_p
Offline