Eliza Pratt – Project 11

click to redraw!

/*
Eliza Pratt
Section E
elpratt@andrew.cmu.edu
Project 11
*/

var face = 5; //face size
var faceY = 100; //starting y coordinate for face
var w = 2; //stroke weight
var eye = {LX: 0, LY: 0, RX: 0, RY: 0}; // eye coordinates
var lipX; // lip x position
var lipY; //lip y position

function setup() {
    createCanvas(480, 360);
    frameRate(10);
}

function draw() {
    background("beige");

    for (var i = 0; i < 3; i++) {
      var turt = makeTurtle(90 + i * 150, faceY);
      turt.penDown();
      turt.setColor("black");

      //draw face features
      faceBrowsNose(turt);
      eyes(turt);
      glasses(turt);
      lips(turt);
    }

    noLoop();

}

//redraw face when the mouse is pressed
function mousePressed() {
  draw();
}


//draws face, eyebrows and nose
function faceBrowsNose(ttl) {
  //FACE
  for (var i = 0; i < 180; i++) {
    turtlepressure(ttl);
    ttl.right(360 / 100 + random(-2.5, 2.5));
    ttl.forward(face + random(-face / 3, face / 3));
  }
  ttl.left(20);

  //LEFT EYEBROW
  for (var i = 0; i < 50; i++) {
    turtlepressure(ttl);
    ttl.right(360 / 100);
    ttl.forward(2 + random(-2, 2));
    //save coordinates at top of brow to assign eye position
    if (i == 25) {
      eye.LX = ttl.x;
      eye.LY = ttl.y + random(10, 25);
    }
  }
  //LEFT NOSE
  for (var i = 0; i < 10; i++) {
    turtlepressure(ttl);
    ttl.right(random(-0.5, .5));
    ttl.forward(1);
  }
  //BOTTOM NOSE
  for (var i = 0; i < 50; i++) {
    turtlepressure(ttl);
    ttl.left(360 / 100);
    ttl.forward(0.5 + random(-1, 1));
    //save bottom of nose coordinates for lip position
    if (i == 25) 
      lipY = ttl.y + random (20, 30);
      lipX = ttl.x + random (-30, 10);
  }
  //RIGHT NOSE
  for (var i = 0; i < 10; i++) {
    turtlepressure(ttl);
    ttl.right(random(-0.5, .5));
    ttl.forward(1);
  }
  //RIGHT EYEBROW
  for (var i = 0; i < 50; i++) {
    turtlepressure(ttl);
    ttl.right(360 / 100);
    ttl.forward(2 + random(-2, 2));
    if (i == 25) {
      eye.RX = ttl.x;
      eye.RY = ttl.y  + random(10, 25);
    }
  }
}


//draws eyes
function eyes(ttl) {
    ttl.penUp();
    ttl.goto(eye.LX, eye.LY);
    ttl.penDown();

    //left eye
    for (var i = 0; i < 100; i++) {
      turtlepressure(ttl);
      ttl.right(360 / 50);
      ttl.forward(.5 + random(-0.75, 0.75));
    }

    ttl.penUp();
    ttl.goto(eye.RX, eye.RY);
    ttl.penDown();

    //right eye
    for (var i = 0; i < 100; i++) {
      turtlepressure(ttl);
      ttl.right(360 / 50);
      ttl.forward(.5 + random(-0.75, 0.75));
    }
}


//draws glasses
function glasses(ttl) {
  ttl.penUp();
  ttl.goto(eye.LX + random(10, 18), eye.LY);
  ttl.penDown();

  //lens 1
  ttl.face(90);
  for (var i = 0; i < 100; i++) {
    turtlepressure(ttl);
    ttl.right(360 / 50 + random(-4, 4));
    ttl.forward(2 + random(-0.75, 0.75));
  }

  ttl.penUp();
  ttl.goto(eye.RX - random(10, 18), eye.RY);
  ttl.face(330);
  ttl.penDown();

  //lens 2
  ttl.face(270);
  for (var i = 0; i < 100; i++) {
    turtlepressure(ttl);
    ttl.right(360 / 50 + random(-4, 4));
    ttl.forward(2 + random(-0.75, 0.75));
  }
}


