Creators: Shootah Part 6 – Enemy Shooting Back

alien

This week we did our last iteration on Shootah and added a Bomb to be dropped by the enemy to try to hit the player.

Bomb Class

We copied the existing Bullet class and called it Bomb instead. The main changes we had to make were:

  1. Changing the speed to a negative number so that it moved down instead of moving up (as the Bullet does)
  2. Changed the check for the top of the screen to one for the bottom of the screen instead (to account for the fact it moves down)
  3. Changed the check in its hit() function so that the Bomb doesn’t interact with the Enemy when it’s dropped, but will be marked as inactive it if hits anything else.
  4. Changed the colour of the bomb to red

Manages Bombs

It happened that the code we had already written to manage bullets was already perfect for managing bombs as well.

We used Visual Studio Code’s built-in capability to automatically rename symbols to:

  1. Rename the bullets array to projectiles
  2. Rename the manageBullets() function to manageProjectiles()

This was enough to have bombs move, draw and be removed when it becomes inactive.

Dropping Bombs

We added a new function to Ememy called shoot(). In that function we generated a random number from one to two hundred. We then dropped a bomb every time that number was less than five (we tuned this small number to get a good rate of bomb drops). This meant that the enemy dropped a bomb at random intervals, to make it impossible for the player to anticipate.

Download

The files for this week can be found on our GitHub repository.

Creators: Shootah Part 5 – Edges

spaceship.png

This week we extended our colliders so that we could used them to prevent the player going off the edges of the screen. We used it to show how software design needs to evolve.

Colliders

Our colliders were designed to be connected to an object with three things:

  1. A property  containing the x-coordinate of its location
  2. A property y containing the y-coordinate of its location
  3. A function hit() which was called if the attached collider touched another collider

Something to Connect To

We had colliders already attached to our:

  1. Enemy
  2. Bullets

but we didn’t have anything to attach to that could represent the side of the screen.

We created a new class called Static() with nothing more than the x, y  and hit() that we needed so that we could connect a collider to it (stored in one more property – collider).

Screen Edges

We created a pair of these colliders positioned at the right and left-hand side of the screen. We made sure to add them to our list in check_colliders(). Nothing much happened. Why? Well, first, the Player didn’t have a collider, so we added one, liberally copying code from Enemy, which a minor change to the description argument.

Now we could see the contact occurring between the edge and the player, though nothing was stopping it moving yet.

Unintended Consequences

As  often happens with code, this change had unexpected consequences; bullets were not firing properly any more. Why? Because the player now had a collider and the bullets were becoming inactive immediately because they were hitting that. The fix was to modify the Bullet’s hit() function to ignore hitting a collider with the description “player”.

Stopping the Player Moving

We now knew our player was hitting an edge, but another problem became apparent: we didn’t know which edge!

To properly stop the player and stop it moving too far, we really needed to know which side of the player the collider we’d hit was, but that information wasn’t available to us with the current design.

A couple of quick changes were necessary:

  1. In Collider.touching(), instead of just passing the descriptors to the objects hit() functions, we changed it to pass the Collider itself.
  2. In all the hit() functions, we had to made a small adjustment to account for the fact that we were now getting a Collider and not just a string.

With the extra information from the collider, were were able to determine how far the player should be allowed to move to and prevent it going further by setting the x value appropriately.

Download

The files for this week can be found on our GitHub repository.

Creators: Shootah Part 4 – Colliders

 

This week we mainly dealt with building and using a box collider in our game. The box colliders are written in a way such that:

  • They are connected to something in the game and follow it around
    • What they are attached to must have the properties x and y for position
  • It is possible to test if they are touching each other
  • If two colliders are found to be touching, we tell the things that they’re attached to that they’ve been hit by something
    • What they are attached to must have a function hit() that we can call

 

Extents of the Collider

Our collider is a box, of a given width and height, centred on the x and y of the thing it’s connected to:

Untitled Diagram

For checking collisions, we need to know the values of the left and right side of the box and the y values of the top and the bottom of the box.

For convenience, we write a function which returns an object (using curly brackets) with the left, righttop, and bottom values (shortened lr, t and b respectively) as properties:

extents(){
  return {
    l: this.connected.x - this.width / 2,
    r: this.connected.x + this.width / 2,
    t: this.connected.y - this.height / 2,
    b: this.connected.y + this.height / 2
  };
}

