Published: January 24, 2017, Edited by: Mads Hobye

Learn to program games in processing

This is a video guide we use to teach students to program in processing. Each video goes through step by step the different elements of programming. We use traditional arcade games as our platform to experiment with.

We further advise you to read through the guides on the processing site:

https://processing.org/tutorials/

Also, the processing reference is your friend:

https://processing.org/reference/

If you want to see examples of games students have made you can find them here:

http://fablab.ruc.dk/noob-to-master-programmer-in-10-days/

Basic understanding of grid and interactivity

The following tutorials give you an overview of the basics understanding the grid and how to make interactivity:

https://processing.org/tutorials/drawing/

https://processing.org/tutorials/interactivity/

General syntax

This is general syntax that we will go through in this tutorial:

   // ********************************************************
  // ***    Basic syntac for Processing - cheat sheet     ***
  // ***    By: FabLab RUC - Mads Hobye - V1              ***
  // ********************************************************

  // Global variables defined by the user 

  float aDecimal = 0.5f; // float creates a decimal (kommatal)
  int anInteger = 100; // int creates an integer (heltal)
  boolean aLogical = true; // boolean creates an a logical operater (only true or false)
  ArrayList<Integer> anArrayOfInt = new ArrayList<Integer>();

  myClass myObject;


  // setup() runs once when you start the program.
  // the curly braces defines the boundary of the setup() funciton
  void setup() 
  {
    println("This message is only presented once"); // "println" prints a line in the debug prompt
    anArrayOfInt.add(1);
    anArrayOfInt.add(3);
    anArrayOfInt.add(4);
    anArrayOfInt.add(5);
    anArrayOfInt.add(6);

  }

  // draw() repeats endlessly.
  void draw() 
  {
    myObject = new myClass(); // Creates and object from the class below
    int myLocalInt = 3; // This is a local variable only accessible within draw

    println("This is the beginning of draw");

    // An if statement - only runs if the variable "anInteger" is equal to 100
    if (anInteger == 100) 
    {
      println("The anInteger is 100");
    }
    else // only runs if "anInteger" is not equal to 100 then 
    {
      println("Change anInteger to something else than 100 to run me");
    }

    //Everything within the curly braces are run 3 times
    for (int i=0; i < 3; i = i +1)
    {
      println("This has been run " + (i+1) + " times");
    }

    // calls my function below
    myFunction(anInteger); 

    // calls classFunction in myObject
    myObject.classFunction(); 

    println("This is the first item in the array: " + anArrayOfInt.get(0));

    println("This is the end of draw - I will now start over");
  } // when draw reaches the end it start over.


  //This is a custom function called myFunction()
  void myFunction(int _input)
  { 
    println("This is my custom function");
    println("You gave me the number:" + _input);
  }


  class myClass
  {
    int classVariable = 0; // local variable for myClass
    void classFunction()
    {
      println("You called the subfunction for my class");
    }
  }

How to program pong

This video is a run-through of the basics of programming a simple pong game. It gives you a basic understanding of the principles behind programming and game design.

Pong example code

      float posX = 150;
      float posY = 100;
      float dirX = 1;
      float dirY = 1;
      float opponentY = 0;
      int score = 0;


      void setup()
      {
        size(300, 200);
      }


      void draw()
      {
        background(0);

        // Y axis - ball
        posY = posY +dirY;

        if (posY > height)
        {
          dirY = -1;
        }

        if (posY < 0)
        {
          dirY = 1;
        }

        // X axis - ball
        posX = posX +dirX;

        if (posX > width)
        {
          dirX = -1;
        }
        if (posX < 0)
        {

          if (posY > mouseY && posY < mouseY + 60) // within the bat
          {
            println("bat hit");
            dirX = 1; 
            score = score +1;
          } else // above or below the bat
          {
            println("bat missed");
            posX = width/2;
            posY = height/2;
            score = score -1;
          }
        }
        //opponent

        opponentY = opponentY * 0.99 + (posY-30)*0.01;

        rect(width-10, opponentY, 10, 60);

        // Bat

        rect(0, mouseY, 10, 60);

        fill(255);
        ellipse(posX, posY, 20, 20);
        text(score, 10, 20);
      }

