Spencer Barton

20 Jan 2014

Rush Hour

sebarton_blog

This design was inspired by the game Rush Hour which I recently played. In that game cars move back and forth until the exit is reached but continually block each other along the way.

I spent a lot of time attempting various fractal designs in a desire to create something complex. The rush hour idea pulled me away from my inclination towards mathematical complexity by keeping the structure simple. I believe the simpler form made a more interesting final piece.

Simplicity is also a downside to this piece. In particular I would like more emphasis on the collisions. This may be corrected by infusing color. This is also a two dimensional piece and it lacks an ability to pull the viewers focus in since the overall scrolling is towards the upper right. I find my eyes leave the picture fairly quickly.

Basic Movement and Starting Position

2014-01-20 14.11.41

End Position

2014-01-20 14.11.48

Code: GitHub

/* Spencer Barton
 * Interactive Art & Computational Design, Spring 2014
 * 1.1 Lenticular Animation
 * 
 * Boxes
 * Starter code from http://golancourses.net/2014/assignments/project-1/lenticular-animation/
 *
 * Ideas
 * - Slow down collisions
 * - Collision color changes
 */
 
/*===================================================
  Global variables & constants
  =================================================== */
 
int FRAME_SIZE = 500; 
int NUM_FRAMES_IN_LOOP = 50; // for lenticular export, change this to 10!
color STROKE_CLR = 255;
int STROKE_WEIGHT = 0;
String IMG_NAME = "sebarton-blog";
float GRID_LENGTH = 30;
float BOX_WIDTH = GRID_LENGTH;
float BOX_HEIGHT = 2*GRID_LENGTH;
int NUM_BOX_TYPES = 4;
 
int nElapsedFrames;
boolean bRecording; 
Box[] boxes;
 
/*===================================================
  Setup
  =================================================== */
 
void setup() {
  size (FRAME_SIZE, FRAME_SIZE); 
  bRecording = false;
  nElapsedFrames = 0;
  frameRate (NUM_FRAMES_IN_LOOP);
 
  generateBoxes();
}
 
void generateBoxes() {
 
  int nBoxesSide = (int)round(FRAME_SIZE / BOX_HEIGHT);
  nBoxesSide = nBoxesSide + nBoxesSide % 2 + 2; // round up to nearest power of 2 and add 2 for good measure
  int nOneTypeBoxPerSide = nBoxesSide / 2;
 
  boxes = new Box[nBoxesSide * nBoxesSide];
 
  // generate individual boxes
  float startX, startY, endX, endY, boxHoriz, boxVert, difference;
  int index = 0;
  for( int t = 0; t < NUM_BOX_TYPES; t++ ) {
    for( int i = 0; i < nOneTypeBoxPerSide; i++) {
      for( int j = 0; j < nOneTypeBoxPerSide; j++) {
 
        startX = j*2*BOX_HEIGHT;
        startY = i*2*BOX_HEIGHT;
        endX = startX;
        endY = startY;
        difference = BOX_HEIGHT - BOX_WIDTH;
        boxHoriz = BOX_HEIGHT;
        boxVert = BOX_WIDTH;
        color clr = color(255,255,255);
 
        switch (t) {
          case(0):
            // horiz, left
            endX = startX - difference;
            break;
          case(1): 
            // horiz, right 
            startX += BOX_WIDTH;
            startY += BOX_HEIGHT;
            endX = startX + difference;
            endY = startY;
            break;
          case(2):
            startX += BOX_HEIGHT;
            endX = startX;
            endY = startY - difference;
            boxHoriz = BOX_WIDTH;
            boxVert = BOX_HEIGHT;
            break;
          case(3):
            startY += BOX_WIDTH;
            endY = startY +  difference;
            boxHoriz = BOX_WIDTH;
            boxVert = BOX_HEIGHT;
            break;
        }
 
        boxes[index] = new Box(startX, startY, endX, endY, boxVert, boxHoriz, clr);
        index++;
 
      }
    }
  }
}
 
/*===================================================
  Keyboard Interupt
  =================================================== */
 
void keyPressed() { 
  // Press a key to export frames to the output folder
  println("Recording");
  bRecording = true;
  nElapsedFrames = 0;
}
 
/*===================================================
  Draw
  =================================================== */
void draw() {
 
  // Compute a percentage (0...1) representing where we are in the loop.
  float percentCompleteFraction = 0; 
 
  if (bRecording) {
    percentCompleteFraction = (float) nElapsedFrames / (float)NUM_FRAMES_IN_LOOP;
  } else {
    float modFrame = (float) (frameCount % NUM_FRAMES_IN_LOOP);
    percentCompleteFraction = modFrame / (float)NUM_FRAMES_IN_LOOP;
  }
 
  // Render the design, based on that percentage. 
  renderMyDesign ( percentCompleteFraction );
 
  // If we're recording the output, save the frame to a file. 
  if (bRecording) {
    saveFrame("output/"+ IMG_NAME + "-loop-" + nf(nElapsedFrames, 4) + ".png");
    nElapsedFrames++; 
    if (nElapsedFrames == NUM_FRAMES_IN_LOOP) {
      bRecording = false;
      println("Done Recording");
    }
  }
}
 
/*===================================================
  Render
  =================================================== */
 
void renderMyDesign (float percent) {
 
  background(0);
  smooth(); 
  stroke (STROKE_CLR); 
  strokeWeight (STROKE_WEIGHT);
 
  float transX = -BOX_HEIGHT * percent;
  float transY = -BOX_HEIGHT * percent;
  translate(transX, transY);
 
  for( Box box : boxes ) {
    box.drawBox(percent);
  }
 
}
/*===================================================
  Box
  =================================================== */
 
class Box {
 
  float startX, startY, endX, endY, boxHeight, boxWidth, cornerRadius;
  color clr;
 
  Box(float startX, float startY, float endX, float endY, float boxHeight, float boxWidth, color clr) {
 
    this.startX = startX;
    this.startY = startY;
    this.endX = endX;
    this.endY = endY;
    this.boxHeight = boxHeight;
    this.boxWidth = boxWidth;
 
    this.clr = clr;
    this.cornerRadius = 2;
  }
 
  void drawBox(float percent) {
    percent  = percentFunction(percent);
    float curX = map(percent, 0, 1, startX, endX);
    float curY = map(percent, 0, 1, startY, endY);
 
    fill(clr);
    rect(curX, curY, boxWidth, boxHeight, cornerRadius);
  }
 
  float percentFunction(float percent) {
    //return sqrt(percent);
    return .5*sin( PI * (percent + .5) ) + .5;
  }
 
}