(1) Where to start....

I grew up first without computers at all, but at age ~11 or so, I got a Commodore 20 (VIC-20). Such a (simple) computer came with an instruction book and power supply. I did not initially get an games or any other software. So the "only" fun one had was to turn it on and try to enter some BASIC programs and learn to program.

Today, one is presented with a very different initial exposure to computers. Once I had kids myself, I wondered how they could be introduced to the fun of programming, without having a large initial step to take. Scratch of course is an easy and quite fun way to go, but when trying this with my kids and doing some programs myself, I found it sometimes hard and cumbersome to express programs graphically.

My older son got introduced in school recently to a new attempt to tech programming. The course/program is called You++. In the background it is using processing as the language. When I looked at what he was doing, I tried it myself and then I downloaded the stand-alone processing package. Now, that seemed both fun and easy to start with.

This blog is an attempt to show you how to start with processing, from scratch, and focus on the "fun" of it, with not a huge focus on knowing exactly on every detail of the language and functions it has and I use. Hope it is helpful to someone.

The video below is going to be an example that will be explained later. But it will be later. A few things needs to be explained first. Enjoy (hopefully)!



(2) Getting set up

Ok, so you want to explore programming. To start head over to the processing home page at:


         http://processing.org

Then navigate to the download page (donate money if you like, or later if you end up liking it, no pressure) and select your operating system. If you do not know if you have 32-bit or 64-bit windows, then you can always select the 32-bit version (or you can right click on "Computer" and select properties, like shown below to find out if you have 32-bit or 64-bit):


Download and you will get a ".zip" file in your download directory. Extract the files, to the desktop for instance, and you are done.

Now, go into the new directory (on the desktop) and you can start processing by double-clicking on the "processing" icon. You should then soon see:


Now we are ready to test our very first program. Enter this into the window, or copy and paste it:
void setup () { 
  size(400, 400);
}

void draw () {
  ellipse(mouseX, mouseY, 20, 20);
}

Easy? Right. Now press the "play" button (or Menu:Sketch->Run). You will get something like this after running over the window with the mouse:


That's it. Your first program and that was not too hard, was it?

(3) What did I just do?

Ok, so you tried it and got to draw circles in the window. But how did that happen? In processing one can insert comments in the code by entering "//". All text on the line after the two forward slashes are ignored by processing. The first program can be explained with inline comments like this:


It might still seem a little magical that this short code of just two routines (called procedures) does what you have seen it does. Lets try an addition. Colors are made up of one number, between 0-255 that represents 0=black, 128=grey and 255=white, and all the grey shades in-between. Lets change the code to:

    // setup() is called once when the program starts execution
    void setup () { 
      // Open a window. First 400 is the width in pixels, second 400 the height
      size(400, 400);
    }
    
    // draw() is called once every frame update (default 30 per second)
    void draw () {
      // Set the fill color to a random grey scale
      fill(random(0,255));
      
      // Draw an ellipse at position X=mouseX, Y=mouseY. The mouseX/Y are built in 
      // variables that are updated with the mouse pointer
      // First 20 is the width and second 20 is the height, in pixels
      ellipse(mouseX, mouseY, 20, 20);
    } 

