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); }
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]); }
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); }
Page last edited March 08, 2024
Text editor powered by tinymce.