The Processing code begins by importing the Network library and setting up the HTTP client as myClient. This is part of the setup for communication over the socket with the Python script.

import processing.net.*;

// HTTP client
Client myClient;

A Lot of Variables

Before the setup, the variables for the various animations are declared. Their purpose is commented in the code.

// variables for receiving data from Blinka socket
int index;
String inString;

// holding the red, green, blue data
String[] r;
String[] g;
String[] b;
int red;
int green;
int blue;

// holding the VL53L4CD data
String[] f;
int flight;

// cat and pizza images
//emojis are from the OpenMoji emoji library (https://openmoji.org/)
PImage cat_img; 
PImage pizza_img;

// colors for Circles animation
color c_red = color(255, 0, 0);
color c_green = color(0, 255, 0);
color c_blue = color(0, 0, 255);
color c_yellow = color(255, 125, 0);
color c_aqua = color(0, 125, 255);
color c_purple = color(255, 0, 255);

IntList colors; 

// float for Cube animation
float i = 0.0;

// variables for Circles animation
int rad = 60;        
float xpos, ypos;       

float xspeed = 2.8;  
float yspeed = 10;  

int xdirection = 1;  
int ydirection = 1;  

// variables for pizzaCat animation
int pizzaCount = 32;
int catCount = 32;
int emojiCount = 32;

PImage[] cats = new PImage[catCount];
PImage[] pizzas = new PImage[pizzaCount];

float[] moveX = new float[emojiCount];
float[] moveY = new float[emojiCount];

float last_speed;

float[] x_dir = new float[emojiCount];
float[] y_dir = new float[emojiCount];
float[] x_speeds = new float[emojiCount];
float[] y_speeds = new float[emojiCount];

// variables for dancingTriangles animation
int x1;
int y1;
int x2; 
int y2;
int x3;
int y3;

The Setup

To run the animations full screen, fullScreen() is called with P3D. P3D is a renderer in Processing that allows for a z-axis parameter. The Cube animation requires this.

An integer list called colors is used in the Circles animation. colors.append() is called to add the colors to the list that were defined before setup().

The loadImage() function loads the .png image files that are used in the Pizza Cat animation.

Three for statements are used to setup the Pizza Cat animation. The cat_img and pizza_img are loaded into arrays and the starting coordinates and speeds for each emoji instance is setup.

Finally, myClient is setup to connect to the socket on port 12345.

void setup() 
{
  // setting animations to run fullscreen with P3D
  fullScreen(P3D);
  // RGB color mode with value range of 0-255
  colorMode(RGB, 255);
  ellipseMode(RADIUS);
  // setting xpos and ypos in center
  xpos = width/2;
  ypos = height/2;
  
  // creating array of colors
  // this is used for the Circles animation
  colors = new IntList();
  colors.append(c_red);
  colors.append(c_yellow);
  colors.append(c_green);
  colors.append(c_aqua);
  colors.append(c_blue);
  colors.append(c_purple);
  
  // loading the cat and pizza images
  cat_img = loadImage("cat.png");
  pizza_img = loadImage("pizza.png");
  
  // adding pizza and cat emojis to their arrays
  for (int slice = 0; slice  < 15; slice ++) {
    pizzas[slice] = pizza_img;
  }
  for (int claw = 16; claw< catCount; claw++) {
    cats[claw] = cat_img;
  }
  // creating arrays of coordinates and speed for pizzaCat
  for (int z = 0; z < emojiCount; z ++) {
    x_dir[z] = random(width);
    y_dir[z] = random(height);
    x_speeds[z] = random(5, 20);
    y_speeds[z] = random(5, 20);
    moveX[z] = x_speeds[z];
    moveY[z] = y_speeds[z];
  }
  
  // connecting to socket to communicate with Blinka script
  myClient = new Client(this, "127.0.0.1", 12345);

}

Reading the Socket

In Processing, draw() is the loop. The code contained in draw() will run forever.

draw() begins by checking if any data is coming in over the socket. inString is used to hold the data coming in over the socket as a string. If you recall in the Python code, the data from the hardware is being encoded as a string before it is sent over the socket.

