As computing becomes more ubiquitous in our objects, designers need to be more aware of how to design meaningful interactions into electronically enhanced objects. At the University of Washington, a class of junior Interaction Design majors is exploring this question. These pages chronicle their efforts.

Thursday, April 5, 2012

Jill Moses Assignment 1: Stop & Ease


This is my sketch based off of the Ease example on Processing. I modified the original sketch by changing the easing distance and speed. As well as the x,y position the ball eases to.

In addition, I added an outside input output function. When the mouse is clicked the easing function is halted and the mouse can move freely without the annoying little brother ball. The mouse can run, but only as long as the mouse is held down. When released, the little nuisance runs after. And the ball is back to easing the cursor.


Assignment 1 Click here

Bridget Weis_Letter K Revised

/**
 *My Name
 * by Bridget Weis
 *Based on Processing Example
 *
 *Letter K
 * by Peter Cho.
 *
 * Move the mouse across the screen to fold the "K".
 */

color backgroundColor;
color foregroundColor;
color foregroundColor2;


PFont didot;

float px, py;
float pfx, pfy;
float pv2, pvx, pvy;
float pa2, pax, pay;
float pMass, pDrag;

void setup() {
  size(800, 400, P3D);
  didot = loadFont("DidotTwo.vlw");
  noStroke();
  backgroundColor = color(255, 255, 255);
  foregroundColor = color(39, 139, 148);
  foregroundColor2 = color(13, 67, 72, 175);
  initParticle(0.6, 0.9,  width/2, height/2);
}

void draw() {
  background(backgroundColor);
  pushMatrix();

  iterateParticle(0.15*(-px+mouseX), 0.15*(-py+(height-mouseY)));

  translate(width/2, height/2, 0);
  fill(foregroundColor);
  drawtext();

  pushMatrix();
  translate(0, 0, 1);
  translate(0.75 * (px-width/2), -0.75 * (py-height/2), 0);
  translate(0.75 * (px-width/2), -0.75 * (py-height/2), 0);
  rotateZ(atan2(-(py-height/2), (px-width/2)) + PI/2);
  rotateX(PI);
  rotateZ(-(atan2(-(py-height/2), (px-width/2)) + PI/2));
 
  fill(foregroundColor2);
  drawtext();
  popMatrix();

  translate(0.75 * (px-width/2), -0.75 * (py-height/2), 2);
  rotateZ(atan2(-(py-height/2), (px-width/2)) + PI/2);
 
  fill(backgroundColor);
  beginShape();
  vertex(-800, 0);
  vertex( 800, 0);
  vertex( 800, -400);
  vertex(-800, -400);
  endShape();
 
  popMatrix();

}

void initParticle(float _mass, float _drag, float ox, float oy) {
  px = ox;
  py = oy;
  pv2 = 0.0;
  pvx = 0.0;
  pvy = 0.0;
  pa2 = 0.0;
  pax = 0.0;
  pay = 0.0;
  pMass = _mass;
  pDrag = _drag;
}

void iterateParticle(float fkx, float fky) {
  // iterate for a single force acting on the particle
  pfx = fkx;
  pfy = fky;
  pa2 = pfx*pfx + pfy*pfy;
  if (pa2 < 0.0000001) {
    return;
  }
  pax = pfx/pMass;
  pay = pfy/pMass;
  pvx += pax;
  pvy += pay;
  pv2 = pvx*pvx + pvy*pvy;
  if (pv2 < 0.0000001) {
    return;
  }
  pvx *= (1.0 - pDrag);
  pvy *= (1.0 - pDrag);
  px += pvx;
  py += pvy;
}

void drawtext() {
  pushMatrix();
  scale(1);
  translate(-350, 30);
  textFont(didot, 200);
  text("Bridget", 10, 50);

  //translate(63, -71);
  popMatrix();
 

 
}

Aaron’s Processing