When making an object like this, we set a property value by first writing the property name, followed by a  colon (:)  and then a space and the value we want it to have. Each property is separated with a comma. The don’t need to be on separate lines, but it makes it easier to read.

 

Touching Colliders

So how do we know that two colliders are touching? Actually there are four ways in which they definitely can’t be touching:

  • One is completely to the left of the other
  • One is completely to the right of the other
  • One is completely above the other
  • One is completely below the other

And if none of these are true, then it must be touching. So actually, we’re going to check that they’re not NOT touching (double negative, used correctly!).

How do we know if something is completely to the left of something else? Look at this diagram:

 

Untitled Diagram (1)

We know that box 2 (in blue) is totally to the left of box 1 (in orange) because we can see it is, but how could get the computer to check it? Remember, left and right are just x values on the screen. Box 2 is left of box 1 because both it’s left and right values are smaller than the left value of box 1.

The checks for the other directions are very similar:

  • The second box is right of the first box when both of it’s x values (left and right) are greater than the first’s right side.
  • The second box is above of the first box when both of it’s y values (top and bottom) are less than the first’s top side.
  • The second box is below of the first box when both of it’s y values (top and bottom) are greater than the first’s bottom side.

 

Sending Messages

Each collider has a property disc that describes the thing, or type of thing, that it’s connected to.

All colliders know what they’re connected to, so when we determine two have touched, we call a function called hit() on each of the connected objects, passing it the desc of the other collider. This means, in our game, when our enemy is hit, it can know that it’s been hit by a bullet – or maybe something else – and react appropriately.

 

Checking Every Collider Against Every Other

In our code, we gather all the active colliders at each frame. We then need to check each one against each every other one. How can we do that?

Consider a list of four items:

Untitled Diagram (2)

To check them all against each other we first need to check 0 against the other three. Simple enough.

We we need to check 1. But we don’t need to check 1 against 0, since we already did that. Nor do we need to check it against itself. We only need to check it against 2 and 3.

If we write out the full sequence, we see that for four items we need three passes to check all combinations:

  • First pass: Check 0-1, 0-2, 0-3
  • Second pass: Check 1-2, 1-3
  • Third pass: Check 2-3

We can write a pair of loops to do this:

for (let i = 0; i < c.length - 1; i++){
  for (let j = i + 1; j < c.length; j++){
    c[i].touching(c[j]);
  }
}

Note two things about these loops:

  • The first loop goes from zero, but stops one short of the last item in the list (i < c.length – 1). It picks the first item to be checked.
  • The second loop doesn’t start from zero. It starts from what ever i currently is, plus one. It picks the second item to be checked.

 

Other Stuff

We also did a few other things this week:

  1. We fixed a small bug that was keeping our spaceship moving when we didn’t want it.
  2. We added a little drag to slow the spaceship down to a stop when we lift our fingers off the keys
  3. We set bullets inactive when they hit something

 

Download

The files for this week can be found on our GitHub repository.

Creators – Shootah Part 3 – Enemies etc.

This week we continued our Shootah project. We did two main things;

  1. Changed the code to control the total number of bullets to those actually on screen
  2. Added an enemy that loops backwards and forwards across the screen

Controlling the Number of Bullets

In Part 2, we made a new bullet every time the user pressed the Up key and put it in the bullets list.

This meant that after a while we could have a lot of bullets, most off the top of the screen, which was even slowing some machines down.

To limit the number of bullets we did four things:

  1. Added a new property to the Bullet class called active and set it to be true
  2. In the move() function for the bullet class, we added a check for the bullet going off the top of the screen (this.y < 0) and, if true, set the active property to false
  3. In sketch.js, we moved the lines of code in the draw() function responsible for moving and drawing the bullets into a new function called manageBullets() and called it from draw().
  4. In manageBullets() we made a new list called active and put every bullet that was still active into it. We then made this the new bullets list.

We write a little code that printed out the total number of bullets to verify this was working.

Adding an Enemy

We added a new file called enemy.js and included it in the index.html file.

This file looked a lot like player.js. The main different was the move() function. Our enemy moves constantly left-to-right. When it gets too far off the right-hand side of the screen (checked in move()) we set its x position to be off the left-hand side of the screen instead. This makes it loop around.

TODO

We still have loads to do and we made a list on the day:

  • No more infinite bullets!
  • Check edges so spaceship doesn’t disappear
  • Enemies
  • Collision detection
  • Enemies shoot back (bombs)
  • Lives/score
  • Levels
  • Background music
  • Moving background
  • Story

