Text Rendering
Text rendering displays text on the Scratch Stage with more flexibility than the usual use of the Say block, but does require more work. There are two main approaches:
- Rapid repeated use of the Say block, which produces a teletype style in a speech bubble.
- Using a set of sprite costumes to display images of letters.
Text Rendering with Say Block
This is a simple process, requiring two variables: "character number" and "text". The user also needs to define a Custom block, like this:
render text [] :: custom
The block's argument is the text or numbers to be rendered.
Defining the Custom Block
This is the defining script for the custom block:
define render text [string] set [character number v] to [1] set [text v] to [] // No text yet repeat ( length of (string)) // Say the number of letters of string set [text v] to (join (text) (letter (character number) of (string)) say (text) // Says what has been previously said and the new character change [character number v] by (1) // To the next character end
This custom block has been tested.<ref>projects:139541622</ref>
It is imperative not to check the "run without screen refresh" checkbox when defining the Custom block. If it is checked, no text will be displayed. Note also that if the project is run in Turbo Mode, the teletype effect will be undetectable unless a Wait block or other delay is included in the Repeat block.
Text Rendering with a Sprite
The examples in this section use the Stamp block. It is possible to achieve the same visual effect by creating clones: Simply replace each Stamp block with a Create Clone of (myself) block. However, the use of clones has two disadvantages:
- The project will be more prone to lag.
- The Scratch maximum limit of 300 clones limits the number of characters which can be displayed simultaneously.
Attempts at text rendering with sprites can produce unwanted results if the input string contains unanticipated characters.
Without Case Sensitivity
Firstly, obtain or create 26 costumes, one for each letter from a to z. Make sure each costume has the same lowercase name as the letter it represents. It is usually a good idea to have a costume to use as a space character. It is not possible to upload an image file named only with a space, but it is safe to rename it to a single space once it has been uploaded to Scratch. If other characters need to be used (e.g. punctuation and numbers) each will require a costume whose name is the same as the character.
A Custom block (see below) processes the provided text, rendering one letter at a time. It takes three parameters: The text to be rendered, the x position where it will be rendered, and the y position where it will be rendered. It is safe and usually desirable to set this Custom block to run without screen refresh.
define render text(text) at x:(text x) y:(text y) set [old x v] to (x position) //remember original sprite position set [old y v] to (y position) go to x: (text x) y: (text y) //move to text start position set [letter v] to [1] repeat (length of (text)) switch costume to (letter (letter) of (text)) stamp//leave an image of this letter change x by (letter width) //move to next letter position change [letter v] by (1) end go to x: (old x) y: (old y) //return to original position
This custom block has been tested.<ref>projects:139471922</ref>
If all of the characters have the same width, it is safe to stop here. If not, see "Varying Letter Widths" below.
With Case Sensitivity
For case sensitivity, follow the Case Sensing tutorial before following this tutorial. The costumes in the Case Sensing tutorial are required. If any letters/characters outside of a to z need to be used, they will each require a costume whose name is the same as the character. Some characters that would be useful to add include: punctuation, numbers, and more.
The first step is to create a Custom block and to go through each letter of the message to be rendered. This Custom block will take three parameters. The text to be rendered, the x position where it will be rendered, and the y position where it will be rendered. It should also run without screen refresh.
The variable letter will be used to remember which letter is being looked.
define render text [text] at x: (x pos) y: (y pos) go to x: (x pos) y: (y pos) set [letter v] to [1] repeat (length of (text)) change [letter v] by (1) end
Next, switch to the appropriate case sensitive costume. Check the Case Sensing tutorial for how this is done. After one letter has been processed, move onto the next letter by increasing the x position.
define render text [text] at x: (x pos) y: (y pos) go to x: (x pos) y: (y pos) set [letter v] to [1] repeat (length of (text)) switch costume to [null v] switch costume to (letter (letter) of (text)) //if the character is lowercase, it will stay on "null" if <(costume #) = (1)> then //if the sprite never changed costumes due to the letter being lowercase switch costume to (join (character) [t]) //all lowercase costumes end in "t" or a lettered choice (refer to pattern above) end if <(costume #) = (1)> then//if the sprite still has not changed costumes ... //there is a space, a character without a costume, or a costume with an incorrect name ... //assume it is a space else stamp end change x by (10)//change this number for more space between letters change [letter v] by (1) end
If all characters have the same width, it is safe to stop here. If not, see Varying Letter Widths below.
Varying Letter Widths
This section builds on the tutorials Without Case Sensitivity and With Case Sensitivity above.
Because each letter (and character) can have a different width, it is sometimes necessary to take this into account to avoid large gaps between letters and overlapping letters.
To accomplish this, create a list named "Letter Widths". For each costume, enter its width (plus a pixel or two) into the list. Make sure that the costume number corresponds with the list number!
If there is a "null" costume, it also requires a number in the "Letter Widths" list. Because the "null" costume is assumed to be a space, make sure the corresponding list number is the width of a space.
In the text rendering script, replace:
change x by (10)
With:
change x by (item (costume [number v]) of [Letter Widths v])
To test that all of the letter widths are correct, it can be helpful to print out every letter and character supported.
Making a Console
Sometimes, a list might need to be converted into an on-screen console. This is useful for games such as text adventures or RPGs. To do this, first create a list for the rendering script to read off of (call it "console"). So the above script needs to be slightly modified to make this work:
refresh screen define refresh screen repeat until <(length of [console v]) < [21]> delete (1 v) of [console v] end set [list item v] to [0] repeat (length of [console v]) change [list item v] by (1) render text (item (list item) of [console v]) at y: (((0) - ((list item) * (15))) + (175)) define render text [text] at y: (y pos) go to x: (-230) y: (y pos) set [letter v] to [1] repeat (length of (text)) switch costume to (letter (letter) of (text)) if <(costume #) = (1)> then switch costume to (join (character) [t]) end if <(costume #) = (1)> then change x by (5) else stamp end change x by (item(costume #) of [Letter Widths v]) change [letter v] by (1) end
This script will delete any excess items in "console" so that the text can fit on the screen. Make sure that the render script is on "run without screen refresh", or else it will take a really long time to refresh the screen.
To add an item to the console, simply use the "add [] to [console v]" block and the "refresh" block to update the console.
See Also
- Arguments
- Case Sensing
- Clones
- Custom block
- Lag
- Repeat () (block)
- Run without screen refresh
- Say () (block)
- Scratch stage
- Stamp (block)
- Turbo mode
- Wait () Seconds (block)
References
<references/>