// void draw() is the loop in Processing
void draw() 
{
  //if data is coming in over the socket...
  if (myClient.available() > 0) {
    //string data is stored in inString
    inString = myClient.readString();

Right now, the string coming over the socket is one long string. For example, if the rotary encoder was set to 2, then the string would come in as "enc 2". For this information to be useful for Processing, the 2 needs to be parsed out from the string and changed to an integer.

An if statement is used to check if inString begins with the string variable from the Python script. If it's a match, then a String[] object is setup. splitTockens() is used to slice inString into separate strings separated by a space. Going back to the example of "enc 2", that means that it would be sliced to be "enc" and "2".

An integer variable holds index 1 of the String[] object. Index 1 is also converted to an integer from a string. 

//if the string begins with 'enc'
    //aka is a msg from the rotary encoder...
    if (inString.startsWith("enc")) {
      // the encoder pos is stored in index
      String[] q = splitTokens(inString);
      index = int(q[1]);
    }

And that is how the data from the Python script is brought into Processing!

Similar if statements are setup for the three NeoSliders and the VL53L4CD.

//if the string begins with 'red'
    //aka is from the red neoslider
    if (inString.startsWith("red")) {
      //the red value is stored in red
      String[] r = splitTokens(inString);
      red = int(r[1]);
    }
    //if the string begins with 'green'
    //aka is from the green neoslider
    if (inString.startsWith("green")) {
      // the green value is stored in green
      String[] g = splitTokens(inString);
      green = int(g[1]);
    }
    //if the string begins with 'blue'
    //aka is from the blue neoslider
    if (inString.startsWith("blue")) {
      //the blue value is stored in blue
      String[] b = splitTokens(inString);
      blue = int(b[1]);
    }
    //if the string begins with flight
    //aka is from the VL53L4CD
    if (inString.startsWith("flight")) {
      //the time of flight value is stored in flight
      String[] f = splitTokens(inString);
      flight = int(f[1]);
    }

Changing Animations

The current animation is controlled by the position of the rotary encoder. A series of if statements are setup to check on the rotary encoder's position. The animations are setup as functions outside of draw() so that they can be called independently.

//the encoder's position corresponds with which animation plays
  if (index == 0) {
    circles();
    }

  if (index == 1) {
    cube();
    }
  if (index == 2) {
    dancingTriangles();
    }
  if (index == 3) {
    pizzaCat();
    }

The Animations

The four included animations are designed to be fairly simple so that you can get an idea of how Processing works.

Circles

The circles() animation randomly generates circles in a line in the middle of the screen that are random colors from the colors[] list. The size of the circles is determined by the VL53L4CD.

The background color is created by the values from the NeoSliders that are held in red, green and blue. The VL53L4CD's data is held in int size, which has the value range of flight mapped to a range of 300 to 25. This allows the circles to get larger the closer you are to the sensor and smaller the farther away you are.

//the Circles animation
//colorful circles randomly appear in the middle of the screen
//background color is affected by the sliders
//the circles' size is affected by the VL53L4CD
void circles() {
  background(red, green, blue);
  strokeWeight(1);
  
  ypos = ypos + ( yspeed * ydirection );
  
  if (ypos > height-rad || ypos < rad) {
    ydirection *= +1;
  }

  int size = int(map(flight, 0, 45, 300, 25));
  
  for (int i = 0; i < 10; i++) {
    for (int z = 0; z < 6; z++) {
      fill(colors.get(z));
      circle(width/2, random(ypos), random(size));
    }
  }
}

Cube

The cube() animation is a hollow, 3D spinning cube. Its background color is affected by the NeoSliders. The speed of the cube's spin is affected by the VL53L4CD. float speed maps the VL53L4CD's range from 10 to 0.1. The closer you are to the sensor, the faster the cube spins.

//the Cube animation
//a 3D cube spins in the center of the screen
//background color is affected by the sliders
//the speed of the spinning cube is affected by the VL53L4CD
void cube() {
  strokeWeight(5);
  
  float speed = map(flight, 0, 45, 10, 0.1);
  
  background(red, green, blue);
  translate(width/2, height/2, 0);
  
  i = i + speed;
  if (i > 180) {
    i = 0.0;
  }
    rotateY(radians(i));
    noFill();
    box(500);
}

Pizza Cat

The pizzaCat() animation demonstrates bringing in image files to a Processing script. Here, pizza and cat emojis bounce around the screen at different speeds.

Its background color is affected by the NeoSliders. The green NeoSlider is affecting how many cat emojis are on the screen. The blue NeoSlider is affecting how many pizza emojis are on the screen. The VL53L4CD is affecting the speed of the pizza and cat emojis' bounce.

//the Pizza Cat animation
//pizza and cat face emojis bounce around the screen
//emojis are from the OpenMoji emoji library (https://openmoji.org/)
//the background color is affected by the sliders
//the speed of the emojis are affected by the V53L4CD
//green slider affects # of cats
//blue slider affects # of pizzas
void pizzaCat() { 
  background(red, green, blue);
  float meow = map(green, 0, 255, 32, 16);
  float pie = map(blue, 0, 255, 15, 0);
  float speed = map(flight, 0, 45, 0, 25);
  
    for (int e = 16; e < meow; e++) {
      if (last_speed != speed) {
        moveX[e] = x_speeds[e] + speed;
        moveY[e] = y_speeds[e] + speed;
      }
      else {
        moveX[e] = moveX[e];
        moveY[e] = moveY[e];
      }
      x_dir[e] += moveX[e];
      if (x_dir[e] < 0 || x_dir[e] > width) {
        moveX[e] *= -1;
        
      }
      if (x_dir[e] > width) {
        x_dir[e] = (width - 2);
      }
      y_dir[e] += moveY[e];
      if(y_dir[e] < 0 || y_dir[e] > height) {
        moveY[e] *= -1;
        
      }
      if (y_dir[e] > height) {
        y_dir[e] = (height - 2);
      }

    image(cats[e], x_dir[e], y_dir[e]);
    
    }
    for (int p = 1; p < pie; p++) {
      if (last_speed != speed) {
        moveX[p] = x_speeds[p] + speed;
        moveY[p] = y_speeds[p] + speed;
      }
      else {
        moveX[p] = moveX[p];
        moveY[p] = moveY[p];
      }
      x_dir[p] += moveX[p];
      if (x_dir[p] < 0 || x_dir[p] > width) {
          moveX[p] *= -1;
      }
      if (x_dir[p] > width) {
        x_dir[p] = (width - 2);
      }
      y_dir[p] += moveY[p];
      if(y_dir[p] < 0 || y_dir[p] > height) {
        moveY[p] *= -1;
      }
      if (y_dir[p] > height) {
        y_dir[p] = (height - 2);
      }

    image(pizzas[p], x_dir[p], y_dir[p]);
    }
    last_speed = speed;
}

Dancing Triangles

The dancingTriangles() animation randomly generates a hollow 2D triangle with random coordinates in the middle of the screen. Its background color is affected by the NeoSliders.

The VL53L4CD is affecting the speed at which the triangles are being generated. The value of int speed is mapped to create a delay range of 25 to 100. The closer you are to the sensor, the slower the triangles will generate.

// the dancingTriangles animation
// triangles are randomly generated in the center of the screen
//the background is affected by the sliders
// the speed of new triangles being added are affected by the V53L4CD
void dancingTriangles() {
  int speed = int(map(flight, 0, 45, 25, 100));
  
  background(red, green, blue);
  strokeWeight(30);
  
  for (int w = 800; w < 1000; w ++) {
    for (int h = 1100; h < 1500; h++) {
    
      x1 = int(random(h));
      y1 = int(random(w));
    
      x2 = int(random(h));
      y2 = int(random(w));
    
      x3 = int(random(h));
      y3 = int(random(w));
     }
   }
  noFill();
  triangle(x1, y1, x2, y2, x3, y3);
  delay(speed);
}

This guide was first published on Mar 29, 2022. It was last updated on 2022-03-29 22:34:39 -0400.

This page (How the Processing Code Works) was last updated on Apr 23, 2022.

Text editor powered by tinymce.