ICM_4_PatchBallsFlies

Category: Blog, ICM_Processing
Tags: brain-squeezing. processing.

Here’s the combination of what I’ve learned so far from Learning Processing and The Nature of Code. I call it “Patch. Balls. and Flies”. It’s kind of messy but I’m glad all the interactions with each others work! Yah! Check it out(click click )!

Functions:
1) move patch to stop bouncing balls
2) press mouse to drag balls with patch
3) long-press keyboard to see flies clubbing!! B-)   (surprisingly fit this perfectly, the most EXCITING part, DANCING time!!)
4) let go keyboard(== keyReleased) to calm down the flies, and gather all the balls within the patch

(Forgive me the awful screen pics, can’t screenshot since this one involve functions of KEY.)

bouncing

clubbing_flies

reset

Here’s some struggles I’ve been through:

  1. when dragging balls, I calculated the distance with patch and ball, and then planed to add this fixed distance to the position of patch and set it as the position of balls. But since I wrote this code in void mouseDragged(), I recalculated the distance every time I dragged and that caused flickering. Thanks to the office hour w/ Daniel Shiffman, this calculation codes were moved into void mousePressed() and it worked!!! (tearing)
  2. same stupid things happened when I want to bump flies with balls: I forgot to set conditions and thus make flies be affected by every balls!
  3. Things getting complicated when I want to make the music band. In the end I successfully saved the original color, and changed the color once it’s been hit(hitGround == true &&  cubes.x < ball.x <cubes.x+w  && ball.y < (height-h)), and then restored the colors back later.

And codes time!

Main

Mover[] movers = new Mover[20];
Band musicBand;
Rain[] rains = new Rain[50];

boolean pressing = false;

void setup() {

  size(600, 500);
  for (int i=0; i<movers.length; i++) {
    movers[i] = new Mover(random(0.5, 2.5), random(width), random(20,50));
  }

  musicBand = new Band(0, 21, 80);
  musicBand.setColor();

  for (int i=0; i<rains.length; i++) {
    rains[i] = new Rain();
  }
}

void draw() {

  background(255);

  // set up musicBand
  musicBand.checkHit();
  musicBand.display();
  musicBand.colorBack();

  // set up forces
  float c = 0.5;
  float normal = 1;
  float frictionMag = c*normal;

  PVector wind = new PVector(0.01, 0);
  PVector gravity = new PVector(0, 0.1);

  for (int i=0; i<movers.length; i++) {

    PVector friction = movers[i].velocity.get();
    friction.mult(-1);
    friction.normalize();    
    friction.mult(frictionMag);

    // if movers in the range of patch, add firction and change color
    if (movers[i].location.x > mouseX-100/2 && movers[i].location.x < mouseX+100/2
      && movers[i].location.y > mouseY-100/2 && movers[i].location.y < mouseY+100/2) {
      movers[i].applyForce(friction);

      boolean insideColor = true;
      movers[i].insideColor = insideColor;

    } else {
      boolean insideColor = false;
      movers[i].insideColor = insideColor;
    }

    movers[i].applyForce(wind);
    movers[i].applyForce(gravity);

    movers[i].update();
    movers[i].checkEdges(width, height-musicBand.h-movers[i].mass*16/2);
    movers[i].display();

  }

  // set up flies
  for (int j=0; j<rains.length; j++) {

    // be affected by balls
    for (int i=0; i<movers.length; i++) {
      rains[j].updateMover(movers[i].location.x, movers[i].location.y);
    }

    rains[j].checkFloor();
    rains[j].show();
  }

  // patch
  rectMode(CENTER);
  pushStyle();
  noStroke();
  fill(150,50);
  rect(mouseX, mouseY, 100, 100);
  stroke(220,100);
  for (int i=0; i<=100; i+=5) {
    line(mouseX-50+i, mouseY-50, mouseX-50+i, mouseY+50);
  }
  for (int i=0; i<=100; i+=5) {
    line(mouseX-50, mouseY-50+i, mouseX+50, mouseY-50+i);
  }
  popStyle();
  rectMode(CORNER);

  // event when key pressed
  if (pressing == true) {
    pushStyle();
    fill(0);
    noStroke();
    rect(0,0,width,height);
    popStyle();
  }

}