Scope, logical structures and state machines

When you have done your first little game it is relevant to dwell a little on some key concepts. By now you probably want to add a start screen. Further, you are probably struggling with getting the curly brackets right. This video runs through these concepts:

Bouncer example code

      // properties of the person who wants to enter the club
      int age = 20;
      boolean wellDressed = false;
      boolean wearsJacket = true;

      // day properties
      boolean saturday = true;


      void setup()
      {
        println("Welcome to the club");
        if (age >= 18 && saturday == false || saturday == true && age >= 21)
        {
          println("Please enter the club");
          if(wearsJacket == true)
          {
           println("Please give your jacket to the wardrobe"); 

          }
          if (wellDressed == true)
          {
            println("Great that you are so well dressed - you will get a drink");
          }
        } else
        {
          println("You are not old enough - please go away!");
        }
      }

      void draw()
      {
      }

State machine example code

int state = 0;

void setup() {
}

void draw() {

     //println(state);

     if (state == 0) {

          state = 1;
     } else if (state == 1) {

          state = 2;
     } else if (state == 2) {

          state = 3;
     }
}

For loops

When programming one has a tendency to write lots of redundant code. One way to solve this is to use for loops to repeat the same kind of code over and over again. In this example, we use the for loop to make a "fence" between the two players in the pong game.

For loop example

      for (int counter = 0; counter < height/30; counter = counter +1)
      {
        rect(width/2-5, 30*counter, 10, 20);
      }

Classes and objects

Object-oriented programming is all about creating classes and make objects from them. This video converts the original pong game into an object oriented structure. This is especially relevant when you want to work with multiple game objects e.g. multiple balls, bullets, spaceships meteors etc.

int state = 0;

Ball theBall = new Ball();
Bat playerBat = new Bat();

float opponentY = 0;
int score = 0;

void setup()
{

  size(400, 300);
  textSize(30);
}

void draw()
{

  if (state == 0) // welcome state
  {
    welcomeScreen();
  } else if (state==1) // play the game state
  {
    gameScreen();
  } else if (state == 2) // gameover state -win
  {
    winScreen();
  } else if (state == 3) // gameover state -loose
  {
    looseScreen();
  }
}

void welcomeScreen()
{
  background(0, 255, 200);
  text("Welcome to the amazing pong", width/2-100, height/2);
  if (mousePressed)
  {
    state = 1;
  }
}


void gameScreen()
{
  background(0);


  // draw the net
  for (int counter = 0; counter < height/30; counter = counter +1)
  {
    rect(width/2-5, 30*counter, 10, 20);
  }

  // tjeck for collision between player one and the bat
  if (theBall.y > playerBat.y && theBall.y < playerBat.y + 60 && theBall.x < playerBat.x) // within the bat
  {
    println("bat hit");
    theBall.dirX = 1; 
    score = score +1;
    if (score > 2)
    {
      state=2;
    }
  } 


  // the bat has been missed and the ball is outside on the left
  if (theBall.x < 0)// above or below the bat
  {
    println("bat missed");
    theBall.x = width/2;
    theBall.y = height/2;
    score = score -1;
    if (score < -2)
    {
      state = 3;
    }
  }

  // bat

  playerBat.updateMe();
  playerBat.drawMe();

  // ball

  theBall.updateMe();
  theBall.drawMe();


  //opponent
  opponentY = opponentY * 0.99 + (theBall.y-30)*0.01;

  rect(width-10, opponentY, 10, 60);
  fill(255);

  text(score, 10, 20);
}


void looseScreen()
{
  background(255, 0, 0);
  if (mousePressed)
  {
    state = 1;
    score = 0;
  }
}