/**
 * Load File
 * by Damien Di Fede.
 * edited by Aaron Calzado for ART 387 Spring 2012
 *
 * This sketch demonstrates how to use the <code>loadFile</code> method
 * of <code>Minim</code>. The <code>loadFile</code> method allows you to
 * specify the file you want to load with a <code>String</code> and optionally
 * specify what you want the buffer size of the returned <code>AudioPlayer</code>
 * to be. If you don't specify a buffer size, the returned player will have a
 * buffer size of 1024. Minim is able to play wav files, au files, aif files,
 * snd files, and mp3 files. When you call <code>loadFile</code>, if you just
 * specify the filename it will try to load the file from the data folder of
 * your sketch. However, you can also specify an absolute path
 * (such as "C:\foo\bar\thing.wav") and the file will be loaded from that
 * location (keep in mind that won't work from an applet). You can also specify
 * a URL (such as "http://www.mysite.com/mp3/song.mp3") but keep in mind that
 * if you run the sketch as an applet you may run in to security restrictions
 * if the applet is not on the same domain as the file you want to load. You can
 * get around the restriction by signing the applet. Before you exit your sketch
 * make sure you call the <code>close</code> method of any <code>AudioPlayer</code>'s
 * you have received from <code>loadFile</code>, followed by the <code>stop</code>
 * method of <code>Minim</code>.
 */

 // Drawing Text taken from Daniel Shiffman @ http://www.learningprocessing.com
 // Music - I do not own the music. Please don't sue me!

import ddf.minim.*;

AudioPlayer player;
Minim minim;

PFont f; // drawing text step 2 declare pfont variable

void setup()
{
  size(512, 200, P2D);

  f = loadFont("Courier-Bold-16.vlw"); // drawing text step 3 load font

  minim = new Minim(this);
 
  // load a file, give the AudioPlayer buffers that are 2048 samples long
  player = minim.loadFile("stde.mp3", 2048);
  // "play" the file once, "loop" the file forever!
  player.loop();
}

void draw()
{
  background(80);
  stroke(255);
  // if mouse is pressed
  if (mousePressed) {
    // drawing text
    textFont(f,24);
    fill(255);
    text("PSYCH! It never ends!", 105, 100);
  } else {
    textFont(f,10); // drawing text step 4 specify font to be used
    fill(255); // drawing text step 5 specify font color
    text("Click anywhere to end the song", 165, 100); // drawing text step 6 display Text

  }
  // draw the waveforms
  // the values returned by left.get() and right.get() will be between -1 and 1,
  // so we need to scale them up to see the waveform
  // note that if the file is MONO, left.get() and right.get() will return the same value
  for(int i = 0; i < player.left.size()-1; i++)
  {
    line(i, 50 + player.left.get(i)*50, i+1, 50 + player.left.get(i+1)*50);
    line(i, 150 + player.right.get(i)*50, i+1, 150 + player.right.get(i+1)*50);
  }
}

void stop()
{
  // always close Minim audio classes when you are done with them
  player.close();
  minim.stop();
 
  super.stop();
}

Carly's Processing

These are in four different tabs so where the break is where a new tab would be!

/**
 * Composite Objects
 * 
 * An object can include several other objects. Creating such composite objects 
 * is a good way to use the principles of modularity and build higher levels of 
 * abstraction within a program.
 */

EggRing er1, er2;

void setup() {
  size(200, 200);
  smooth();
  er1 = new EggRing(66, 132, 0.1, 66);
  er2 = new EggRing(132, 180, 0.05, 132);
}


void draw() {
  background(37, 91, 115);
  er1.transmit();
  er2.transmit();
}




class Egg {
  float x, y; // X-coordinate, y-coordinate
  float tilt; // Left and right angle offset
  float angle; // Used to define the tilt
  float scalar; // Height of the egg
  // Constructor
  Egg(int xpos, int ypos, float t, float s) {
    x = xpos;
    y = ypos;
    tilt = t;
    scalar = s / 80.0;

   } 
   
  void wobble() {
    tilt = cos(angle) /10;
    angle += 0.2;
  }

  void display() {
    noStroke();
    if (mousePressed == true) {
      fill (75, 184, 232);
    } else {
       fill(24, 249, 249);

    }
    pushMatrix();
    translate(x, y);
    rotate(tilt);
    scale(scalar);
    beginShape();
    vertex(0, -100);
    bezierVertex(25, -100, 40, -65, 40, -40);
    bezierVertex(40, -15, 25, 0, 0, 0);
    bezierVertex(-25, 0, -40, -15, -40, -40);
    bezierVertex(-40, -65, -25, -100, 0, -100);
    endShape();
    popMatrix();
  }
 
}