void mousePressed() {

  for (int i=0; i<movers.length; i++) {

    // if in the range of the patch, be able to drag balls
    if (movers[i].location.x > mouseX-100/2 && movers[i].location.x < mouseX+100/2 &&
      movers[i].location.y > mouseY-100/2 && movers[i].location.y < mouseY+100/2) {

      boolean inside = true;
      movers[i].inside = inside;

      PVector mouse = new PVector(mouseX, mouseY);
      PVector dis = PVector.sub(movers[i].location, mouse);
      movers[i].dis = dis;

    } else {

      boolean inside = false;
      movers[i].inside = inside;
    }

  }
}

void mouseDragged() {
  for (int i=0; i<movers.length; i++) {

    PVector mouse = new PVector(mouseX, mouseY);
    if (movers[i].inside == true) {
      movers[i].location = PVector.add(mouse, movers[i].dis);
    }

  }
}

void keyPressed() {
  background(0);

  pressing = true;

  // calm down all the balls and gather them into patch
  for (int i=0; i<movers.length; i++) {
    movers[i].location.x = mouseX+random(-40,40);
    movers[i].location.y = mouseY+random(-30,30);;
    movers[i].velocity.mult(0);
    movers[i].acceleration.mult(0);
  }

  for (int j=0; j<rains.length; j++) {
    rains[j].checkFloor();
    rains[j].show();
  }

}

void keyReleased() {
  pressing = false;

  // reset all the flies
  for (int j=0; j<rains.length; j++) {
    rains[j] = new Rain();
  }

}

Mover

class Mover {

  PVector location;
  PVector velocity;
  PVector acceleration;

  float mass;

  PVector dis;
  boolean inside = false;
  boolean insideColor = false;

  boolean lastHitState = false;
  boolean hitState = false;
  boolean hitGround = false;

  Mover() {
    location = new PVector(random(width/2), random(height/2));
    velocity = new PVector(0, 0);
    acceleration = new PVector(0, 0);
    mass = 1;
  }

  Mover(float m, float x, float y) {
    mass = m;
    location = new PVector(x, y);
    velocity = new PVector(0, 0);
    acceleration = new PVector(0, 0);
  }

  void update() {

    velocity.add(acceleration);
    location.add(velocity);
    acceleration.mult(0);
  }

  void display() {
    pushStyle();
    noStroke();

    float time = second();
    fill(time % 255, 50);
    ellipse(location.x, location.y, mass*20, mass*20);

    if (insideColor == true) {
      fill(252, 255, 3, 180);
    } else {
      fill(0, 232, 254, 150);
    }

    ellipse(location.x, location.y, mass*12.5, mass*12.5);

    popStyle();
  }

  void checkEdges(float w, float h) {
    if (location.x > w) {
      location.x = w;
      velocity.x *= -1;
    } 
    else if (location.x < 0) {
      location.x = 0;
      velocity.x *= -1;
    }

    if (location.y > h) {
      location.y = h;
      velocity.y *= -1;
      hitGround = !hitGround;
    }

    if (location.y < h-100) {
      hitGround = false;
    }

  }

  void applyForce(PVector force) {
    PVector f = PVector.div(force, mass);
    acceleration.add(f);
  }
}

Rain

class Rain{

  PVector location;
  PVector velocity;
  PVector acceleration;
  PVector distance;
  PVector distanceRain;

  Bug bug;

  float w, h;
  float topSpeed;
  color c;

  Rain() {

    location = new PVector(random(width), -50);
    velocity = new PVector(random(-0.1, 0.1), random(-0.1, 0.1));
    distance = new PVector(20, 20);
    distanceRain = new PVector(10, 10);

    w = 4;
    h = 6.5;
    topSpeed = 3;

  }

  void show() {

    smooth();
    pushStyle();

    noStroke();
    bug = new Bug(location.x, location.y, w, h);
    bug.show();

    popStyle();
  }