//draws lips
function lips(ttl) {

  ttl.penUp();
  ttl.goto(lipX, lipY);
  ttl.penDown();
  ttl.face(310);

  //TOP LEFT
  for (var i = 0; i < 20; i++) {
    turtlepressure(ttl);
    ttl.right(360 / 100);
    ttl.forward(1 + random(-1, 1));
  }
  ttl.left(50);

  //TOP RIGHT
  for (var i = 0; i < 20; i++) {
    turtlepressure(ttl);
    ttl.right(360 / 100);
    ttl.forward(1 + random(-1, 1));
  }
  ttl.face(180);

  //LINE
  for (var i = 0; i < 30; i++) {
    turtlepressure(ttl);
    ttl.forward(1);
    ttl.right(random(-2, 2));
  }
  ttl.face(90);

  //BOTTOM LIP
  for (var i = 0; i < 50; i++) {
    turtlepressure(ttl);
    ttl.left(360 / 100);
    ttl.forward(1 + random(-1, 1));
  } 
}


//varies stroke weight to create "hand drawn" effect
function turtlepressure(turtle) {
  w += random(-0.4, 0.4);
  if (w <=0) w = 0.4;
  else if (w>= 3) w = 2.7;
  turtle.setWeight(w);

} 

/////////////////////////////////////////////////////////////////
function turtleLeft(d) {
    this.angle -= d;
}


function turtleRight(d) {
    this.angle += d;
}


function turtleForward(p) {
    var rad = radians(this.angle);
    var newx = this.x + cos(rad) * p;
    var newy = this.y + sin(rad) * p;
    this.goto(newx, newy);
}


function turtleBack(p) {
    this.forward(-p);
}


function turtlePenDown() {
    this.penIsDown = true;
}


function turtlePenUp() {
    this.penIsDown = false;
}


function turtleGoTo(x, y) {
    if (this.penIsDown) {
      stroke(this.color);
      strokeWeight(this.weight);
      line(this.x, this.y, x, y);
    }
    this.x = x;
    this.y = y;
}


function turtleDistTo(x, y) {
    return sqrt(sq(this.x - x) + sq(this.y - y));
}


function turtleAngleTo(x, y) {
    var absAngle = degrees(atan2(y - this.y, x - this.x));
    var angle = ((absAngle - this.angle) + 360) % 360.0;
    return angle;
}


function turtleTurnToward(x, y, d) {
    var angle = this.angleTo(x, y);
    if (angle < 180) {
        this.angle += d;
    } else {
        this.angle -= d;
    }
}


function turtleSetColor(c) {
    this.color = c;
}


function turtleSetWeight(w) {
    this.weight = w;
}


function turtleFace(angle) {
    this.angle = angle;
}


function makeTurtle(tx, ty) {
    var turtle = {x: tx, y: ty,
                  angle: 0.0, 
                  penIsDown: true,
                  color: color(128),
                  weight: 1,
                  left: turtleLeft, right: turtleRight,
                  forward: turtleForward, back: turtleBack,
                  penDown: turtlePenDown, penUp: turtlePenUp,
                  goto: turtleGoTo, angleto: turtleAngleTo,
                  turnToward: turtleTurnToward,
                  distanceTo: turtleDistTo, angleTo: turtleAngleTo,
                  setColor: turtleSetColor, setWeight: turtleSetWeight,
                  face: turtleFace};
    return turtle;
}

Ever since our second variable face assignment where we saw examples of Moka’s generative faces, I’ve wanted to code doodles that look blind contours! I had a lot of fun playing with the turtles and got some pretty great results from randomizing different things. Also, by randomizing the stroke weight for each point I was able to make my own “brush” of sorts. It was challenging to have any control over the randomness factor, but here are some of the beautiful creations that came out of it before I decided to do multiple faces:

friend with hair
derp
sleepy friend
abstract friend

Leave a Reply