Sniff is a "Scratch-like" programming language that's designed to help Scratchers move gently from Scratch to more conventional languages. They can start writing programs, without having to learn a new language because Sniff is based on Scratch. They learn a little more about variables, compiling, syntax errors (!), and they can have fun controlling real hardware while they're doing it.

Sunday, 24 April 2016

Sniff from Scratch #4 : Drawing on the Screen

So far we've covered handling inputs and outputs on the Microbit. In doing this we've introduced a little bit of Sniff, but not by teaching the language - you already know that because you've used Scratch. Rather we've focused on hooking Sniff into meaningful things, like leds and switches which is far more fun! These simple inputs and outputs are easy to handle directly in Sniff, but sometimes you need to interact with more complex devices like the microbit display.

Complex hardware is handled by creating "Devices". These are a little like objects if you've used more advanced languages. If you're fresh from Scratch, then they're just a way of wrapping up a bunch of code someone else has written and letting you easily talk to a piece of hardware. The microbit display device handles drawing on the screen.

make display microbitDisplay device
make displayX number
make displayY number
make displayColor number
make message string


Here we've made a variable (of sorts) called display, which is actually a microbit display. We've also made some other variables which we're going to use to talk to the display. Now for some actual code:

when start
.set displayColor to 700
.tell display to "clear"

Colours in Sniff are (usually) represented by a 3 digit number. If you've written HTML you'll know it uses 6 digits. Sniff is just a slightly simplified version of that. The first digit is the amount of red, the second green and the third blue. Each digit is allowed to go from 0 to 7. But wait a minute - the Microbit display can only do red? That's true, but Sniff runs on lots of different hardware with different kinds of displays. Here we're specifying 700 which is full red, but 700 is full red on all displays. It means we can take this code and run it on different hardware later, with only minimal changes.

Having set a colour we tell the display to "clear". Tell is the only extra thing that's in Sniff that isn't in Scratch. In Scratch when you want to talk to something that's not part of the core system you use an extension, but that causes all sorts of problems, as you end up with dozens of extension, and hundreds of new blocks. In Sniff there's only one "extension" - tell. It lets us send a message to the display device asking it to do something. Different devices understand different messages, but devices which can act as displays have a fairly standard set of message.

Now there's one more think we need to add to get the  display to do something: The Microbit display is actually broken down into three parts. At any time only 1/3 of the display can be lit up. In other languages there's a lot of really fancy code built into the system that automatically lights up different parts of the screen really quick so you can't see it move but in Sniff, its much simpler - we light up different parts of the screen by calling "tick". That means we need an extra script to handle that:

when start
.forever
..tell display to "tick"

You need to include something like this in every Sniff program that uses the microbit display. It might look a bit clunky when you start out, but its actually quite clever - Sniff is doing the work for us that would be much harder to do in another language. You can even add a delay into this loop, and you'll see the different parts of the display light up, so you can really understand how the display works. If your program isn't displaying, then check you've remembered to include this.


The next thing to do is try setting some individual pixels:

when start
.set displayColor to 000
.tell display to "clear"
.set displayColor to 777
.set displayX to 3
.set displayY to 3
.tell display to "set pixel"

This just sets the middle pixel to be fully on.

when start
.set displayX to 1
.repeat 5
..set displayY to 1
..repeat 5
...set displayColor to (displayX+displayY-2)*100
...tell display to "set pixel"
...change displayY by 1
..change displayX by 1

Here we set every pixel on the screen with a colour based on its position. This forms a gradient, with the bottom left pixel being off, and the top right being fill on.

You can draw lines with "move" and "draw":

when start
.set displayColor to 000
.tell display to "clear"
.set displayX to 1
.set displayY to 1
.tell display to "move"
.set displayColor to 777
.set displayX to 5
.set displayY to 5
.tell display to "draw"

Finally we can display text:

when start
.set displayColor to 000
.tell display to "clear"
.set displayX to 1
.set displayY to 1
.set displayColor to 777
.set message to "hello"
.tell display to "show"

This tries to write "hello" on the screen. Unfortunately the microbit screen is rather limited, and all you'll see is the "h" - the rest doesn't fit. To make it fit we'll need so scroll it around:

when start
.set message to "hello"
.set displayY to 1
.forever
..set displayX to 1
..set offset to 1
..repeat until displayX<1
...set displayColor to 000
...tell display to "clear"
...set displayColor to 777
...set displayX to offset
...tell display to "show"
...change offset by -1
...wait 0.1 secs


We start by drawing the text at 1,1 and then change the offset, so the next time around the loop its printed one pixel to the left. After you've drawn some text, displayX tells us where then end of the text is, so when displayX is less than 1 we know we've scrolled the whole message off the left hand side of the screen, and we start again.

You can easily add this script to any of your Sniff programs, so that a message constantly scrolls. In your main script you can measure something and then just assign the results to message, and it will scroll. If you like you could use a slightly different version that just displays the message once:

when showMessage
.set displayY to 1
.set displayX to 1
.set offset to 1
.repeat until displayX<1
..set displayColor to 000
..tell display to "clear"
..set displayColor to 777
..set displayX to offset
..tell display to "show"
..change offset by -1
..wait 0.1 secs

Then in your main script

when start
.set message to "scroll me"
.broadcast showMessage
.say "there's a message scrolling!"

We're starting the showMessage script by calling broadcast,  and just like in Scratch the showMessage script runs at the same time as the main script continues. If you want to wait for the message to complete scrolling just use broadcast showMessage and wait.

This might look like a lot of code just to display a piece of text, but look at what we're actually doing. All of the scrolling, and timing is handled in Sniff. Scrolling a message continuously on the screen while doing another calculation is very hard in most languages, but in Sniff its easy. Of course Python on the microbit has a "displayScrollingMesssage" function built in which does all of this for us, but that's because actually doing it in Python would be too hard. Doing it in Sniff means you can see how it works, and change it around. How about making the text bounce left to right, then right to left?

While we've been specifically talking about the Microbit display, you can use exactly the same code to draw on all sorts of different display hardware, from and LED matrix connected to an Arduino, and GameBoy advance screen, through to an on-screen window on a Mac, or PC. They all use the same commands, so porting the code is just matter of changing the type of device you create, and then maybe adding some scaling to take into account for the different resolution.

No comments:

Post a comment