We’ve done two and we’ll do some of the others for sure.

Download

The files for this week can be found on our GitHub repository.

 

Creators – Pixels

543px-Liquid_Crystal_Display_Macro_Example_zoom

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:

pixel diagram

Getting and Setting a Pixel

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

  • getPixel(x, y) which returns an array containing [r, g, b] values
  • setPixel(x, y, colour) where colour is an array containing [r, g, b] values

Both these functions rely on knowing where in pixels[] the data for the pixel at (x, y) is.

We can work out this as:

  1. Location of R: 4 * ((y * width) + x)
  2. Location of G; Location of R + 1
  3. Location of B: Location of R + 2

Knowing this, the functions can be written as:

function getPixel(x, y){
  let loc = 4 * ((y * width) + x);

  return [pixels[loc + 0],
          pixels[loc + 1],
          pixels[loc + 2]];
}

function setPixel(x, y, c){
  let loc = 4 * ((y * width) + x);
  
  pixels[loc + 0] = c[0];
  pixels[loc + 1] = c[1];
  pixels[loc + 2] = c[2];
}

FIlters
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.
Putting all the filters together:

Download

The files for this week can be found on our GitHub repository.

 

 

Demos and Pizza – Christmas 2018

Here are photos from our Christmas party and Show & Tell day at CoderDojo Athenry on 08 December 2018.

This slideshow requires JavaScript.

It was fantastic to see the things that our young people had created.

We are very grateful to our supporters in the community around Athenry:

  • Clarin College and Principal Ciaran Folan, who are so generous with their space every week
  • Galway & Roscommon Education & Training Board, who provide us with an annual Youth Club Grant
  • HEA (Higher Education Authority) and NUI Galway School of Computer Science, who provide us with funding towards equipment.
  • Medtronic and Declan Fox, who have provided us with a grant linked to Declan’s volunteering
  • Hewlett Packard Enterprise and Mark Davis, who provide us with loaner laptops
  • Boston Scientific and Kevin Madden, who provide us with the loan of 3D printers.
  • Supermacs, who gave us a great deal on the food for the Christmas party

And of course, we are eternally grateful to our wonderful mentors, and to the parents who come along with their children every week. Thank you!

Creators – Tanks

tank-1530043_640

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).

Creators – Painting

watercolors-854491_640

This week we looked at making a painting program.

We started with three built in P5.js variables:

  • mouseIsPressed – true whenever the mouse button is held down
  • mouseX – contains the X position of the mouse pointer
  • mouseY – contains the Y position of the mouse pointer

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:

let colours = ['black', 'white', 'red', 'blue', 'green'];
let sizes = [5, 10, 20, 40, 80, 160];

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!

Download

The files for this week can be found on our GitHub repository.

Creators – Pattern

washer-machine-porous-mechanical-83852

This week we looked at two important concepts, loops and lists.

Loops

Start by imagining we wanted to draw four circles next to each other. We could write four calls the ellipse function, like this:

let size = 50;

ellipse(25, 25, size, size);
ellipse(75, 25, size, size);
ellipse(125, 25, size, size);
ellipse(175, 25, size, size);

Pretty easy. What if we had variables for the positions? We’d get this:

let size = 50;
let x = size / 2;
ley y = size / 2;

ellipse(x, y, size, size);
x = x + size;
ellipse(x, y, size, size);
x = x + size;
ellipse(x, y, size, size);
x = x + size;
ellipse(x, y, size, size);
x = x + size;

It’s longer than before, but notice how the same two lines now keep repeating. If we had a way to say “do these two lines four times” then this would get much shorter, and we do. We use the for statement:

let size = 50;
let x = size / 2;
ley y = size / 2;

for (let i = 0; i < 4; i++){
  ellipse(x, y, size, size);
  x = x + size;
}

The for statement is a bit complicated, so let’s break it down:

for (do first; check to see if we keep going; do every time 2) {
  do every time 1
}

Note the curly brackets (braces) containing the stuff we want repeated.

So in our case we:

  1. First create a new variable called i and give it the value 0
  2. Check to make sure that i is less than 4
  3. Draw our ellipse and make x bigger
  4. Increase i by 1
  5. Go back to step 2 and check if we can keep going, otherwise stop

This means that i will have the values 0, 1, 2 and 3 and our two lines will be run four times in total. Result! Our code can draw a row of circles. If we increase the value in the check, we can have as many as we like. We choose to have 8.