class EggRing {
  Egg ovoid;
  Ring circle = new Ring();

  EggRing(int x, int y, float t, float sp) {
    ovoid = new Egg(x, y, t, sp);
    circle.start(x, y - sp/2);
  }

  void transmit() {
    ovoid.wobble();
    ovoid.display();
    circle.grow();
    circle.display();
    if (circle.on == false) {
      circle.on = true;
    }
  }
}





class Ring {
  float x, y; // X-coordinate, y-coordinate
  float diameter; // Diameter of the ring
  boolean on = false; // Turns the display on and off
  void start(float xpos, float ypos) {
    x = xpos;
    y = ypos;
    on = true;
    diameter = 1;
  }
  void grow() {
    if (on == true) {
      diameter += 0.75;
      if (diameter > width*2) {
        diameter = 0.0;
      }
    }
  }
  void display() {
    if (on == true) {
      noFill();
      if (mousePressed == true) {
        strokeWeight (12);
      } else {
        strokeWeight (4);
      }
      stroke(255, 255, 255);
      ellipse(x, y, diameter, diameter);
    }
  }
}





Erin + Charissa Programming experiments

These are the two programs I'm hoping are able to be loaded onto the blog!

Here is the Puzzle, and here is the Hand!

Puzzle takes the basic program of Sprite and is modified through images I developed myself. The idea of a .gif image following the movement of the mouse is the same, the images are the only things that change.

Hand is a program named Transparency. This is probably where I played around with programming most, and manipulated the original program more extensively than Puzzle. My current objective is to figure out how to achieve the transparency effect (gradient changes in the background) but with two different objects. My first attempt was with a lightbulb and a hand controlling the gradients, but I had to settle with working only with one image in the end.

Assignment 1: Robin's Processing


For my Processing assignment, I chose to modify objects that follow path of the mouse cursor in a
fun and animated way. More specifically, a face with eyes will follow your cursor around the board as if it were looking and following it. If you click the movement will be faster.

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

float x = 400;
float y = 300;
float bx = 400;
float by = 300;
float cx = 400;
float cy = 300;
float d = 300;
float easing = 0.02;
float easingb = 0.02;
float easingc = 0.02;

void draw() {
 
  if (mousePressed && (mouseButton == LEFT)) {
  easing = 0.01;
  easingb = 0.007;
  easingc = 0.004;
  } else {
  easing = 0.002;
  easingb = 0.0007;
  easingc = 0.0004;
  }
 
  float targetX = mouseX;
  float targetY = mouseY;
 
  if (mousePressed && (mouseButton == RIGHT)) {
  targetX = 400;
  targetY = 300;
  }
 
  x += (targetX - x) * easing;
  bx += (targetX - bx) * easingb;
  cx += (targetX - cx) * easingc;
  y += (targetY - y) * easing;
  by += (targetY - by) * easingb;
  cy += (targetY - cy) * easingc;
 
  println(mouseX);
  println(mouseY);
  background(100);
 
  //face
  noStroke();
  fill(200);
  ellipse(x, y, 200, 200);
  fill(240);
  ellipse(x-50, y-20, 68, 68);
  ellipse(x+50, y-20, 68, 68);
 
  //eyes
  float eyex = map(mouseX, 0, 800, 0, 60);
  float eyey = map(mouseY, 0, 800, 0, 60);
  fill(200);
  noStroke();
  if (mousePressed && (mouseButton == RIGHT)) {
  ellipse(x-50, y-20, 20, 40);
  ellipse(x+50, y-20, 20, 40);
  } else {
  ellipse(eyex+x-80, eyey+y-40, 40, 40);
  ellipse(eyex+x+20, eyey+y-40, 40, 40);
  }
  /*fill(60,120,240);
  ellipse(eyex+x-80, eyey+y-40, 10, 30);
  ellipse(eyex+x+20, eyey+y-40, 10, 30);*/
 
  noFill();
  stroke(120);
  strokeWeight(3);
  ellipse(x-50, y-20, 68, 68);
  ellipse(x+50, y-20, 68, 68);
 
  //red dot
  noStroke();
  float dotease = 0.5;
  float dotsize = 30;
  if (mousePressed && (mouseButton == LEFT)) {
  dotsize = 30;
  fill(255,0,0);
  } else if (mousePressed && (mouseButton == RIGHT)) {
  dotsize = 0;
  } else {
  dotsize = 10;
  fill(180,40,40);
  }
  d += (dotsize - d) * dotease;
  ellipse(mouseX, mouseY, d, d);
 
}

