Rush Hour
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
End Position
Code: GitHub
/* Spencer Barton * Interactive Art & Computational Design, Spring 2014 * 1.1 Lenticular Animation * * Boxes * Starter code from https://ems.andrew.cmu.edu/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; } } |