void winScreen()
{
  background(#FFCA08);
  if (mousePressed)
  {
    state =1;
    score = 0;
  }
}



void keyPressed()
{
  if (key=='s')
  {
    playerBat.dirY = 1;
  }

  if (key=='w')
  {

    playerBat.dirY = -1;
  }

  if (key=='a')
  {
    playerBat.dirX = -1;
  }

  if (key=='d')
  {

    playerBat.dirX = 1;
  }
}

void keyReleased()
{
  if (key=='s' || key == 'w')
  {
    playerBat.dirY = 0;
  }

  if (key=='a' || key == 'd')
  {
    playerBat.dirX= 0;
  }
}


class Ball
{
  float x = 150;
  float y = 100;
  float dirX = 1;
  float dirY = 1;

  void updateMe()
  {

    // Y axis - ball
    theBall.y = theBall.y +theBall.dirY;

    if (theBall.y > height)
    {
      theBall.dirY = -1;
    }

    if (theBall.y < 0)
    {
      theBall.dirY = 1;
    }

    // X axis - ball
    theBall.x = theBall.x +theBall.dirX;

    if (theBall.x > width)
    {
      theBall.dirX = -1;
    }
  }

  void drawMe()
  {

    ellipse(theBall.x, theBall.y, 20, 20);
  }
}

class Bat
{
  float x = 0;
  float y = 0;
  float dirX = 0;
  float dirY = 0;

  void updateMe()
  {
    // Bat
    playerBat.y = playerBat.y + playerBat.dirY;
    playerBat.x = playerBat.x + playerBat.dirX;
  }

  void drawMe()
  {
    rect(playerBat.x, playerBat.y, 10, 60);
  }
}

Asteroids game

Simple example of making a meteor:

 class Meteor
 {
      float x = 0;
      float y = 0;
      float size = 0;
      float dirX = 0;
      float dirY = 0;

      void init()
      {
           x = random(0, 200);
           y = random(0, 200);
           dirX = random(-1,1);
           dirY = random(0,2);
           size = random(3,10);
      }

      void show()
      {
           x = x + dirX;
           y = y + dirY;
           if(x > width)
           { 
                x = 0;
           }
           if(x < 0)
           {
                x = width;
           }
           if(y  > height)
           {
                y = 0;
           }
           if(y < 0)
           {
                y = height;
           }

           ellipse(x, y, size, size);
      }
 } // slut på meteor definition


 ArrayList<Meteor> meteorList = new ArrayList<Meteor>();
 float numMeteors = 100;


 void setup()
 {

      noStroke();
      size(200, 200);

      for (int i = 0; i < numMeteors; i= i +1)
      {

           Meteor tmpMeteor = new Meteor();
           tmpMeteor.init();
           meteorList.add(tmpMeteor);
      }

 }

 void draw()
 {

      background(0);
      for (int i = 0; i < numMeteors; i = i +1)
      {
           meteorList.get(i).show();
      }


 }

Basic gravity

It is often needed to have some element with gravity. E.g. at ball falling to the ground. This video shows you have to make the ball fall and also bounce on the ground. Further, keyPressed is used to enable jumping and moving around.

Gravity code examples

        float posX = 0;
        float posY = 0;
        float speedX = 0;
        float speedY = 0;

        void setup()
        {
             rectMode(CENTER);
             size(200,200);
        }


        void draw()
        {
             background(0);
             rect(posX, posY, 20, 20);
             posX = posX +speedX;
             posY = posY +speedY;


             // gravity - crude version
             speedY = speedY +0.01;

             //platform
             rect(width/2,height/2,20,20); 
             if(posY > height/2-20 && posX > width/2-10 && posX < width/2+10)
             {
              speedY = 0;    
             }

        }


        void keyPressed()
        { 
             if (key== 'd') 
             {
                  speedX = 1;
             } else if (key== 'a')
             {
                  speedX = -1;
             }

             if (key== 'w') 
             {
                  speedY = -1;
             } else if (key== 's')
             {
                  speedY = 1;
             }
        }

        void keyReleased()
        {
             if (key=='d')
             {
                  speedX = 0;
             } else if (key=='a')
             {
                  speedX = 0;
             }

             if (key=='w')
             {
                  speedY = 0;
             } else if (key=='s')
             {
                  speedY = 0;
             }
        }

Complex collision detection, gravity and level creation

This video is a run-through of making the basic of e.g. a Super Mario level.

class Block
{
     float x =0;
     float y = 0;
     float w = 0;
     float h = 0;

     void show()
     {
          rect(x, y, w, h);
     }
}


Player thePlayer = new Player();

ArrayList<Block> blocks = new ArrayList<Block>();

int numBlocks = 20;

void setup()
{
     size(500, 500);

     for (int counter = 0; counter < numBlocks; counter = counter +1)
     {
          Block tmpBlock = new Block();
          tmpBlock.x = counter * 50+random(30);
          tmpBlock.w = 50;
          tmpBlock.y = height - random(0, 100);
          tmpBlock.h = 100;

          blocks.add(tmpBlock);
     }
}

void draw()
{
     background(0);
     translate(thePlayer.x*-1+100, thePlayer.y *-1+100);
     thePlayer.move();
     thePlayer.show();

     for (int counter = 0; counter < numBlocks; counter = counter +1)
     {
          Block selectedBlock = blocks.get(counter);
          selectedBlock.show();
          //ellipse(selectedBlock.x,selectedBlock.y,20,20);
          thePlayer.collision(selectedBlock.x,selectedBlock.y,selectedBlock.w);
     }
}


void keyPressed()
{
     if (key == 'w')
     {
          thePlayer.jump();
     }

     if ( key=='a')
     {
          thePlayer.speedX = -1;
     }

     if (key == 'd')
     {
          thePlayer.speedX = 1;
     }
}

void keyReleased()
{
     if (key=='d' || key=='a')
     {
          thePlayer.speedX = 0;
     }
}

class Player
{
     float x =100;
     float y = 100;
     float speedY = 0;
     float speedX = 0;
     float size = 20;
     boolean jumpOk = false;

     void jump()
     {
          if (jumpOk == true)
          {
               speedY = -10;
               jumpOk = false;
          }
     }

     void move()
     {
          x = x + speedX;
          y = y + speedY;
          speedY = speedY + 0.3f;
     }

     void collision(float xCol, float yCol, float wCol)
     {

          if (y > yCol  && x >= xCol && x <= xCol + wCol )
          {
               println("we have collision");
               y = constrain(y, 0, yCol);
               speedY = speedY * -0.3 ;
               jumpOk = true;
          }
     }

     void show()
     {
          ellipse(x, y, size, size);
     }
}

Programming patterns

If you want a more general understanding of programming patterns and some of the common challenges I suggest that you look here:

http://fablab.ruc.dk/basic-programming-patterns/

Other code examples

Rotation

float speedX = 1;
float speedY = 1;

void setup()
{
     size(500, 500);
     background(0);
}


void draw()
{

     float angle = (float)Math.toDegrees(Math.atan2(speedY, speedX));
     pushMatrix();
     translate(200, 200);
     rotate(radians(angle));
     rect(0, 0, 100, 20);
     popMatrix();
}

KeyPressed

float batY = 0;
float batDirY = 0;
float batX = 0;
float batDirX = 0;


void setup()
{
  size(400, 300);
  background(0);
}

void draw()
{

  rect(batX, batY, 10, 30);
  batY = batY + batDirY;
  batX = batX + batDirX;
}

void keyPressed()
{
  if (key=='s')
  {
    batDirY = 1;
  }

  if (key=='w')
  {

    batDirY = -1;
  }

  if (key=='a')
  {
    batDirX = -1;
  }

  if (key=='d')
  {

    batDirX = 1;
  }
}

void keyReleased()
{
  if (key=='s' || key == 'w')
  {
    batDirY = 0;
  }

  if (key=='a' || key == 'd')
  {
    batDirX= 0;
  }
}

Chasing an object

float posX = 0;
float svampeX = 0;
float speedX = 0;

void setup()
{
     size(500,500);
}

void draw()
{
 background(0);    
     svampeX = mouseX;
     ellipse(posX,200,20,20);
     if(svampeX > posX)
     {
       speedX = 1;    
     }
     else
     {
          speedX = -1;
     }
     posX = posX + speedX;
     rect(svampeX,200,20,20);
}

Explosion

float fireX = 0;
float fireY = 0;
float fireSize = -1;
float fireSpeed = 0;

void setup()
{

     size(500, 500);
}

void draw()
{
     background(0);
     if (mousePressed)
     {
          fireX = mouseX;
          fireY = mouseY;
          fireSize = 0;
          fireSpeed = 1;
     }
     if (fireSize >= 0)
     {
          colorMode(HSB);
          fill(random(70), 100, 100);
          ellipse(fireX, fireY, fireSize, fireSize);
          colorMode(RGB);

          fireSize = fireSize +fireSpeed;
     }

     if (fireSize > 100 && fireSize > -1)
     {
          fireSpeed = -1;
     }

     if(fireSize >= 0 && dist(mouseX,mouseY,fireX,fireY)< fireSize)
     {
          fill(255,0,0);
     }
     else
     {
      fill(255);    
     }
     ellipse(mouseX,mouseY,20,20);

}

Chasing the mouse

 float botX = 100;
 float botY = 100;


 void setup()
 {
      size(200, 200);
 }

 void draw()
 {
      background(0);

      if(botX > mouseX)
      {
       botX = botX -1;    
      }

      if(botX < mouseX)
      {
       botX = botX +1;    
      }

       if(botY > mouseY)
      {
       botY = botY -1;    
      }

      if(botY < mouseY)
      {
       botY = botY +1;    
      }
      //  botY = mouseY;
      ellipse(botX, botY, 20, 20);
 }

Fluid chase

More fluid chase.

 float x =0;
 float y = 0;
 float dirX = 0;
 float dirY=0;
  float speed = 3;

 void setup()
 {

      size(600, 600);
 }

 void draw()
 {
      background(0);
      ellipse(mouseX, mouseY, 20, 20);
      ellipse(x, y, 10, 10);
      // x = x * 0.90 + mouseX*0.1;
      // y = y * 0.90 + mouseY*0.1;
      x = x + dirX;
      y = y + dirY;

      float angle = (float)Math.toDegrees(Math.atan2(y-mouseY, x-mouseX));
      dirX = -cos(radians(angle)) * speed;
      dirY = -sin(radians(angle)) * speed;
 }

Play audio file

Download the minim library:Menu>Sketch>Load Library > Add Library (search for minim)

 import ddf.minim.*;

 Minim minim;
 AudioSample kick;

 void setup()
 {

      minim = new Minim(this);


      kick = minim.loadSample( "BD.mp3", // filename
           512      // buffer size
           );
      if ( kick == null ) println("Didn't get kick!");
      kick.setGain(-40); // from -13 to -80
 }

 void draw()
 {
 }

 void keyPressed() 
 {

      if ( key == 'k' ) kick.trigger();
 }

Use images

 PImage img; 
  void setup() {
    size(640, 360);
    // The image file must be in the data folder of the current sketch 
    // to load successfully
    img = loadImage("moonwalk.jpg");  // Load the image into the program  
  }

  void draw() {
    // background image
    image(img, 0, 0,width,height);

    // follow the mouse with a 50 width and height
    image(img, mouseX, mouseY,50,50);

  }

Timing an event

 long timer = 0;
 void setup()
 {

 }

 void draw()
 {
     if(millis()-timer > 2000) // do something every two seconds)
     {
       timer = millis();
       //do something here
     }
 }