This week we looked at pixels. Your screen is made up of thousands of them; the picture on it is created by setting each one to the correct colour. We may ask P5 for an ellipse(), but ultimately some piece of code is deciding which pixels to change to the currently selected fill() colour (for the centre) and which to set to the currently selected stroke() colour (for the edges).

Working with Pixels in P5

P5 contains two main functions for working with pixels. The first is loadPixels(). By default it reads all the pixels from the canvas and copies the information into a huge array (or list) called pixels[].

If we then make a change to pixels[], all we have to do is call updatePixels() to copy this information back to the canvas again.

Sound easy? It almost is, but the content of pixels[] isn’t immediately obvious.

Structure of the pixels[] Array

The pixel[] array is one long list of numbers. It is arranged such all the information for the first row on the canvas is first, followed by the information for the second and so on until the bottom of the canvas.

For each pixel there are four numbers representing the red (R), green (G), blue (B) and alpha/transparency (A) value of the pixel. By the time the pixel has reached the screen, alpha has no more meaning, so we will ignore it and concentrate on the RGB values.

This diagram represents what we’ve been talking about:

Getting and Setting a Pixel

To make it easy to get and change the value of a specific pixel we can write two functions:

We wrote three filters, all very similar. Each used loops to go over each pixel in turn, retrieve the current colour, change it in some way and set it back.

The first was fade(amount) which took a number between 0 -> 1 for amount. It multiplied each of the original RGB values from the pixel with this value. The closer to zero amount was, the more it faded the image to black.

The second was invert(). It subtracted each RGB value from 255. This has the effect of inverting all colours in the image.

The final one was vignette(). This is like fade() but fades pixels depending on how close to the edge of the picture they are.

Animating Fade

Finally, we also animated fade() so that the picture started black and got brighter over a number of frames.

Introduction

For our first day back in 2019 we decided to do a simple Paper folding program.

It doesn’t really fold paper though, it just shows you how thick the paper gets when you keep folding it in half! It will get very thick quite quickly!

So we Googled, how thick is a sheet of Paper and we got the number 0.1mm, so quite thin really!

We then Googled a list of items and their heights, so we could write out a message when we reached that height, this was the list we came up with [and a guess of how many folds it would take]:

Paper: 0.1mm

Baby: 530mm

Human: 2 Meters [50]

Dublin Spire: 121m

Croagh Patrick: 764m

Burj Khaleefa: 828m [10,000]

Carauntoohill: 1038m [1 billion]

Mount Everest: 8848m

Galway to America: 6603km [25]

Space: 100km

Moon:300,000km

Mars: 56,000,000 km

Sun: 150,000,000 km

Pluto: 7,500,000,000 KM

The Program

In order to keep track of how many folds we have done and what height the paper has reached we needed a few variables:

We store the number of folds, and the height in mm, meters and kilometers.

folds – to store how many times we have folded the paper

mm – to store the height in milimetres

metre – to store the height in metres

km – to store the height in kilometres

We then made sure that they were all set to the correct value when the Green Flag was clicked.

The only one that is not zero is the height in mm which we set the thickness of paper 0.1

Now we can get coding.

We used the Up and Down arrows to fold/unfold the Paper, this would increase/decrease the number of folds and the mm height and then Broadcast to the code that checked everything else.

The code that does the checking needs a few IF’s to work out what to do. First of all though it needs to calculate the height in Metres and Kilometres as well.

We used the number of folds to work out if we should be checking the mm, metre or km variable. All we did when we got to a particular height was to Say something on the Screen, but you could do anything you want at these points in the code, maybe show a different sprite or make a sound or something.

This is the code that checked the mm and metre variables

and this is the code that checked the metre and km variables

And if anyone wants the full project, it is availabe on the scratch.mit.edu web site:

Introduction

This week we looked at both the Progam project and the Recursion (Branching) project. with a plan to get the output of the Recursion project be the input of the Program project.

The 2 Projects

Program Project

The Program project that we did a couple of weeks ago can read a list of commands and get Scratch to perform those commands. We programmed it to be able to:

Put the Pen Up or Down (P:0 or P:1)

Move some steps (M:100, where 100 is the number of steps)

Turn in a different direction (T:90, where 90 is how far to turn)

Each Command was identified by the First Letter.

Recursion Project

The Recursion project that we did last week can draw a branching Tree pattern. The commands it uses to draw the Tree are:

Pen Up and Down

Move some steps

Turn in a different direction.

Joining them together

The Recursion Project changes

You can see that the Recursion project using the same commands as the Program project, but in order to get the commands from the Recursion project to the Program project we have to add some code to the Recursion project.

First job is to create a List, we called it Commands as it will store all the commands that we have run.

