Processing lab, or “Easy easy lemon easy”

Another exciting installment of Physical Computing Labs with Tina, this time not so Physical, and with more Computing.

After getting my butt kicked by Objective C in the iPhone Lab on the 11th floor, doing Processing is like traveling to a far-off wonderful wonderland of wonderfulness. (Hmm I really need to stop writing these things at 1am.) Processing is not so much a language as it is a series of conveniently packaged shortcuts to interactivity. It’s almost a little too easy…

The lab itself was fairly straightforward. I installed Processor and followed the directions through each of the steps of the exercises.

For the first exercise, Structure, my code was as follows:

// Tina Ye, t@tinabeans.com

void setup () {
  size(640, 480);
  println("Hooray!!!");
}

void draw() {
  background(0);
}

This creates a 640-pixel wide by 480-pixel tall window for the program, and prints “Hooray!!!” in the console. It also makes the background black over and over again (60 times per second, as it were).

The second exercise, First Sketch, resulted in the following code:

// Tina Ye, t@tinabeans.com

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

void draw() {
  background(#ffffff);
  fill(#dddddd);
  ellipse(200,200,280,200);
  triangle(87, 64, 157, 114, 79, 150);
  triangle(304, 65, 312, 151, 233, 114);
  arc(118, 207, 50, 50, 0, PI);
  arc(272, 207, 50, 50, 0, PI);
  ellipse(191,284,30,14);
}

This draws an adorable sleepy cat. I cheated and drew it in Illustrator first and used that to find all my coordinates. Shhhhh.

It looks like this:

The next exercise was to play around with some color (fill and stroke). I also loaded up an image of some cool galaxy because… I think this sleepy cat is actually meditating in space, like in that movie The Fountain. Here is the source code:

// Tina Ye, t@tinabeans.com

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

void draw() {
  // set background
  PImage spacey = loadImage("galaxy.jpg");
  background(spacey);
 
  // set color of spacekitty
  float alphaval = mouseX*200/400+55;
  print(alphaval);
  fill(#ffffff, alphaval);
 
  // draw overall head shape
  noStroke();
  ellipse(200,200,280,200);
  triangle(87, 64, 157, 114, 79, 150);
  triangle(304, 65, 312, 151, 233, 114);
 
  // draw eyes
  stroke(#000000);
  noFill();
  arc(118, 207, 50, 50, 0, PI); // left eye
  arc(272, 207, 50, 50, 0, PI); // right eye
 
  noStroke();
  fill(#E79EA9);
  ellipse(191,284,30,14); // nose
}

And here is a screenshot. You can click on it to see the actual program as a Java applet. The cat also fades in and out depending on your mouse’s horizontal position.

And then I did a Josef Albers painting. That guy really liked him some squares.

// This is a Josef Albers painting.
// It is called: Homage to the Square: “Ascending” (1953)
// I like it because it looks like a square egg on a gray square plate on a blue square table.

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

void draw() {
  background(#6fa8c6);
  noStroke();
  fill(#97a2a6);
  rect(41,61,320,320);
  fill(#edebde);
  rect(79,121,240,240);
  fill(#f5ba1f);
  rect(119,182,160,160);
}

… which turns into this when you run it:

For the rest of the lab, I strayed a bit from the directions as I discovered I could have a lot more fun that way. It was easy to type something wrong in the paintbrush setup, and then get some fantastic behaviors as a result.

For the first part, I created a simple sketch that draws circle trails. I flipped the X and Y of the ellipse-to-mouse position mapping for one of the circles, and it allowed you to create symmetrical circle trails duplicated along the x=-y axis:

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

void draw() {
  if(mousePressed){
    noStroke();
    fill(#000000);
    ellipse(mouseX,mouseY+20,10,10);
    fill(#ffffff);
    ellipse(mouseY,mouseX+20,20,20);
  }
}

Click the sketch below to see it in action.

Next I added the drawing area constraints, clear button, save button, rollover effects, and click effects. I got excited and forgot to save out all the intermediate steps. But this is what the final code looks like (with comments).

/* This program allows you to draw a Rorschach test thingy */

void setup() {
  size(600,650);
 
  // loading a font resource! yay typography!
  PFont font;
  font = loadFont("Ubuntu-Bold-16.vlw");
  textFont(font);
 
  // corners of the bounding rectangle are (20,20), (580, 20), (20,580) and (580, 580)
  // Coding the bounding rectangle here because it only needs to be drawn once, so it can go in the setup
  fill(#ffffff);
  noStroke();
  rect(20,20,560,560);
 
  // the corners of the clear button are (20,600), (120,600), (20,630), (120,630)
  // drawing the Clear button...
  fill(#f40464);
  drawClearButton();
  // let's do a Save button too...
  fill(#f40464);
  drawSaveButton();
}

// so I don't have to keep typing the same stuff over and over again because the button gets redrawn on rollover/rollout/click
void drawClearButton() {
    rect(20,600,100,30);
    fill(#ffffff);
    text("Clear", 50, 620);
}

void drawSaveButton() {
    rect(140,600,100,30);
    fill(#ffffff);
    text("Save", 172, 620);
}

void draw() {
  // conditional looks for both mouse pressed and mouse position within bounds of drawing area
  // if fulfilled, then program draws the trails
  if(mousePressed && (mouseX>30 && mouseX<570) && (mouseY>30 && mouseY<570)){
    noStroke();
    fill(#5adefa);
    ellipse(mouseX,mouseY,10,10);
    fill(#00b4cf);
    ellipse(600-mouseX,mouseY,10,10);
  }
 
  // time for some rollover action! on the clear button!
  if((mouseX>20 && mouseX<120) && (mouseY>600 && mouseY<630)){
    if(mousePressed) {
      fill(#ff620d);
      drawClearButton();
    }
   else {
    fill(#ff4f95);
    drawClearButton();
   }
  }
  // put the button back the way it was if the mouse isn't over it anymore
  else {
    fill(#f40464);
    drawClearButton();
  }
 
  // time for some rollover action on the save button too!
  if((mouseX>140 && mouseX<240) && (mouseY>600 && mouseY<630)){
    if(mousePressed) {
      fill(#ff620d);
      drawSaveButton();
    }
   else {
    fill(#ff4f95);
    drawSaveButton();
   }
  }
  // put the button back the way it was if the mouse isn't over it anymore
  else {
    fill(#f40464);
    drawSaveButton();
  }
}

// for saving out multiple files
int saveNum = 1;

void mouseClicked() {
  // We need a mouseClicked function so that the screen doesn't get accidentally cleared if you drag your mouse over any of the buttons while drawing
 
  // CLEAR BUTTON
  // conditional looks for mouse position within bounds of clear button
  // if fulfilled, then program clears the stage
  if((mouseX>20 && mouseX<120) && (mouseY>600 && mouseY<630)){
      fill(#ffffff);
      noStroke();
      rect(20,20,560,560);
  }
 
  // SAVE BUTTON
  // conditional looks for mouse position within bounds of clear button
  // if fulfilled, then program clears the stage
  if((mouseX>140 && mouseX<240) && (mouseY>600 && mouseY<630)){
      save("rorschach"+saveNum+".jpg");
      saveNum++;
  }
}

The code got pretty long. I guess this is one of the downsides of Processing: you don’t have any control over the objects you create, so you have to keep redrawing them, which means more code. Actually, they aren’t even objects in memory; they are just pixel arrangements on the screen after each drawing command is executed. So to try and shorten the code, I put some of the repeat code in their own functions. The code is still pretty klunky though. But it works?

Here is the final product. Click to play!

(NOTE: The save doesn’t work on the web; this is because it just writes a file to the directory of the application and for security reasons, it’s not allowed. But if this were on your computer, it would save out Rorschach1.jpg, Rorschach2.jpg, etc… )