Assignment 1: Ryan's Processing Assignment

In this application I chose to modify a program to simulate the flocking behavior. This program traces the path of all the rockets. Clicking on the screen will create a rocket - watch the rockets interact as they get near to each other.


/**
 * Flocking 2
 * by Ryan Sun.
 *
 * An implementation of Craig Reynold's Boids program to simulate
 * the flocking behavior of birds. Each boid steers itself based on
 * rules of avoidance, alignment, and coherence.
 *
 * Click the mouse to add a new boid.
 */

int dots = 1000;
float[] dX = new float[dots];
float[] dY = new float[dots];

float l_0 = 0.0;
float h_0 = 0.0;

float legX = 0.0;
float legY = 0.0;
float thighX = 0.0;
float thighY = 0.0;

float l = 60.0; // Length of the 'leg'
float h = 90.0; // Height of the 'leg'

float nmx, nmy = 0.0;
float mx, my = 0.0;

int currentValue = 0;
int valdir = 1;

Flock flock;

void setup()

{
  size(640, 360);
  noStroke();
  flock = new Flock();
  // Add an initial set of boids into the system
  for (int i = 0; i < 0; i++) {
    flock.addBoid(new Boid(new PVector(width/2,height/2), 3.0, 0.05));
  }
  smooth();
  background(20,40,80);
}

void draw()

{
  flock.run();
}

// Add a new boid into the System
void mousePressed() {
  flock.addBoid(new Boid(new PVector(mouseX,mouseY),2.0f,0.05f));
}

// The Boid class

class Boid {

  PVector loc;
  PVector vel;
  PVector acc;
  float r;
  float maxforce;    // Maximum steering force
  float maxspeed;    // Maximum speed

    Boid(PVector l, float ms, float mf) {
    acc = new PVector(0,0);
    vel = new PVector(random(-1,1),random(-1,1));
    loc = l.get();
    r = 2.0;
    maxspeed = ms;
    maxforce = mf;
  }

  void run(ArrayList boids) {
    flock(boids);
    update();
    borders();
    render();
  }

  // We accumulate a new acceleration each time based on three rules
  void flock(ArrayList boids) {
    PVector sep = separate(boids);   // Separation
    PVector ali = align(boids);      // Alignment
    PVector coh = cohesion(boids);   // Cohesion
    // Arbitrarily weight these forces
    sep.mult(1.5);
    ali.mult(1.0);
    coh.mult(1.0);
    // Add the force vectors to acceleration
    acc.add(sep);
    acc.add(ali);
    acc.add(coh);
  }

  // Method to update location
  void update() {
    // Update velocity
    vel.add(acc);
    // Limit speed
    vel.limit(maxspeed);
    loc.add(vel);
    // Reset accelertion to 0 each cycle
    acc.mult(0);
  }

  void seek(PVector target) {
    acc.add(steer(target,false));
  }

  void arrive(PVector target) {
    acc.add(steer(target,true));
  }

  // A method that calculates a steering vector towards a target
  // Takes a second argument, if true, it slows down as it approaches the target
  PVector steer(PVector target, boolean slowdown) {
    PVector steer;  // The steering vector
    PVector desired = target.sub(target,loc);  // A vector pointing from the location to the target
    float d = desired.mag(); // Distance from the target is the magnitude of the vector
    // If the distance is greater than 0, calc steering (otherwise return zero vector)
    if (d > 0) {
      // Normalize desired
      desired.normalize();
      // Two options for desired vector magnitude (1 -- based on distance, 2 -- maxspeed)
      if ((slowdown) && (d < 100.0)) desired.mult(maxspeed*(d/100.0)); // This damping is somewhat arbitrary
      else desired.mult(maxspeed);
      // Steering = Desired minus Velocity
      steer = target.sub(desired,vel);
      steer.limit(maxforce);  // Limit to maximum steering force
    }
    else {
      steer = new PVector(0,0);
    }
    return steer;
  }