We then need to read through the code and wherever there is a Pen Up, Pen Down, Move or Turn we need to add an item to the Commands list.

This is the code and I have highlighted where

You can see that I have marked 7 places where we need to add code to Insert into commands.

When the Inserts are added the code will look like this, just remember that the Insert has to put in the Command letter that Progam needs Joined to the same action that the Recursion code is doing. All the entries go in the last place in Commands.

You can see that we have added a delete all to start and then after the Pen down we have added a P:1 to the last place in Commands.

On the Pen up we have added a P:0 to the last place in Commands.

Then we did the same to the Code that did the drawing of the Branches.

Notice that all the Inserts use a JOIN block, the first section is the Command letter that the Program project is expecting, the second section is the exact same code from the code block above.

For example when the code turns Degrees * -2 the insert also has Degrees * -2 in the second section of the JOIN.

If we run the Recursion Program now, the Commands list will end up with lots of commands, if you have 10 Branches it creates 5117 Commands!

You can see that Commands starts with a Pen Down (P:1) and then starts all the Moves (M:…) and Turns (T:…) and when the Tree is finished there are 5117 items in Commands.

Next step is to Export the Commands to a file. This is simply a case of Right Clicking on the Commands List and selecting Export, just make sure you add a .txt to the file name and also remember where you saved it!

The Program Project changes

Now we switch projects and open the Program Project.

First thing we changed was to remove all the test code, add some instructions and move the broadcast Play to when the space key pressed.

Next step, click the green Flag and follow the instructions.

So right click on the Program List and Import the file that you Exported from the Recursion Project. And then press the Space key…

Hmm, not quite what we were expecting, but close, the Tree is on it’s side and the drawing has started in the centre of the screen rather than at the bottom.

This test has highlighted a number of problems with our Program Project. We don’t have any code to set the Direction of the Sprite or the X and Y Positions.

Well that is easy to fix, we just add some more Command Letters to our Programming code:

D:nnn – This will set the Direction to point in, where nnn is the Direction to point in.

X:nnn – This will set the X Position, where nnn is the X position.

Y:nnn – This will set the Y Position, where nnn is the Y Position.

This gave us 3 more IF sections in our code like this:

You can see that the new commands are almost the same as the old ones, we just change the letter we are looking for and the code block that gets run if we find one of the New letters.

So D:0 for example will run the Point in Direction code with the value 0 (Up).

The Recursion Project – more changes

Now this where we have to jump back to the recursion project and add some more Inserts so we can set the correct direction and the correct X and Y positions. Again this is not too difficult, we just look for code that sets the direction or X and Y Positions and add some Inserts into the Command list.

You can see 3 extra insert code blocks, 1 for the point in direction code and 2 for the go to x: y: code block. We have to add 2 here because our Program project is very basic and doesn’t know how to do a Go To…

The Commands List will now get 3 new entries at the beginning and have a total of 5120 commands now. Don’t forget to Export this new list to test the Program project again.

And Finally

Program Project – test 2

Now that we have the Recursion project writing out the extra Direction and X and Y commands we can test again in the Program project.

And, test 2 is a little better than test 1.

It’s still not perfect, the line is all the same thickness and the colour is always the same.

But you could easily add some more Program letters to add this extra functionality.

Notes:

As always the code is on the Scratch web site, I have added 2 projects that should produce the results you see above:

The main purpose of this week’s session was to explore the idea of transforms by using them to make a little top-down tank that we could drive about the screen. I close a tank because:

It’s easy to draw a recognisable tank with a few simple shapes

It’s easy to see which way is forward

Tanks move in a very simple way (either turn or drive forward or backwards)

Origin and Axes

We don’t often use the word, but the top left of the screen (0, 0) can be referred to as the origin.

Another useful word is axes (plural of axis). We have two axes in 2D – the X-axis which normally runs horizontally left-to-right on the screen and the Y-axis that runs top-to-bottom.

Transforms

With these words in hand, let’s talk transform. P5 has three functions that allow us to make transforms. Once we call them, they effect everything that’s subsequently drawn. Here they are:

translate() – Move the origin by a given amount along the x and y axes.

rotate() – Rotate about the origin (wherever it currently is).

scale() – Scale along x and y axes.

Design of our Tank class

Our Tank class has five main things:

A constructor that takes and stores a vector for the tank’s position [this.pos]

A property to store the tank’s angle [this.angle]

A function to draw the tank [draw()]

A function to tell the tank to turn left/right [turn()]

A function to tell the tank to drive forwards/backwards [drive()]

We draw our tank as if it’s centered on (0, 0) and facing right. We then can use translate(this.pos) to move it and rotate(this.angle) to change its angle.

