nannon-Body

Face Face Revolution 

Vimeo

(sadly the "levels" label disappears!!)

 
 
 

-----
GIF

 
 
 

----
Still

 
 
 
 

Though I was super impressed/awed by all the examples shown in class of digital interactive artworks, I personally had a hard time coming up with an idea for this project. My DDR concept still seems a bit boring to me, but I'm glad I got it to work in a reasonable amount of time (relative to how stressed I was about previous assignmentS). The game itself is mildly fun, if a little hard. In coming up with this concept, I wanted to make sure I wasn't scaling out of proportion, so I looked at the templates carefully first before trying to figure out what to do, which really helped me scope down my project. Moving forwards, if this project were to be improved, I think it'd be really fun to try to get people to contort their faces to match what comes up in the grid--though I can imagine that being 1) really hard to play and 2) needing to randomize the grid in a really careful way i.e. the mouth is never above the eyes.

 
 
 
 

//
// a template for receiving face tracking osc messages from
// Kyle McDonald's FaceOSC https://github.com/kylemcdonald/ofxFaceTracker
//
// 2012 Dan Wilcox danomatika.com
// for the IACD Spring 2012 class at the CMU School of Art
//
// adapted from from Greg Borenstein's 2011 example
// http://www.gregborenstein.com/
// https://gist.github.com/1603230
//
import oscP5.*;
OscP5 oscP5;
 
 
PFont intersect50;
PFont intersect25;
 
 
//game bools
boolean pressplay =false;
boolean gameOver = false;
 
int level;
 
// num faces found
int found;
 
// pose
float poseScale;
PVector posePosition = new PVector();
PVector poseOrientation = new PVector();
 
 
 
 
 
// gesture
float mouthHeight;
float mouthWidth;
float eyeLeft;
float eyeRight;
float eyebrowLeft;
float eyebrowRight;
float jaw;
float nostrils;
 
 
//mouth, left eye, right eye, nose
String[] parts = {"mouth", "left eye", "right eye","nose"};
int partsActive; 
 
// grid variables
int[][] grid = new int[10][10];
 
int gridNum = 2;
 
int gridSize = 700;
int margin = 100;
 
int sqSize;
int randX;
int randY;
int points;
//timer
 
int time;
int wait = 8000;
float countdown;
 
 
void setup() {
  // Uncomment the following two lines to see the available fonts 
  //String[] fontList = PFont.list();
  //printArray(fontList);
  //String[] fontList = PFont.list();
  //for (int i =300;i<700; i++) { // println(fontList[i]); //} intersect50 = createFont("IntersectB44Solid", 120); intersect25 = createFont("IntersectB24", 30); translate(0,0); size(700,700); frameRate(30); oscP5 = new OscP5(this, 8338); oscP5.plug(this, "found", "/found"); oscP5.plug(this, "poseScale", "/pose/scale"); oscP5.plug(this, "posePosition", "/pose/position"); oscP5.plug(this, "poseOrientation", "/pose/orientation"); oscP5.plug(this, "mouthWidthReceived", "/gesture/mouth/width"); oscP5.plug(this, "mouthHeightReceived", "/gesture/mouth/height"); oscP5.plug(this, "eyeLeftReceived", "/gesture/eye/left"); oscP5.plug(this, "eyeRightReceived", "/gesture/eye/right"); oscP5.plug(this, "eyebrowLeftReceived", "/gesture/eyebrow/left"); oscP5.plug(this, "eyebrowRightReceived", "/gesture/eyebrow/right"); oscP5.plug(this, "jawReceived", "/gesture/jaw"); oscP5.plug(this, "nostrilsReceived", "/gesture/nostrils"); points = 0; getNewRand(); //timer time = millis();//store the current time println("time", time); //game level =1; partsActive = int(random(4)); } void draw() { if (!pressplay && !gameOver) { gameStart(); } else if (pressplay && !gameOver){ game(); } else if (pressplay && gameOver) { gameend(); } } void gameStart(){ background(1, 34, 160); textAlign(CENTER, CENTER); textFont(intersect50); fill(133,242,231); text("face", width/2-3,height/2-100); text("face", width/2-3, height/2); fill(0,222,190); text("face", width/2, height/2-100+3); text("face", width/2, height/2+3); textFont(intersect25); int passedMillis = millis() - time; // calculates passed milliseconds if(passedMillis >= 300){
      time = millis();
      fill(1, 34, 160);  // if more than 215 milliseconds passed set fill color to red
  }
  else {
    fill (0,222,190);
  }
   text("free play", width/2, 490);
   if (keyPressed) {
     if (key=='p' || key=='P') {
       pressplay = true;
     }
   }
}
 