  void updateMover(float x_, float y_) {

    PVector mover = new PVector(x_, y_);
    PVector dir = PVector.sub(mover, location);

    acceleration = new PVector(0, 0);

    if (dir.mag() < distanceRain.mag()) {

      dir.normalize();
      dir.x *= random(-0.2);
      dir.y *= random(-0.2);
      acceleration = dir;

    }

    velocity.add(acceleration);
    velocity.limit(topSpeed);
    location.add(velocity);
  }

  void checkFloor() {

    if (location.y > (height - musicBand.h)) {
      location.y = 0;
    } else if (location.y < 0) {
      location.y = (height - musicBand.h);
    }

    if (location.x > width) {
      location.x = 0;
    } else if (location.x < 0) {
      location.x = width;
    }

  }

}

Drop

class Drop{

  float x, y, w, h;

  Drop(float _x, float _y, float _w, float _h) {
    x = _x;
    y = _y;
    w = _w;
    h = _h;
  }

  void show() {

    pushStyle();
    smooth();
    noStroke();
    triangle(x, y-h, x+w/2, y, x-w/2, y);
    ellipse(x, y, w, w);
    popStyle();
  }

}

Cube

class Cube{
  float x; 
  float y;
  float w, h;
  color c;

  boolean beHit;

  Cube(float _x, float _y, float _w, float _h, color _c) {
    x = _x;
    y = _y;
    w = _w;
    h = _h;
    c = _c;
    beHit = false;
  }

  void display() {
    pushStyle();
    noStroke();
    fill(c);
    rect(x, y, w, h);
    popStyle();
  }

}

Bug

class Bug{

  float x, y, w, h;
  Drop[] drops;

  Bug(float _x, float _y, float _w, float _h) {
    x = _x;
    y = _y;
    w = _w;
    h = _h;
    drops = new Drop[4];
  }

  void show() {
    pushStyle();
    smooth();
    fill(173, 191, 216, 150);

    pushMatrix();
    translate(x, y);
    rotate(radians(40));
    drops[0] = new Drop(0, 6, w, h);
    drops[0].show();
    rotate(radians(70));
    drops[1] = new Drop(0, 6, h, h);
    drops[1].show();
    rotate(radians(140));
    drops[2] = new Drop(0, 6, h, h);
    drops[2].show();
    rotate(radians(70));
    drops[3] = new Drop(0, 6, w, h);
    drops[3].show();

    popMatrix();
    popStyle();
  }

}

Band

class Band {
  float x; 
  float y;
  float w, h;
  int interval;
  color[] colors;
  color[] colorSave;

  Cube[] cubes;

  Band(float _x, int _interval, float _h) {
    x = _x;
    interval = _interval;
    h = _h;

    w = width / interval;
    y = height - h;
    colors = new color[interval];
    colorSave = new color[interval];
    cubes = new Cube[interval];
  }

  void setColor() {
    for (int i=0; i<interval; i++) {
      float cc = random(130);
      colors[i] = color(cc, cc+120, cc+60);
      colorSave[i] = colors[i];
    }
  }

  void checkHit() {
    for (int i=0; i<interval; i++) {
      for (int j=0; j<movers.length; j++) {
        if (movers[j].hitGround == true && movers[j].location.x > cubes[i].x && 
          movers[j].location.x < cubes[i].x+w && movers[j].location.y < (height-h)) {
          float cc = random(130);
          colors[i] = color(cc+120, cc+120, 0);
        }
      }
    }
  }

  void colorBack() {
    for (int i=0; i<interval; i++) {
      for (int j=0; j<movers.length; j++) {
        if (movers[j].hitGround == false) {
          colors[i] = colorSave[i];
        }
      }
    }
  }

  void display() {
    float tempX = x;

    for (int i=0; i<interval; i++) {
      cubes[i] = new Cube(tempX, y, w, h, colors[i]);
      cubes[i].display();
      tempX += w;
    }
  }

}

Leave a Reply

Your email address will not be published. Required fields are marked *