For turn() all we need to do is to to change this.angle by a requested amount.

For drive(), we do a little more. We:

Create a copy of the current position

Create a vector (1, 0) which is facing right (representing the tank’s forward direction)

Multiply that vector by how fast we want the tank to move

Rotate that vector to point in the tank’s actual direction this.angle

Add to the copy of the current position we took initially

Check that new position to make sure we wouldn’t end up off-screen and, as long as we we wouldn’t, update the tanks actual position this.pos

Getting user input

We then need to get input from the user. In sketch.js we created a new function getInput() and put a call to it in our draw() function.

In getInput() we just look for the arrow keys. If we see Left or Right then we tell the tank to turn. If we see Up or Down we tell the tank to drive. We use the P5 function keyIsDown() for this.

Download

The files for this week can be found on our GitHub repository. The actual files uploaded have expanded the game a little. There are now two tanks and the Tank constructor takes two new arguments for the tank’s colours. The second tank is controlled not with the arrow keys but with WSAD and we use the P5 variables keyIsPressed and key to detect those being held down (as they’re different to the arrow keys).

Introduction

This week we created another drawing program using recursion, code that calls itself.

This drawing program will draw a Tree with 2 number of Branches, each Branch will split in 2 and be a little smaller than the previous Branches, The Branches will split X number of times. The finished picture will look something like this when X = 5:

You can see that each branch splits into 2 new branches which are a little thinner and a little shorter than the previous branches, just like a real tree.

The Plan

Very simple plan for this one, we wanted to be able to control:

the amount of branches

how many degrees the split should be

and what size the first branch would be

So we created a variable for each of these and left them on the Screen as a Slider. We set some minimum and Maximum values as well.

Branches (1-10)

Degrees (0-180)

Size (30-100)

The Code

As always we have some code that initialises everything when the Green Flag is clicked.

We point upwards, we go to the middle of the bottom of the screen, clear everything, set the Pen colour and then call our code with the values from the Sliders.

Improvement : This should be “When Spacebar Pressed”, then we could just adjust the Sliders and then click the Spacebar to see the next tree.

The recursive code

This is the code that calls itself, because the Branching code is just the same thing repeated over and over again, but with slightly different values (the branches are getting smaller) it is ideal to use recursive code. You just need to remember that the code next to be able to finish.

The code has two values sent in the number of branches and the size of the branches.

First thing we do is check to see if the number of branches is > 0 otherwise we exit, this is our way to finish the code.

We move (draw the branch), turn and then call ourself with slightly different values.

We put the call to background() in the setup() function because we didn’t want to clear the background every frame. After that, in the draw() function, we just needed to draw an circle at the mouse’s position every time the mouse button was pressed.

This gave us an very basic painting program in just a few lines of code!

Toolbar

We then looked at the idea of a toolbar to contain buttons for selecting colours and the size of the brush.

We first need to decide where it would be (the left side of the screen) and we created a variable toolbarSize to store the width of it.

In the draw() function we then added a check not to draw an circle if we were inside the toolbar area.

We then added a new function called mouseClicked(). This is a special function name (like setup() and draw()) that P5.js will call at the appropriate time. In this case its called when the mouse is clicked (button pressed down and the released).

Colour and Sizes

We created two arrays to store a list of colours and brush sizes at the top of our script:

To draw the toolbar, we made a new function called drawToolbar() and put a call to it in our draw() function. In the new function, we looped over the colours array, drawing a new button, filled with the respective colour and then another loop over sizes drawing a square with a circle inside to represent the brush size. We needed to scale those circles to make them fit inside our buttons.

Detecting Selected Button

Since everything in our toolbar was toolbarSize high, to determine what had been clicked on, we just needed to divide mouseY by toolbarSize to get the index of the button that had been clicked on. We looked at that index, if it was less than the number of colours, we must have clicked on a colour. If greater, it had to be a size (or beyond the end).

Selected colours and selected sizes were stored in two variables called currentColour and currentSize respectively and used within the draw() function when creating our circles.

Featured Artwork

Mark suggested that people draw a portrait of me to test our new program and there were some brilliant renderedings. Three people were kind enough to share theirs with me so that I could put them here. I think they’re great!

This week we started looking at physical computing and the Raspberry Pi. This involves attaching various components such as sensors, motors or controllers to the GPIO pins on our Pi. This week we connected a LED and two buttons, and we used the GPIO Zero module for Python to control them. I’ve made a video, it’s a little bit long, that covers everything from Saturday’s session.

At the end of the session the group started working on a traffic light idea and we will combine this with HC-SR04 ultrasonic distance sensor next week to create a measuring device.