void gameend() {
  background(1, 34, 160);
   textAlign(CENTER, CENTER);
   textFont(intersect50);
   fill(133,242,231);
   text("game", width/2-3,height/2-100);
   text("over", width/2-3, height/2);
   fill(0,222,190);
   text("game", width/2, height/2-100+3);
   text("over", width/2, height/2+3);
   textFont(intersect25);
   int passedMillis = millis() - time; // calculates passed milliseconds
  if(passedMillis >= 300){
      time = millis();
      fill(1, 34, 160);  // if more than 215 milliseconds passed set fill color to red
  }
  else {
    fill (0,222,190);
  }
   text("good bye", width/2, 490);
   if (keyPressed) {
     if (key=='s' || key=='S') {
       gameOver =false;
       pressplay = false;
       //level =0;
       //points =0;
       setup();
     }
   }
 
}
 
void game() {
 
if (points<40) {
   level =1;
 }
 
 else if (points<70) {
   level =2;
 }
 
 else if (points<100) {
   level =3;
 }
 
   else if (points<130) {
   level =4;
 }
 
 else {
 level =5;
 }
 
  pushMatrix();
  background(0);
   translate(sqSize/2,sqSize/2);
 
 
  fill(0);
 
  gridNum=level+1;
  sqSize = (gridSize-margin*2)/gridNum;
  //500/3
  //
  println(sqSize);
 
  for (int i=0; i<gridNum; i++) {
        for (int j=0; j<gridNum; j++) { //size/ grid size stroke(133,242,231); //noFill();222 //println(i, j, sqSize, sqSize*j+margin); rect(sqSize*j+margin, sqSize*i+margin, sqSize, sqSize); } } textFont(intersect25); fill (0,222,190); textAlign(LEFT); text("level "+str(level), -50,-50); fill(133,242,231); rect(sqSize*randX+margin, sqSize*randY+margin, sqSize, sqSize); fill(0); rect(sqSize*randX+margin, sqSize*randY+margin, sqSize-20, sqSize-20); fill(133,242,231); rect(sqSize*randX+margin, sqSize*randY+margin, sqSize-40, sqSize-40); //rect(300,300,40,40); popMatrix(); pushMatrix(); textFont(intersect25,40); textAlign(CENTER,CENTER); fill(0); text(parts[partsActive], sqSize*randX+margin+sqSize/2, sqSize*randY+margin+sqSize/2); popMatrix(); //write points count fill(133,242,231); textSize(60); //println(points); text(str(points), 350, 630); //timer if(millis() - time >= wait){
      gameOver = true;
      //also update the stored time
 
    }
    else {
      countdown = (millis()-time);
 
      //println("wait", wait);
      //println("test", millis()-time);
 
      countdown = countdown/wait;
      //println("countdown", countdown);
    }
    //println((3*PI)/2, ((3*PI)/2)*countdown);
    pushMatrix();
    noFill();
    stroke(133,242,231);
    strokeWeight(7);
    arc(600, 70, 30,30, 3*(PI/2)*countdown, 3*(PI/2), OPEN);
    popMatrix();
 
    strokeWeight(1);
 
  //translate(width,0);
  //  scale(-1,1);
  //facial data
  if(found > 0) {
 
    pushMatrix();
 
    translate(posePosition.x, posePosition.y);
    scale(poseScale);
    noFill();
    ellipse(-20, eyeLeft * -9, 7, 7);
    ellipse(20, eyeRight * -9, 7, 7);
    ellipse(0, 20, 7, 7);
    ellipse(0, nostrils * -1, 7, 7);
    rectMode(CENTER);
    fill(0);
    rect(-20, eyebrowLeft * -5, 25, 5);
    rect(20, eyebrowRight * -5, 25, 5);
    popMatrix();
 
 
    //gamify your LEFT eye
    float realMouthX = (posePosition.x);
    float realMouthY = posePosition.y+((eyeLeft*7)*poseScale);
 
 
    //gamify your LEFT eye
    float realLeftEyeX = (posePosition.x-(20*poseScale));
    float realLeftEyeY = posePosition.y+((eyeLeft*-9)*poseScale);
 
     //gamify your RIGHT eye
    float realRightEyeX = (posePosition.x+(20*poseScale));
    float realRightEyeY = posePosition.y+((eyeLeft*-9)*poseScale);
 
     //gamify your NOOOSE
    float realNoseX = (posePosition.x);
    float realNoseY = posePosition.y+((eyeLeft*-1)*poseScale);
 
 
    //translate(125,125);
    stroke(255,0,0);
 
 
    //MOUTH POINTS
     if (partsActive==0) {
      ellipse(realMouthX, realMouthY, 20,20);
        if (realMouthX >= sqSize*randX+margin && realMouthX <= sqSize*randX+sqSize+margin && realMouthY>= sqSize*randY+margin && realMouthY<= sqSize*randY+sqSize+margin) { //println("hello"); points+=10; getNewRand(); } } //LEFT EYE POINTS if (partsActive==1) { ellipse(realLeftEyeX, realLeftEyeY, 20,20); if (realLeftEyeX >= sqSize*randX+margin && realLeftEyeX <= sqSize*randX+sqSize+margin && realLeftEyeY>= sqSize*randY+margin && realLeftEyeY<= sqSize*randY+sqSize+margin) { //println("hello"); points+=10; getNewRand(); } } //RIGHT EYE POINTS if (partsActive==2) { ellipse(realRightEyeX, realRightEyeY, 20,20); if (realRightEyeX >= sqSize*randX+margin && realRightEyeX <= sqSize*randX+sqSize+margin && realRightEyeY>= sqSize*randY+margin && realRightEyeY<= sqSize*randY+sqSize+margin) { //println("hello"); points+=10; getNewRand(); } } if (partsActive==3) { ellipse(realNoseX, realNoseY, 20,20); if (realNoseX >= sqSize*randX+margin && realNoseX <= sqSize*randX+sqSize+margin && realNoseY>= sqSize*randY+margin && realNoseY<= sqSize*randY+sqSize+margin) {
        //println("hello");
        points+=10;
        getNewRand();
      }  
    }
 
  }
}
 
 
 
void getNewRand() {
  randX = int(random(0,gridNum));
  randY = int(random(0,gridNum));
  partsActive = int(random(4));
  time = millis();
}
 
void mouseClicked() {
  randX = int(random(0,gridNum));
  randY = int(random(0,gridNum));
  partsActive = int(random(4));
  time = millis();
}
 
// OSC CALLBACK FUNCTIONS
 
public void found(int i) {
  //println("found: " + i);
  found = i;
}
 
public void poseScale(float s) {
  //println("scale: " + s);
  poseScale = s;
}
 
public void posePosition(float x, float y) {
  //println("pose position\tX: " + x + " Y: " + y );
  posePosition.set(x, y, 0);
}
 
public void poseOrientation(float x, float y, float z) {
  //println("pose orientation\tX: " + x + " Y: " + y + " Z: " + z);
  poseOrientation.set(x, y, z);
}
 
public void mouthWidthReceived(float w) {
  //println("mouth Width: " + w);
  mouthWidth = w;
}
 
public void mouthHeightReceived(float h) {
  //println("mouth height: " + h);
  mouthHeight = h;
}
 
public void eyeLeftReceived(float f) {
  //println("eye left: " + f);
  eyeLeft = f;
}
 
public void eyeRightReceived(float f) {
  //println("eye right: " + f);
  eyeRight = f;
}
 
public void eyebrowLeftReceived(float f) {
  //println("eyebrow left: " + f);
  eyebrowLeft = f;
}
 
public void eyebrowRightReceived(float f) {
  //println("eyebrow right: " + f);
  eyebrowRight = f;
}
 
public void jawReceived(float f) {
  //println("jaw: " + f);
  jaw = f;
}
 
public void nostrilsReceived(float f) {
  //println("nostrils: " + f);
  nostrils = f;
}
 
// all other OSC messages end up here
void oscEvent(OscMessage m) {
  if(m.isPlugged() == false) {
    println("UNPLUGGED: " + m);
  }
}