If you enter this (or just add the "fill(random(0,255));" line, and run, you should get this (after moving the mouse over the window):


Now, that might look a little nicer. The "random(0,255)" will simply pick a random number between 0 (black) and 255 (white). What if you do not want to have that long "tail" of circles. Then you could add another command in your program;

    // setup() is called once when the program starts execution
    void setup () {
      // Open a window. First 400 is the width in pixels, second 400 the height
      size(400, 400);
    }
    
    // draw() is called once every frame update (default 30 per second)
    void draw () {
      // Clear the screen setting the color to 255 (white)
      background(255);
    
      // Set the fill color to a random grey scale
      fill(random(0, 255));
    
      // Draw an ellipse at position X=mouseX, Y=mouseY. The mouseX/Y are built in
      // variables that are updated with the mouse pointer
      // First 20 is the width and second 20 is the height, in pixels
      ellipse(mouseX, mouseY, 20, 20);
    }
    
This, when executed will make the screen look like this:


I think I prefer the "tail". But what about real color? Easy, instead of just one value (for grey) we use a set of three values in the "fill()" call. These three value are RED, GREEN, BLUE, or simply known as RGB. For instance (255,0,0)=RED. Check out this link to find colors and their values. Now add this (and remove the "background()" call;

    // setup() is called once when the program starts execution
    void setup () {
      // Open a window. First 400 is the width in pixels, second 400 the height
      size(400, 400);
    }
    
    // draw() is called once every frame update (default 30 per second)
    void draw () {
      // Set the fill color to a random color
      fill(random(0, 255), random(0, 255), random(0, 255));
    
      // Draw an ellipse at position X=mouseX, Y=mouseY. The mouseX/Y are built in
      // variables that are updated with the mouse pointer
      // First 20 is the width and second 20 is the height, in pixels
      ellipse(mouseX, mouseY, 20, 20);
    }
    
This gives you this nice output:


Now, try random background color by yourself!

(4) Adding mouse clicks

Let's take that last program with nice colors and add so that we can start and stop the drawing of circles by pressing the left mouse button, and maybe drawing rectangles when pressing the right button.
    // setup() is called once when the program starts execution
    void setup () {
      // Open a window. First 400 is the width in pixels, second 400 the height
      size(400, 400);
    }
    
    // draw() is called once every frame update (default 30 per second)
    void draw () {
      // Set the fill color to a random color
      fill(random(0, 255), random(0, 255), random(0, 255));
    
      // Check if mouse button is pressed and if it is left button
      if (mousePressed && (mouseButton == LEFT)) {
        // Draw an ellipse at position X=mouseX, Y=mouseY. The mouseX/Y are built in
        // variables that are updated with the mouse pointer
        // First 20 is the width and second 20 is the height, in pixels
        ellipse(mouseX, mouseY, 20, 20);
    
    } else if (mousePressed && (mouseButton == RIGHT)) {
        // Draw an square at position X=mouseX, Y=mouseY. The mouseX/Y are built in
        // variables that are updated with the mouse pointer
        // First 20 is the width and second 20 is the height, in pixels
        rect(mouseX, mouseY, 20, 20);
      }
    }
    
    
    
The output looks like this:



The "if" statement is looking at the condition in the paranthesis and if true, executes that code, otherwise not. When comparing values it is important to use "==" for equal and not just "=". The "&&" is for "and". I.e. both the "mousePressed" needs to be true as well as the "mouseButton == LEFT". 

To get help on what commands do and example on how to use them, click on Help->Reference in the menu on the window:


You will then see this:


And here are all the built in commands listed. Each one has a small example to it. Try to find the help for "iF" or "rect". 

(5) A bouncing ball...

Some classic programming example involves a ball that is bouncing back and forth when reaching the edge of the screen. It is part of the action in some classic games starting with breakout . So how is that done? Well, take a look at this basic program:
    // Run once at start
    void setup() {
      // 500 pixels wide, 400 pixel height
      // This call will set system variables (width, height)
      size(500, 400);
    }
    
    // Variables to keep track of position and speed of ball
    int x = 0;
    int y = 0;
    int x_speed = 5;
    int y_speed = 5;
    
    // Called every re-draw, defaul 30 times per second
    void draw() {
    
      // Clear screen to black
      background(0);
      // Set fill color to white
      fill(255);
      // Draw a circle at position x,y, 10 pixels large
      ellipse(x, y, 10, 10);
      // Update position by adding speed
      x = x + x_speed;
      y = y + y_speed;
    }
    
If you enter it into the processing editor, or simple copy it, and then run you will see this:






But... that is not quite right is it? The ball starts off but when it reaches the bottom then it disappears... Not what we want. Solution? Add this lines before the last curly bracket "}":

      if (y>height) 
        y_speed = -y_speed;
    
    
Now re-run... All good? Well yes, it bounces when it reaches the bottom, but then it is gone again. We need to detect when the x is also out of range. Add:

      if (x>width)  
        x_speed = -x_speed;
    

Now, re-run. When the ball reached the bottom or the right side, we reverse the speed and it looks like it is bouncing. But we still have a problem. We also need to detect the upper side and the left side. There are two ways to write this. Compare the x and y in these two:


      if (y>height) 
        y_speed = -y_speed;
      else if (y<0)
        y_speed = -y_speed;
      if (x>width || x<0)  
        x_speed = -x_speed;
    
They both do the job. The "||" sign mean logical OR. I.e. if (x>width) OR (x<0) then do the next statement. Since the same is happening for both cases, this is more compact and easier to write and read. Job done. Whole program is now:
    // Run once at start
    void setup() {
      // 500 pixels wide, 400 pixel height
      // This call will set system variables (width, height)
      size(500, 400);
    }
    
    // Variables to keep track of position and speed of ball
    int x = 0;
    int y = 0;
    int x_speed = 5;
    int y_speed = 5;
    
    // Called every re-draw, defaul 30 times per second
    void draw() {
    
      // Clear screen to black
      background(0);
      // Set fill color to white
      fill(255);
      // Draw a circle at position x,y, 10 pixels large
      ellipse(x, y, 10, 10);
      // Update position by adding speed
      x = x + x_speed;
      y = y + y_speed;
      if (y>height) 
        y_speed = -y_speed;
      else if (y<0)
        y_speed = -y_speed;
      if (x>width || x<0)  
        x_speed = -x_speed;
    }
    
And that keeps the ball bouncing until the end of time...


(6) A moving paddle

Remember that link I gave you to the breakout game? Well, now we have a bouncing ball. What we need is a paddle that we can move to the left and right on the screen. This is simply added by using the "rect()" command. This command, like the ellipse() takes four inputs:

 rect(x position, y position, width, height)

But what we have not pointed out is what the x,y position is referencing to. For a ellipse the default is to the middle/center of the ellipse, but for a rectangle it is the upper left corner. One can change this reference for these types of objects with a command:

  rectMode(CENTER);


This will now make the x,y reference the center of the rectangle. It makes it a little easier to deal with the position of the obejects, I think.

to detect key presses, we can use some built in variables in the draw() routing. They are
  • keyPressed - set to 1 (TRUE) when any key is pressed
  • keyCode - Set to special keys that is not a sign, like arrow left (LEFT)
  • key - Set to the key pressed, like 'A' or 'a' (note upper/lower case is not same)
This can now be put together to this program:

// Run once at start
void setup() {
  // 500 pixels wide, 400 pixel height
  // This call will set system variables (width, height)
  size(500, 400);
  rectMode(CENTER);
}

// Variables to keep track of paddle
int x_paddle = 250, y_paddle = 370;
int paddle_width_half = 40;

// Called every re-draw, defaul 30 times per second
void draw() {

  // Check if keys are pressed
  if (keyPressed) {
    if (keyCode == RIGHT || key == 'd') {
      // Move paddle right
      x_paddle = x_paddle + 8;
    } else if (keyCode == LEFT || key == 'a') {
      // Move paddle left
      x_paddle = x_paddle - 8;
    }
  }

  // Clear screen to black
  background(0);
  // Set fill color to white
  fill(255);
  
  // draw paddle
  rect(x_paddle, y_paddle, paddle_width_half*2+1, 11);
}

Enter it, or copy paste, and run:


Try moving it with the left/right arrow. Personally I think we need to add so that one cannot go outside the screen. Adding this after the checking of keys will do that.

  if (x_paddle>width) x_paddle = width;
  if (x_paddle<0) x_paddle = 0;
  


(7) Paddle and bouncing ball

If you take what is in the 5th and 6th post and put it all in the same program you will get a bouncing ball and a moving paddle. Let's do that. The code is (with some clean up):

// Run once at start
void setup() {
  // 500 pixels wide, 400 pixel height
  // This call will set system variables (width, height)
  size(500, 400);
  rectMode(CENTER);
}

// Variables to keep track of position and speed of ball
int x = 0;
int y = 100;
int x_speed = 5;
int y_speed = 5;
// Variables to keep track of paddle
int x_paddle = 250, y_paddle = 370;
int paddle_width_half = 40;

// Called every re-draw, defaul 30 times per second
void draw() {

  // Update position by adding speed
  x = x + x_speed;
  y = y + y_speed;
  if (y>height) 
    y_speed = -y_speed;
  else if (y<0)
    y_speed = -y_speed;
  if (x>width || x<0)  
    x_speed = -x_speed;

  // Check if keys are pressed
  if (keyPressed) {
    if (keyCode == RIGHT || key == 'd') {
      // Move paddle right
      x_paddle = x_paddle + 8;
    } else if (keyCode == LEFT || key == 'a') {
      // Move paddle left
      x_paddle = x_paddle - 8;
    }
  }
  // Check if paddle is at edge of screen 
  if (x_paddle>width) x_paddle = width;
  if (x_paddle<0) x_paddle = 0;

  // Clear screen to black
  background(0);
  // Set fill color to white
  fill(255);
  // Draw a circle at position x,y, 10 pixels large
  ellipse(x, y, 10, 10);
  // draw paddle
  rect(x_paddle, y_paddle, paddle_width_half*2+1, 11);
}

Try to copy it and run it. Almost a start of the breakout game, right? But that code does nothing when the ball hits the paddle and the ball does not disappear when it reaches the bottom of the screen. Let's try to fix that. Making it disappear at the bottom is simple. We just remove the check where we reverse the y_speed when it reaches the bottom. I.e. removing:

  if (y>height) 
    y_speed = -y_speed;

Will make the ball disappear at the bottom. How about making the ball "bounce" of the paddle? It is not as simple as what we just removed, as the paddle is smaller, and can move. We need to check if the ball is hitting where the paddle is at the moment. We need to check that 4 conditions are met at the same time. The ball needs to be in x-position where the paddle is (checked in the first two lines below) and then we also need to check that the paddle is in y-position where we have the paddle. We need to have a range here as the ball is travelling with some speed and will not move just one pixel at the time. Place this code just before the real drawing begins (i.e. at the background()):

  // Check if ball collides with paddle
  if ((x_paddle-paddle_width_half)<x && (x_paddle+paddle_width_half)>x && 
    (y_paddle-10)<y && (y_paddle)>y) {
    // ball is hitting paddle rectangle, reverse y_speed
    y_speed = -y_speed;
  }

Now try it and run it. You should be able to keep the ball bouncing if you have skills and precision for a while. What if we tried to add a score keeping for each bounce of the paddle you manage? Declare a global variable (done outside the setup() and draw() routines) called "score" like:

// score keeping
int score = 0;

And add an increment to the score inside the "if" where we detected the hit of the paddle:

  // Check if ball collides with paddle
  if ((x_paddle-paddle_width_half)<x && (x_paddle+paddle_width_half)>x && 
    (y_paddle-10)<y && (y_paddle)>y) {
    // ball is hitting paddle rectangle, reverse y_speed
    y_speed = -y_speed;
    score = score + 1;
  }

But how would we know the score? We need to display the score. This is done by:

  // Display score
  textSize(16);
  textAlign(RIGHT);
  text("Score", 80, 390);
  textAlign(LEFT);
  text(score, 90, 390);

Remember to put this after the "background()" call, since that is erasing the whole screen. So far we have this code, if you have followed along:

// Run once at start
void setup() {
  // 500 pixels wide, 400 pixel height
  // This call will set system variables (width, height)
  size(500, 400);
  rectMode(CENTER);
}

// Variables to keep track of position and speed of ball
int x = 0;
int y = 100;
int x_speed = 5;
int y_speed = 5;
// Variables to keep track of paddle
int x_paddle = 250, y_paddle = 370;
int paddle_width_half = 40;
// score keeping
int score = 0;

// Called every re-draw, default 30 times per second
void draw() {

  // Update position by adding speed
  x = x + x_speed;
  y = y + y_speed;
  if (y<0)
    y_speed = -y_speed;
  if (x>width || x<0)  
    x_speed = -x_speed;

  // Check if keys are pressed
  if (keyPressed) {
    if (keyCode == RIGHT || key == 'd') {
      // Move paddle right
      x_paddle = x_paddle + 8;
    } else if (keyCode == LEFT || key == 'a') {
      // Move paddle left
      x_paddle = x_paddle - 8;
    }
  }
  // Check if paddle is at edge of screen 
  if (x_paddle>width) x_paddle = width;
  if (x_paddle<0) x_paddle = 0;

  // Check if ball collides with paddle
  if ((x_paddle-paddle_width_half)<x && (x_paddle+paddle_width_half)>x && 
    (y_paddle-10)<y && (y_paddle)>y) {
    // ball is hitting paddle rectangle, reverse y_speed
    y_speed = -y_speed;
    score = score + 1;
  }

  // Clear screen to black
  background(0);
  // Set fill color to white
  fill(255);
  // Draw a circle at position x,y, 10 pixels large
  ellipse(x, y, 10, 10);
  // draw paddle
  rect(x_paddle, y_paddle, paddle_width_half*2+1, 11);
  // Display score
  textSize(16);
  textAlign(RIGHT);
  text("Score", 80, 390);
  textAlign(LEFT);
  text(score, 90, 390);
}

If you haven't followed along, copy and paste the whole thing and run it. Nice right? Almost a breakout game. Certainly a game, although simple. Now, what is missing is that we do not detect when you miss and declare "Game Over" and have a way to restart. This is fixed by adding two parts. One print at the very end, before the last "}" in the draw():

  if (y>height) {
    textSize(40);
    textAlign(CENTER);
    text("Game over", 250, 150);
  }

And then also inside the "keyPressed" "if" statement, adding another check for hitting the spacebar:

  // Check if keys are pressed
  if (keyPressed) {
    if (keyCode == RIGHT || key == 'd') {
      // Move paddle right
      x_paddle = x_paddle + 8;
    } else if (keyCode == LEFT || key == 'a') {
      // Move paddle left
      x_paddle = x_paddle - 8;
    } else if (key == ' ') {
      // Restart
      x = 0;
      y = 100;
      x_paddle = 250;
      score = 0;
    }
  }

This last check for ' ' will reset the ball position, paddle position, and score to what it started with. Add it and run it. Nice? That is indeed a real game. Not too fancy and one get bored quickly, but still, a game. This is how it looks like:


Full source code:

// Run once at start
void setup() {
  // 500 pixels wide, 400 pixel height
  // This call will set system variables (width, height)
  size(500, 400);
  rectMode(CENTER);
}

// Variables to keep track of position and speed of ball
int x = 0;
int y = 100;
int x_speed = 5;
int y_speed = 5;
// Variables to keep track of paddle
int x_paddle = 250, y_paddle = 370;
int paddle_width_half = 40;
// score keeping
int score = 0;

// Called every re-draw, defaul 30 times per second
void draw() {

  // Update position by adding speed
  x = x + x_speed;
  y = y + y_speed;
  if (y<0)
    y_speed = -y_speed;
  if (x>width || x<0)  
    x_speed = -x_speed;

  // Check if keys are pressed
  if (keyPressed) {
    if (keyCode == RIGHT || key == 'd') {
      // Move paddle right
      x_paddle = x_paddle + 8;
    } else if (keyCode == LEFT || key == 'a') {
      // Move paddle left
      x_paddle = x_paddle - 8;
    } else if (key == ' ') {
      // Restart
      x = 0;
      y = 100;
      x_paddle = 250;
      score = 0;
    }
  }
  // Check if paddle is at edge of screen 
  if (x_paddle>width) x_paddle = width;
  if (x_paddle<0) x_paddle = 0;

  // Check if ball collides with paddle
  if ((x_paddle-paddle_width_half)<x && (x_paddle+paddle_width_half)>x && 
    (y_paddle-10)<y && (y_paddle)>y) {
    // ball is hitting paddle rectangle, reverse y_speed
    y_speed = -y_speed;
    score = score + 1;
  }

  // Clear screen to black
  background(0);
  // Set fill color to white
  fill(255);
  // Draw a circle at position x,y, 10 pixels large
  ellipse(x, y, 10, 10);
  // draw paddle
  rect(x_paddle, y_paddle, paddle_width_half*2+1, 11);
  // Display score
  textSize(16);
  textAlign(RIGHT);
  text("Score", 80, 390);
  textAlign(LEFT);
  text(score, 90, 390);
  if (y>height) {
    textSize(40);
    textAlign(CENTER);
    text("Game over", 250, 150);
  }
}

(8) Disappering blocks

We seem to be moving to a breakout game. In that we also need some blocks. We cannot just have a bouncing ball and moving paddle. To keep track of the blocks we could use an array. Each element in the array represents a block. If it is not hit, and exists, then the element could be '1', when it is hit, we can set the element to '0'. If we start with the basics, let's declare a global array of ints to keep track of the blocks, and lets initialize them in the setup() routine:

// We will have 20 blocks. blocks[i]==1 means it still exists
int[] blocks = new int[20];

// Run once at start
void setup() {
  int i;
  // 500 pixels wide, 400 pixel height
  // This call will set system variables (width, height)
  size(500, 400);
  rectMode(CENTER);
  for (i=0; i<20; i++) {
    blocks[i] = 1;
  }
}

Now, that's done, we also need to draw them. There are several ways to do it. What I did was to loop through all blocks with using a local variable (declared inside setup()) 'i'. Then I calculate the x, y pixel position of the block we are looking at right now. The picture shows how the blocks[] array corresponds to the blocks.


And this is the code to draw them:

void draw() {
  int i, x, y;

  // Erase the screen, all black
  background(0);

  // Loop through all the potential blocks
  for (i=0; i<20; i++) {
    // Calculate the x,y position of upper right corner
    x = i%5*100+10; // %5 is modulus - will result 0-4 always 
    y = 40*(i/5)+10; 
    // Check if we we have a block (blocks[x] is 1)
    if (blocks[i]==1) { 
      // Draw the block
      rect(x+40, y+10, 80, 20);
    }
  }
}

Now it is a nice collection of blocks. But they are all there, always. How do we "remove" them. We can test by checking if the mouseX/Y is on one of the blocks and if it is, remove it. This can be done by this code:

    // Check if mouse is over the block, if so, remove it (blocks[i]=0)
    if (mouseX>x && mouseX<(x+80) &&
      mouseY>y && mouseY<(y+20)) 
      blocks[i]=0;

Similar to how we checked if the ball hit the pad, this is done by checking if it is inside the coordinates for the blocks. The x,y is same as when we did the drawing of the blocks. The last thing we would want to add in this example, is to detect when all blocks are gone. We can do this by setting a variable to '1' before drawing anything and if we draw any number of blocks, setting it to '0'. If it is '1' after the loop, we did not draw anything. The complete code for this is

// We will have 20 blocks. blocks[i]==1 means it still exists
int[] blocks = new int[20];

// Run once at start
void setup() {
  int i;
  // 500 pixels wide, 400 pixel height
  // This call will set system variables (width, height)
  size(500, 400);
  rectMode(CENTER);
  for (i=0; i<20; i++) {
    blocks[i] = 1;
  }
}

void draw() {
  int i, x, y;
  int blocks_gone;

  // Erase the screen, all black
  background(0);

  blocks_gone = 1;
  // Loop through all the potential blocks
  for (i=0; i<20; i++) {
    // Calculate the x,y position of upper right corner
    x = i%5*100+10; // %5 is modulus - will result 0-4 always 
    y = 40*(i/5)+10; 
    // Check if we we have a block (blocks[x] is 1)
    if (blocks[i]==1) { 
      // Draw the block
      rect(x+40, y+10, 80, 20);
      // Since we drew a block, all are not gone
      blocks_gone = 0;
    }
    // Check if mouse is over the block, if so, remove it (blocks[i]=0)
    if (mouseX>x && mouseX<(x+80) &&
      mouseY>y && mouseY<(y+20)) 
      blocks[i]=0;
  }
  if (blocks_gone==1)
    text("You win", 200, 200);
}

Copy/paste it or enter it and run it.



(9) Breakout game in processing

To make a "complete" game, probably with bugs and quirks, we just need to put together the paddle, moving ball, and the disappearing blocks. Well, and add some final touched such as introducing a level (ball speeds up for each level) and to add detection if the ball hit the sides of the blocks for just bouncing in the horizontal direction. Adding it together and adding those touches produces this code:

// We will have 20 blocks. blocks[i]==1 means it still exists
int[] blocks = new int[20];
// Variables to keep track of position and speed of ball
int x = 250 + int(random(-80,80));
int y = 350;
int x_speed = 3;
int y_speed = -3;
// Variables to keep track of paddle
int x_paddle = 250, y_paddle = 370;
int paddle_width_half = 40;
// keep score 
int score = 0;
int level = 1;
int wait = 0;

// Run once at start
void setup() {
  int i;
  // 500 pixels wide, 400 pixel height
  // This call will set system variables (width, height)
  size(500, 400);
  rectMode(CENTER);
  // All blocks exist
  for (i=0; i<20; i++) {
    blocks[i] = 1;
  }
}

// Called every re-draw, defaul 30 times per second
void draw() {
  int i, x_tmp, y_tmp;
  int blocks_gone;

  // Update ball position by adding speed
  x = x + x_speed;
  y = y + y_speed;
  if (x>width || x<0)  
    x_speed = -x_speed;
  if (y<0)
    y_speed = -y_speed;

  // Check if keys are pressed
  if (keyPressed) {
    if (keyCode == RIGHT || key == 'd') {
      // Move paddle right
      x_paddle = x_paddle + 8;
    } else if (keyCode == LEFT || key == 'a') {
      // Move paddle left
      x_paddle = x_paddle - 8;
    } else if (key == ' ') {
      // Restart
      x = 250 + int(random(-80,80));
      y = 350;
      x_speed = 3;
      y_speed = -3;
      x_paddle = 250;
      score = 0;
      level = 1;
      // All blocks exist
      for (i=0; i<20; i++) {
        blocks[i] = 1;
      }
    }
  }

  // Check if ball collides with paddle
  if ((x_paddle-paddle_width_half)<x && (x_paddle+paddle_width_half)>x && 
    (y_paddle-10)<y && (y_paddle)>y) {
    // ball is hitting paddle rectangle, reverse y_speed
    y_speed = -y_speed;
    score = score + 1;
  }

  // Clear screen to black
  background(0);
  // Set fill color to white
  fill(255);
  // Display score
  textSize(16);
  textAlign(RIGHT);
  text("Score", 80, 390);
  textAlign(LEFT);
  text(score, 90, 390);
  // Display level
  textAlign(RIGHT);
  text("Level", 450, 390);
  textAlign(LEFT);
  text(level, 460, 390);

  // Draw a circle at position x,y, 10 pixels large
  ellipse(x, y, 10, 10);
  // draw paddle
  rect(x_paddle, y_paddle, paddle_width_half*2+1, 11);
  if (y>height) {
    textSize(40);
    textAlign(CENTER);
    text("Game over", 250, 250);
  }

  blocks_gone = 1;
  // Loop through all the potential blocks
  for (i=0; i<20; i++) {
    // Calculate the x,y position of upper right corner
    x_tmp = i%5*100+10; // %5 is modulus - will result 0-4 always 
    y_tmp = 40*(i/5)+10; 
    // Check if we we have a block (blocks[x] is 1)
    if (blocks[i]==1) { 
      // Draw the block
      rect(x_tmp+40, y_tmp+10, 80, 20);
      // Since we drew a block, all are not gone
      blocks_gone = 0;
    }
    // Check if ball is over the block, if so, remove it (blocks[i]=0) 
    // first check bounce on top/bottom
    if (x>(x_tmp+4) && x<(x_tmp+76) &&
      y>y_tmp && y<(y_tmp+20) && blocks[i]==1) { 
      blocks[i]=0;
      y_speed = -y_speed;
      score = score + 5;
    }
    // first check bounce on sides
    if (((x>(x_tmp-5) && x<x_tmp) || (x>(x_tmp+80) && x<(x_tmp+85))) &&
      y>y_tmp && y<(y_tmp+20) && blocks[i]==1) { 
      blocks[i]=0;
      x_speed = -x_speed;
      score = score + 5;
    }
    // first check bounce on sides
    if (((x>(x_tmp-1) && x<(x_tmp+5)) || (x>(x_tmp+75) && x<(x_tmp+81))) &&
      y>y_tmp && y<(y_tmp+20) && blocks[i]==1) { 
      blocks[i]=0;
      x_speed = -x_speed;
      y_speed = -y_speed;
      score = score + 5;
    }
  }
  if (blocks_gone==1 && wait<200) {
    textSize(40);
    textAlign(CENTER);
    text("Level cleared...", 250, 210);
    text("Preparing next level", 250, 290);
    x = 250;
    y = 350;
    x_speed = 0;
    y_speed = 0;
    wait++;
    if (wait==200) {
      wait = 0;
      x = 250 + int(random(-80,80));;
      y = 350;
      x_speed = 3+level;
      y_speed = -3-level;
      x_paddle = 250;
      level++;
      // All blocks exist
      for (i=0; i<20; i++) {
        blocks[i] = 1;
      }
    }
  }
}


And this gameplay:


(10) Fun with recursive function - Classic tree

One way to write very short programs that can make up complex drawings is to use recursive calls to a function. A recursive function is a function that calls itself from inside the own code in the function. When this is done, it is extremely important to have a termination condition to stop doing that. Otherwise the function will end up locking up the program/computer and will not respond at all.

A very classic example of this is to draw a "tree". This is done by drawing a line, just a line in a function, but then in the call, calling itself again twice. The call to itself is then modified to have a slightly shorter line, and at an angle... Enough talk. This is about "learn by doing". Here is the code:

// Run once
void setup() {
  frameRate(30);
  // size(1000, 1000);
  fullScreen();
}

// Run "frameRate" times per secont
void draw() {
  // angle is the amount of tilt we do on the line. 
  // In radians : 2*PI radians = 360 degrees 
  float angle = (width/2-mouseX)*TWO_PI/width;
  // len is the length of the first line
  float len = (height-mouseY)/2;
  background(0); // Black
  smooth(4);
  stroke(255);   // White
  // Print the text
  text("Len = " + len + " Angle(radians) = " + angle, 15, 15);
  // Call the tree function (once)
  tree(width/2, height, len, -PI/2, angle);
}

// This is the recursive function
void tree(float x, float y, float len, float alpha, float gamma) {
  line(int(x), int(y), int(x+len*cos(alpha)), int(y+len*sin(alpha)));
  // We need to have some termination condition. In our case we stop 
  // Calling recursive once the length has decreased to 1 
  if (len>1) {
    // We change the len and alpha for each call to make up the "tree"
    tree(x+len*cos(alpha), y+len*sin(alpha), len*0.64, alpha-gamma, gamma);
    tree(x+len*cos(alpha), y+len*sin(alpha), len*0.64, alpha+gamma, gamma);
  }
}

Now, some math understanding is required to really see what is going on, but please just copy, paste and run. Move the mouse! Read the text! Have fun!


(11) A ship that can shoot?

Just to try some other classic games, consider Astroids. In this you are a small ship that looks like a triangle and your objective is to shoot down astroids that are moving around. In the following example, a ship is drawn, pointing to the mouse, and you can shoot bullets. There are no astroids and nothing fancy. There are two new items used.

The first one is the ability in processing to shift the perspective and then shift back. Using this one can draw the same object (like the triangle in the example) the same way, but still make it appear as if it is moving. This is used in the example to both draw the ship and the bullets.

The second new thing, is the use of Objects and list of objects. Objects are used to group variables and code belonging together. It is then also easy to use it over and over without making the code messy. In the example, the bullet is an object. The ship could also have been an object, but it felt too simple.

Enter this and try!

// List of shots
// Shots is an object we have defined that represents a single bullet
ArrayList<shot> shots = new ArrayList<shot>();

// Run once
void setup () {
  frameRate(60);
  size(500, 500);
  // White
  stroke (255);
  fill(255);
}

// Called 60 times per second
void draw()
{
  int i;
  // Find the angle from x=250, y=250 to the mouse
  float angle = atan2(mouseY - 250, mouseX - 250);

  // Clear screen, black
  background(0);
  // "pushMatrix" saves current viewpoint
  pushMatrix();
  // Set 250,250 as the new 0,0 
  translate(250, 250);
  // Rotate screen "angle" 
  rotate(angle);
  // Draw a triangle (the ship)
  triangle(20, 0, -20, -10, -20, 10);
  // Bring back normal perspektive
  popMatrix();
  // Go through all shots (if any) and update their position
  for (i = 0; i<shots.size(); i++) {
    shot s = shots.get(i);
    if (s.update()) {
      // Remove bullet, if outside screen
      shots.remove(i);
    }
  }
}

// When left mouse button is pressed, create a new shot
void mousePressed() {
  if (mouseButton == LEFT) {
    float angle = atan2(mouseY - 250, mouseX - 250);
    shots.add(new shot(angle, 2));
  }
}

// Class definition for the shot
class shot {
  // A shot has x,y, and speed in x,y. All float for smooth movement
  float angle, speed;
  float position;

  // Constructor  
  shot(float _angle, float _speed) {
    angle = _angle;
    speed = _speed;
    position = 0;
  }

  // Update position, return true when out of screen
  boolean update() {
    position = position + speed;
    pushMatrix();
    // Set 250,250 as the new 0,0 
    translate(250, 250);
    // Rotate screen "angle" 
    rotate(angle);
    // Draw bullet
    ellipse (position + 20, 0, 5, 5);
    // Bring back normal perspektive
    popMatrix();
    if (position>250) {
      return true;
    } else {
      return false;
    }
  }
}




(12) Creating astroids...

So in previous post, we have a ship that can shoot bullets at... nothing. Not much fun as a game. If we are to try to create a simple astroids clone, then we need... astroids. In my version they will come from outside the screen at random angles and speeds, and traverse in a straight line across. For making them look better, instead of just a circle, I use an object called "PShape" (click to read about ir). This shape is created unique per astroid as I create the shape for each new astroid in the constructor for the object. (Tutorial to objects and explanation of constructor here). I decided to keep the astroid roughly circular to make collision detection easier later...

How does it look like? Watch this:



Try it your self and play with it using this code. Clicking right mouse button spawns new astroid.

ArrayList<astroid> astroids = new ArrayList<astroid>();


// Settings - how many seconds between each new astroid (3 seconds = 3 * 60)
int astroid_rate = 3 * 60;
int astroid_count = 0;
// Size in pixel of nominal astroid
float ast_size = 10;

// Run once
void setup () {
  frameRate(60);
  size(500, 500);
}

// Called 60 times per second
void draw()
{
  int i;
  // Find the angle from x=250, y=250 to the mouse
  float angle = atan2(mouseY - 250, mouseX - 250);

  // 1 new astroid every 5 seconds (60 fps * 4 sec)
  if (astroid_count--==0) {
    astroids.add(new astroid(random(0, TWO_PI), random(0.1, 2.0), random(0.5, 4), random(-0.1, 0.1), 
      random(-150, 150), random(-150, 150)));
    // Increase rate just a little
    astroid_count = astroid_rate--;
  }

  // Clear screen, black
  background(0);
  // Go through all astroids (if any) and update their position
  for (i = 0; i<astroids.size(); i++) {
    astroid a = astroids.get(i);
    if (a.update()) {
      astroids.remove(i);
    }
  }  
  // "pushMatrix" saves current viewpoint
  pushMatrix();
  // Set 250,250 as the new 0,0 
  translate(250, 250);
  // Rotate screen "angle" 
  rotate(angle);
  fill(255);
  // Draw a triangle (the ship)
  triangle(20, 0, -20, -10, -20, 10);
  // Bring back normal perspektive
  popMatrix();
}

// When right mouse button is pressed, create a new astroid
void mousePressed() {
  if (mouseButton == RIGHT) {
    astroids.add(new astroid(random(0, TWO_PI), random(0.1, 2.0), random(0.5, 4), random(-0.1, 0.1), 
      random(-80, 80), random(-80, 80)));
  }
}

// Class definition for the astroid
class astroid {
  // An astroid angle, speed, size, rotation
  float angle, speed, size, rotSpeed;
  float position;
  float rotation;
  float xoff, yoff;
  float x, y;
  PShape s;  // The PShape object - Keeps the astroid shape
  float i;

  // Constructor  
  astroid(float _angle, float _speed, float _size, float _rotSpeed, float _xoff, float _yoff) {
    angle = _angle;
    speed = _speed;
    size = _size;
    rotSpeed = _rotSpeed;
    // This will be used when later breaking down astroids
    if (xoff<1000) {
      // Normal - start outside screen
      x = 250+500*cos(angle)+_xoff;
      y = 250+500*sin(angle)+_yoff;
    } else {
      // Start on specific x,y
      x = _xoff-2000;
      y = _yoff-2000;
    }
    rotation = 0; 
    // Generate the shape of the astroid - Some variations for all, roughly sircular
    s = createShape();
    s.beginShape();
    s.fill(255, 255, 100);
    s.noStroke();
    for (i=0; i<TWO_PI; i=i+PI/(random(4, 11))) {
      s.vertex(random(ast_size*0.8, ast_size*1.2)*cos(i), random(ast_size*0.8, ast_size*1.2)*sin(i));
    }
    s.endShape(CLOSE);
  }

  // Update position, return true when out of screen
  boolean update() {
    x = x - cos(angle)*speed;
    y = y - sin(angle)*speed;
    rotation = rotation + rotSpeed; 

    pushMatrix();
    // Set position as the new 0,0 
    translate(x, y);
    // Rotate screen "angle" 
    rotate(rotation);
    // Draw astroid
    scale(size);
    shape(s, 0, 0);
    // Bring back normal perspektive
    popMatrix();

    if (x<-300 || x>800 || y<-300 || y>800) {
      return true;
    } else {
      return false;
    }
  }
}