  void render() {
    // Draw a triangle rotated in the direction of velocity
    float theta = vel.heading2D() + PI/2;
    fill(200,1,1);
    stroke(255);
    pushMatrix();
    translate(loc.x,loc.y);
    rotate(theta);
    beginShape(TRIANGLES);
    vertex(0, -r*5);
    vertex(-r, r*2);
    vertex(r, r*2);
    endShape();
    popMatrix();
  }
 
  // Wraparound
  void borders() {
    if (loc.x < -r) loc.x = width+r;
    if (loc.y < -r) loc.y = height+r;
    if (loc.x > width+r) loc.x = -r;
    if (loc.y > height+r) loc.y = -r;
  }


  // Separation
  // Method checks for nearby boids and steers away
  PVector separate (ArrayList boids) {
    float desiredseparation = 20.0;
    PVector steer = new PVector(0,0,0);
    int count = 0;
    // For every boid in the system, check if it's too close
    for (int i = 0 ; i < boids.size(); i++) {
      Boid other = (Boid) boids.get(i);
      float d = PVector.dist(loc,other.loc);
      // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
      if ((d > 0) && (d < desiredseparation)) {
        // Calculate vector pointing away from neighbor
        PVector diff = PVector.sub(loc,other.loc);
        diff.normalize();
        diff.div(d);        // Weight by distance
        steer.add(diff);
        count++;            // Keep track of how many
      }
    }
    // Average -- divide by how many
    if (count > 0) {
      steer.div((float)count);
    }

    // As long as the vector is greater than 0
    if (steer.mag() > 0) {
      // Implement Reynolds: Steering = Desired - Velocity
      steer.normalize();
      steer.mult(maxspeed);
      steer.sub(vel);
      steer.limit(maxforce);
    }
    return steer;
  }

  // Alignment
  // For every nearby boid in the system, calculate the average velocity
  PVector align (ArrayList boids) {
    float neighbordist = 25.0;
    PVector steer = new PVector(0,0,0);
    int count = 0;
    for (int i = 0 ; i < boids.size(); i++) {
      Boid other = (Boid) boids.get(i);
      float d = PVector.dist(loc,other.loc);
      if ((d > 0) && (d < neighbordist)) {
        steer.add(other.vel);
        count++;
      }
    }
    if (count > 0) {
      steer.div((float)count);
    }

    // As long as the vector is greater than 0
    if (steer.mag() > 0) {
      // Implement Reynolds: Steering = Desired - Velocity
      steer.normalize();
      steer.mult(maxspeed);
      steer.sub(vel);
      steer.limit(maxforce);
    }
    return steer;
  }

  // Cohesion
  // For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location
  PVector cohesion (ArrayList boids) {
    float neighbordist = 25.0;
    PVector sum = new PVector(0,0);   // Start with empty vector to accumulate all locations
    int count = 0;
    for (int i = 0 ; i < boids.size(); i++) {
      Boid other = (Boid) boids.get(i);
      float d = loc.dist(other.loc);
      if ((d > 0) && (d < neighbordist)) {
        sum.add(other.loc); // Add location
        count++;
      }
    }
    if (count > 0) {
      sum.div((float)count);
      return steer(sum,false);  // Steer towards the location
    }
    return sum;
  }
}

// The Flock (a list of Boid objects)

class Flock {
  ArrayList boids; // An arraylist for all the boids

  Flock() {
    boids = new ArrayList(); // Initialize the arraylist
  }

  void run() {
    for (int i = 0; i < boids.size(); i++) {
      Boid b = (Boid) boids.get(i);
      b.run(boids);  // Passing the entire list of boids to each boid individually
    }
  }

  void addBoid(Boid b) {
    boids.add(b);
  }

}