Nested Loops

Nesting a loop means putting one loop inside another. What’s the point of that? Well in our case we have a loop that can draw a single row of circles. If we put all of that inside another loop we could draw several rows. The row outside has a different variable j and also runs eight times. After we draw our row we do two things:

  1. We make y bigger move down the screen
  2. We move x back to the left to its starting position for the next row

The code now looks like this:

let size = 50;
let x = size / 2;
let y = size / 2;

for (let j = 0; j < 8; j++){
  for (let i = 0; i < 8; i++){
    ellipse(x, y, size, size);
    x = x + size;
  }
  y = y + size; // Move down and
  x = size / 2; // Back to the left
}

We now have 8 x 8 = 64 circles in a grid.

Changing the Colour of Some Circles Based on a Check

We then added code just before our call to ellipse() to change the colour based on some check:

if( /* some check here */ ){
  fill("red");
}
else {
  fill("white");
}

We experimented with some different checks to see what might happen. This check turns the upper-left of the grid red:

if (i + j < 8 ){ 
  :  :  :

This check, using the modulus operator, turns every third circle of the grid red:

if ((i + j) % 3 == 0){ 
  :  :  :

This check paints a red cross through the centre of the grid:

if (i == 3 || i == 4 || j == 3 || j == 4){ 
  :  :  :

Lists

We then jumped quickly into lists. Also called arrays, lists are like a variable that can store several values. We create them simply like this:

let a = []; // An empty list
let b = [1, 2, 4, 7]; // A list created with four entries

To get at the entries in a list you just use the list variable’s name and square brackets containing the number of the entry in the list you want to get out, noting that the first one is zero:

b[0] = 10; // Set the first entry in the list to ten
b[4] = 301; // Set the fifth entry in the list to three hundred and one

A list isn’t just for holding numbers though, it can hold anything. It can hold strings for example, or even other lists!

It’s this idea of holding lists that we use to define our pattern.

Defining our Pattern

We make a list with eight entries, each of which is a list also containing eight entries, all zero. We write it so it forms a neat block like this:

let pattern = [
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0]
];

Then down in our code, where we’re deciding what colour to make our circles, we change the check to read:

if (pattern[j][i] == 1){  
  : : :

What does this mean? Well, j is a counter that goes from 0 -> 7 as we go down our eight rows. Given that, pattern[j] means get entry from our list for that row. Since pattern[j] is a list too, we need to say which entry we want in. The variable i goes from 0 -> 7 as we go across each row. So, pattern[j][i] gets the list for the row and then picks out the number for that column.

Once it’s set up, we can then change zeros to one in our pattern and have our circles turn red to match (red in the text below to make them stand out):

let pattern = [
  [0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 1, 0, 0, 1, 0, 0],
  [0, 0, 1, 0, 1, 0, 0, 0],
  [0, 0, 1, 1, 0, 0, 0, 0],
  [0, 0, 1, 1, 0, 0, 0, 0],
  [0, 0, 1, 0, 1, 0, 0, 0],
  [0, 0, 1, 0, 0, 1, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0]
];

Screenshot 2018-10-15 at 18.14.34

We have essentially built something that works like an image file! Our pattern is the image data and our program is the code that draws it.

As several smart people already noticed, you’re not limited to one and zero. By using more numbers, and expanding the if statement, you can have as many colours as you like.

Download

The files for this week are on our GitHub, as always.

Creators – Basic Scripting

Screenshot 2018-09-30 at 11.22.16

 

This week we were joined by some additional ninjas, welcome! We had to do a little revision of the first week’s content and probably didn’t manage to get quite a much done as I’d hoped.

Let’s review what we did manage to get done.

Embed a simple script in a web-page

The first thing we did was to create our folders for this week and then create a brand new HTML file called index.html. We then embedded a simple script in our html file using the tag, like this:

window.alarm("I'm alarmed");

When we opened our page in Chrome, our message popped up as an alert.

Seperate that script into its own file

We then created a new file in our folder called script.js. We cut out everything from in between our and tags and pasted it into this new file:

window.alarm("I'm alarmed");

and in our HTML file we gave the tag the name of this file instead, using the src= attribute (short for “source”) :


Our script continued to work as before, as we’d hoped.

The advantage of moving scripts into their own files is that as we get more scripts and these scripts get more complex, keeping them all within the HTML file gets messy and difficult to work with.

Developer Tools

The developer tools build into Chrome, and some other browsers, help us see what is happening with our pages and scripts and helps us to fix them when they’re not working correctly.

To open the developer tools, open the menu in Chrome (the three dots in the upper-right of the program) and select More Tools | Developer Tools.

The console, part of the developer tools, is a place for us, as programmers, to write out things that will help us check if our script is doing what we want it to do. Ordinary users never see what developers write to the console.

To write to the console, we changed our script.js to read:

console.log("I'm alarmed");

The message box stopped appearing and this message could only be seen by looking at the console.

Basic Script Concepts

The most important basic concept in programming is that of a variable. A variable is just a place to store something and a name to refer to it by. We can make a new variable, in this case called a, like this:

let a;

The first word, let, is known as a keyword and tells JavaScript “we’re going to make a new variable”. The name of the variable, in this case a, comes next and finally a semi-colon (;) to show that this line is finished. The semi-colon is how we mark the end of a command in JavaScript and it’s an easy thing to forget.

We quickly made this example more complex:

let a = 4;
let b = 5;
let c = a + b;

console.log("c");
console.log(c);

In this extended example we defined three variables called a, b, and c respectively. Not only do we define them, we also assign them a value (using the operator =) at the same time. The first two are just given a simple value, but c has a value calculated from adding a and together.

The two console.log() line are to show the difference between actually writing the letter c to the console (as in the first line) and writing the value of the variable called c to the console (as in the second line).

Strings

Strings are how we hold a piece of text in a program. Strings are surrounded by quotations marks:

"This is a string"

I didn’t mention the last day, although I mean to, that JavaScript also allows strings with single quotes, which many other programming languages do not:

'This is also a string'

We experimented with changing our script so that instead of numbers we set our variable to strings:

let a = "4";
let b = "5";
let c = a + b;

console.log("c");
console.log(c);

and in the console saw the perhaps surprising result:

c
45

We determined that when we have two number variables the operator + does normal addition but when one or both are strings it makes a new string with the two stuck together (this is often called “concatenation”).

We introduced the following four mathematical operators:

  • + : Plus does addition
  • – : Minus does subtraction
  • * : Asterix does multiplication
  • / : Forward-slash does division  (don’t confuse with back-slash \)

Conditions

We looked at a simple condition. This allows us to choose between two options based on whether a check was true or not:

if (c < 1){
  console.log("c is less than one")
}
else {
  console.log("c is greater than one")
}

The keyword if  starts this check. The thing we’re testing is then inside roundy brackets (). Here we’re checking “is c less than one?”. After this we get a block of code (contained in the curly brackets {}) to do if it is true. Here we’ve also added (which is optional, you don’t have to have this if you don’t need it) the keyword else and another block of code to do if it is not true.

Basic Functions

Functions perform an action. They contain a bunch of commands to run together.

They’re great where we’re doing the same thing repeatedly but from different places and they help to logically break-up and organise our scripts.

Here’s a basic function that just writes to the console:

function SayHi(){
  console.log("Hi");
}

The keyword function indicates that we’re going to define a function. Next comes the function name, SayHi in this case, followed by roundy brackets (), followed by a block of code surrounded by curly brackets {}. Inside the curly brackets are the commands that make up this function.

To make this function actually run we need this in our script:

SayHi();

Without this the function would never run. Functions only run when we “call” them.

Function Arguments

Sometimes it’s nice to be able to give a function more information about what we want to do. A function can take several values as input, these are called arguments.

Let’s imagine we don’t want our function to log the same thing to the console every time. We want to tell it what to write. Let’s see what that looks like:

function MyFunction(what){
  console.log(what);
}

MyFunction("Testing the function");

Here our function is defined as before, but we have a name, what, inside the roundy brackets. Firstly, this means that when you call the function, you’re expected to provide a value. Secontly, inside MyFunction(), we have a new variable, here called what, containing the supplied value and usable like any normal variable.

Finally here’s a more complex example with two arguments:

function Divide(m, n){
  return m / n;
}

There’s a new keyword here, return. This means “send back this value to the place that called me”. Let’s see how we might use it:

let a = 4;
let b = 5;
let c = Divide(a, b);

The third line here both calls the Divide() function and stores the value sent back.

P5.js

We had the briefest of introductions to P5.js and a flying visit to the new P5.js web editor. We’ll follow up properly on these next week.

Download

Files from this week can be found on our GitHub page.