Your browser does not support the canvas tag.

Week 6
Troubleshooting: A few of you are trying to write a lot of code all at once and having multiple errors. You want to keep constantly testing your code as you write. This way if something breaks, you know it was (probably) the last thing you just did - that's way easier to track down.
Everybody codes this way, not just beginners.

Timely art project by our very own Paul Thayer. Guns on Parade

Monty Hall Problem :(
Marilyn vos Savant
Plays into both our the "Gambler's fallacy" and the "Hot Hand fallacy". The down side of learning about math is that the more you know the less fun gambling it. Question, why to table games have limits?
Richard Stallman


Collision detection with circles

Are these circles touching? Are you sure? can you prove it?

In order to see if ellipses are colliding we need to calculate the distance between their centers, then check to see if the radii of both circles combined is more or less than the distance.
First problem is getting the distance - we solve it with good olde Pythagoras' help.
The square of the hypotenuse of a right triangle is equal to the sum of the square of the opposite two sides.
Each point has an x and y value and we already know what these are, so think of an imaginary right triangle with these points at the scalene (pointy) corners. To get the distance of 'a' we subtract the y value of one point from the y value of the other. Repeat the same step for 'b' with the x values. Now Square both a and b and add then together. Finally, c will be equal to the root of that number! It's magic!
// long verbouse code do not use! 
void setup() {
  size(200, 200);
}
void draw() {
  float x2 = 30; 
  float x1 = 147; 
  float y1 = 185; 
  float y2 = 20; 
  float a = x2 - x1; 
  float b = y2 - y1; 
  float c = sqrt(a * a + b * b);
  println(c); 
  line(x1, y1, x2, y2);
}
Okay, that's a lot of code. You could squish it down to one line like this.
 float c = sqrt(sq(x2 - x1)+sq(y2 - y1)); 
But this being Processing, there's an even simpler way which is using dist();
This is how you should actually do it. All that code above is just stupid teacher stuff
 float c = dist(x1, y1, x2, y2); 
But even though we use dist, it's important to remember that the code for dist uses the Pythagorean theorem. I think it's cool that this ancient formula is still the best way to make this calculation. Hooray for math!
This script uses dist() and an if statement to see if the distance is less that the sum of the radii of the two circles.
int locX = 50; 
int locY = 80; 
int size1 = 60; 
int size2 = 40; 
void setup() {
  size(200, 200);
}
void draw() {
  background(200); 
  float d = dist(locX, locY, mouseX, mouseY); 
  if (d < size1/2 + size2/2) {
    fill(255, 0, 0);
  } else {
    fill(0, 0, 255);
  }
  ellipse(locX, locY, size1, size1); 
  ellipse(mouseX, mouseY, size2, size2);
}

This code expands on the in class assignment from last week and adds a couple freatures. 1. we've give each ball a color by creating a color array 2. we've added collision detection between balls. We use the same method as above for collision detection only for every ball, we check to see if it is colliding with every other ball. This means for every ball in the for loop, we run ANOTHER FOR LOOP!
int arraySize = 30; 
float [] xArray = new float[arraySize]; 
float [] yArray = new float[arraySize]; 
float [] xspeedArray = new float[arraySize]; 
float [] yspeedArray = new float[arraySize]; 
color[] bcolorArray = new color[arraySize]; 
boolean colorReset = false; 
int ballSize = 30;  

void setup() {
  size(800, 300); 
  noStroke(); 
  for (int i = 0; i < xArray.length; i ++) {
    xArray[i] = random(width); 
    yArray[i] = random(height);
    xspeedArray[i] = random(-5, 5); 
    yspeedArray [i] = random(-5, 5);
    bcolorArray [i] = color(random(255), random(255), random(255));
  }
}
void draw() {
  fill(200, 10); 
  rect(0, 0, width, height); 
  colorReset = true;
  for (int i = 0; i < xArray.length; i ++) {
    xArray [i] += xspeedArray [i] ; 
    yArray [i] += yspeedArray [i]; 
    if (xArray [i] > width || xArray [i] < 0) {
      xspeedArray [i] *= -1;
    }
    if (yArray [i] > height || yArray [i] < 0) {
      yspeedArray [i] *= -1;
    }
    fill(bcolorArray[i]); 
    ellipse(xArray[i], yArray[i], ballSize, ballSize);
    // collision detection area
    for (int j = 0; j < xArray.length; j ++) { // go through each ball 
      if ( bcolorArray[i] !=  bcolorArray[j] ) {
        colorReset = false; // if the colors are different set a boolean
      }
      float distance = dist(xArray[i], yArray[i], xArray[j], yArray[j]); 
      if (distance < ballSize/2 + ballSize/2) {
        if (random(2) > 1) {
          bcolorArray[i] = bcolorArray[j];
        } else {
          bcolorArray[j] = bcolorArray[i];
        }
      }
    }
    // end collision detection area
  }
  if (colorReset == true) { // if the boolean never goes false then all the colors are the same
    for (int i = 0; i < bcolorArray.length; i ++) {
      bcolorArray [i] = color(random(255), random(255), random(255));
    }
  }
}
Walk cycle bones. First solve the problem of making a circle move to where you click.
int locX = 20; 
int locY = 200; 
int Speed = 7; 
int Destination = locX;

void setup() {
  size(400, 400);
  smooth();
}
void draw() {
  background(200); 
  ellipse(locX, locY, 20, 20);
   if (locX + Speed< Destination) {
    locX += Speed; 
  } 
  else if (locX - Speed> Destination) {
    locX  -= Speed; 
  }
}
void mouseReleased(){
  Destination = mouseX; 
}
Next, add a sequenced animation from last week and draw it where you would draw the circle. Easy Peasy.

Tim Cook will serve as the example image for Pixel arrays

Pixel Array

When we load images, we are actually just loading a big array of color variables, one for each pixel in the image. Now that we know how arrays work we can go in and mess with those pixels! This is awesome. To do this you must

In this sketch we're setting the pixel value to the value one of the pixel's neighbors. How far away that neighbor is depends on a random range dictated by the mouseX value.
PImage img;
void setup() {
  size(213, 284);
  img = loadImage("cook.jpg");
}
void draw() {  
  image(img, 0, 0);
  loadPixels();
  int glitchNum = mouseX/4; 
  for (int i = 0; i < pixels.length; i ++) {
    if(i > glitchNum && i < pixels.length - glitchNum){
      pixels[i] = pixels[i - int(random(-glitchNum, glitchNum))] ; 
    }
  }
  updatePixels();
}
This one swaps the red green and blue values of each pixel when you click the mouse.

PImage img;
boolean pressed; 
void setup() {
  size(213, 284);
  img = loadImage("cook.jpg");
}
void draw() {  
  image(img, 0, 0);
  if (pressed == true) {
    loadPixels();
    for (int i = 0; i < pixels.length; i ++) {
      color pix = pixels[i]; 
      float r = red(pix);  
      float g = green(pix); 
      float b = blue(pix); 
      color newpix = color(g, b, r); 
      pixels[i] = newpix;
    }
    updatePixels();
  }
}

void mousePressed() {
  pressed = true;
}

void mouseReleased() {
  pressed = false;
}


The pixel array only holds color information of every pixel, it does not know where that pixel is on the screen. We can, however, get the pixel dimensions with imageName.width and imgaeName.height. Using two for loops, and the get(x, y) command we can extrapolate the color value of a pixel at any given location.

You don't actually need to draw the image in order to get the pixel information from it. The following code uses the line
img.loadPixels();
instead of the usual
loadPixels();

Now, because you've loaded the pixels from that image into memory, if you want to get pixel information you can use img.get(x, y) or img.pixels[]. The advantage with this approach is we can create a visualization on the screen that references the image, without having to actually draw the image.

PImage img;
boolean pressed; 
int circleSize = 1;  

void setup() {
  size(213, 284);
  img = loadImage("cook.jpg");
  noStroke();
}

void draw() {  
  background(255); 
  circleSize = int(map(mouseY, 0, width, 1, 20));  
  img.loadPixels(); 
  for (int i = 0; i < width + circleSize/2; i += circleSize+2) {
    for (int j = 0; j < height + circleSize/2; j+= circleSize + 2) {
      color pix = img.get(i, j); 
      fill(pix);  
      ellipse(i , j, circleSize, circleSize);
    }
  }
}

There is NO WAY to combine an array of looping images like we had in week 5 with this pixel array information ... or is there?

This sketch uses the eye images from week 6

int numFrames = 6;  // The number of frames in the animation
int frame = 0;
PImage[] images = new PImage[numFrames];
int timer; 
float framespeed = 200; 
int circleSize = 3; 

void setup()
{
  size(600, 400);
  images[0]  = loadImage("eye_0000.jpg");
  images[1]  = loadImage("eye_0001.jpg"); 
  images[2]  = loadImage("eye_0002.jpg");
  images[3]  = loadImage("eye_0003.jpg"); 
  images[4]  = loadImage("eye_0004.jpg");
  images[5]  = loadImage("eye_0005.jpg"); 
  timer = millis(); 
  imageMode(CENTER);
  smooth();  
  strokeWeight(2);
} 

void draw() 
{ 
  if (millis() - timer > framespeed) {
    timer = millis(); 
    frame ++; 
    if (frame == numFrames) {
      frame = 0;
    }
  }  
  images[frame].loadPixels();
  for (int i = 0; i < images[frame].width; i += circleSize + 3) {
    for (int j = 0; j < images[frame].height; j+= circleSize + 3) {
      color pix = images[frame].get(i, j); 
      fill(pix);  
      stroke(green(pix), blue(pix), red(pix)); 
      float newx = map(i, 0, images[frame].width, -20, width); 
      float newy = map(j, 0, images[frame].height, -20, height); 
      ellipse(newx, newy, 20, 20);
    }
  }
}


In this example we have two PImages, one we load as we normally would, but the other we create a blank PImage array with the line
destination = createImage(width, height, RGB);
In the two for loops we look at every pixel of the curler image, and we put those pixels into the "destination" pixel array. HOWEVER, we can alter where in the destination array we put the pixel information. So when the mouse is pressed it sets c, the color information, at a different location in the destination array. In this case instead of putting it at the normal width location (i), it put is at width - i, which results in a mirrored image.

PImage p1; 
PImage destination; 
color c, newpix;
boolean click; 

void setup() {
  size(380, 590);
  background(255);
  p1 = loadImage("curler.jpg");
  destination = createImage(width, height, RGB);
}

void draw() {
  p1.loadPixels();
  destination.loadPixels();  
  for (int i = 0; i < p1.width; i ++) {
    for (int j = 0; j < p1.height; j ++) {
      c= p1.get(i, j); 
      if (mousePressed == true){
       destination.set(i, j, c); 
      }
      else{
       destination.set(width - i, j, c); 
      }
    }
  } 
  destination.updatePixels();
  image(destination, 0, 0);
}
This example takes one image and compares the pixel brightness to an iterating variable. If the pixel is brighter it sets the destination to the pixel from the first image, if it's darker it takes the pixel from the other.

PImage p1; 
PImage p2;
PImage destination; 
color c, c2, newpixel;
int shifter = 100; 

void setup() {
  size(320, 480);
  background(255);
  p1 = loadImage("curler.jpg");
  p2 = loadImage("cat.jpg");
  destination = createImage(width, height, RGB);
}

void draw() {
  p1.loadPixels();
  p2.loadPixels();
  destination.loadPixels();
  shifter ++; 
  if (shifter >= 255) {
    shifter = 0;
  }  
  for (int i = 0; i < p1.width; i ++) {
    for (int j = 0; j < p1.height; j ++) {
      c= p1.get(i, j); 
      c2= p2.get(i, j); 
      if (brightness(c2) < shifter) {
        newpixel =  c;
      }
      else {
        newpixel =  c2;
      }
      destination.set(i, j, newpixel); 
    }
  }
  destination.updatePixels();
  image(destination, 0, 0);
}

It starts at the first pixel in each image and calculates the difference between the red green and blue values. Then it uses shifter to map a number that is somewhere between one pixel and the other.

There's a couple new things in this sketch worth looking up.

PImage p1; 
PImage p2;
PImage destination; 
color c, c2, newpix;
boolean shifterDirection; 
void setup() {
  size(380, 590);
  background(255);
  p2 = loadImage("cat.jpg");
  p1 = loadImage("curler.jpg");
  destination = createImage(p1.width, p1.height, RGB);
  noCursor();
}

void draw() {
  background(255); 
  p1.loadPixels();
  p2.loadPixels();
  destination.loadPixels();  
  for (int i = 0; i < p1.width; i ++) {
    for (int j = 0; j < p1.height; j ++) {
      c = p1.get(i, j); 
      c2 = p2.get(i, j);
      float d = dist(mouseX, mouseY, i, j); 
      d = constrain(d, 0, 120); 
      float newd = map(d, 0, 120, 0, 1); 
      newpix  = lerpColor(c, c2, newd); 
      destination.set(i, j, newpix);
    }
  }
  destination.updatePixels();
  image(destination, 0, 0);
}

void mouseReleased() {
  saveFrame("meerkat_curler###.jpg");
}