ashleyc1-Section C-Final Project

RULES:

-Use the mouse (either by pressing or moving around) to interact with animations

-Click any key to cycle through different animations (click within the canvas first if not working because wordpress is weird)

Note: If file is opened through google browser, mouse isn’t limited on first animation and they all generally run smoother

sketch

//Ashley Chan
//Section C
//ashleyc1@andrew.cmu.edu
//Final Project - Type in Motion

/////////////////////////////////////
// MAIN  CONTROL //
///////////////////////////////////

var index = 0;

//global var for images
var revealImg;
var twinkleImg;
var eraseImg;
var sprayHintImage;
var sprayOverlayImage;

function preload() {

//load all the images
revealImg = loadImage("https://i.Imgur.com/giFSIcI.jpg?1");
twinkleImg = loadImage("https://i.imgur.com/hqn6Cv9.jpg?1");
eraseImg = loadImage("https://i.imgur.com/VO4buSz.png");
sprayHintImage = loadImage("https://i.imgur.com/P6LkUET.jpg");
sprayOverlayImage = loadImage("https://i.imgur.com/dr6JWoH.png");

}

function setup() {

    createCanvas(480, 180);
    background(0);

    //index that cycles through animations
    //call each animations' setups 
    //depending on index number
    if(index == 0){
        revealSetup();
    }

    if(index == 1){
        twinkleSetup();
    }

    if(index == 2){
        eraseSetup();
    }

    if(index == 3){
        spraySetup();
    }
}


function draw() {

    //call each animations' draw depending on index number
    if(index == 0) {
        revealDraw();
    }

    if(index == 1){
        twinkleDraw();
    }

    if(index == 2){
        eraseDraw();
    }

    if(index == 3){
        sprayDraw();
    }

}

// Cycles through animations every time 
//any key is pressed
function keyPressed(){

    index = (index + 1)%4;

    setup();

}

////////////////////////////////////////////
// REVEAL  ANIMATION //
///////////////////////////////////////////

//var that will spell out reveal
var revealCircles; 
var revealDots;


function revealSetup(){
    
    //Draw a black rectangle for every animation 
    //because we need to make sure the animations 
    //restart without actually calling setup 
    //and messing everything up
    fill(0);
    rect(0, 0, 480, 180);

    revealCircles = [];
    revealDots = [];

    // iterate through pixels
    image(revealImg, 0, 100);
    revealImg.loadPixels();
    
    for(var i = 0; i < 2 * revealImg.width; i++) {
        for(var j = 0; j < revealImg.height; j++) {

            var revealIndex = i * 2 + (j * revealImg.width)*8;
            
            //locate the dark pixels of underlaying image
            //where there is dark, make a revealCircle
            if (revealImg.pixels[revealIndex] < 200){

                revealDots.push(createVector( i / 2, j * 2));
            }
        }
    }

        var num_circles = 0;
    
    //draw certain number of revealCircles every frame
    while (num_circles < 400){
        
        var c = revealCreateCircle();
    
        if (c) {

            revealCircles.push(c);
            num_circles++;

        }
    }
}


function revealDraw(){

    background(0);
  
    //draw the revealCircles
    for(var i = 0; i < revealCircles.length; i++) {
      
        var x = revealCircles[i].x;
        var y = revealCircles[i].y;
        var r = revealCircles[i].r;

    //calculate distance around mouse
    //any space within radius will be drawn and shown
    var d = dist(x, y, mouseX, mouseY);

    if (d  < 90) {
        //center image
        push();
        scale(.5, .5);
        translate(150, 0);
        revealCircles[i].show();
        pop();

        }
    }
}

//While creating a new revealCircle
//Do not create one inside existing one
function revealCreateCircle(){

    var x;
    var y;
    
    // find a random position to create a revealCircle
    var position = int(random(0, revealDots.length));

    x = revealDots[position].x;
    y = revealDots[position].y;

    var valid = true;

    for (var i = 0; i < revealCircles.length; i++) {

        //Don't draw inside another revealCircle
        // If generated already drawn revealCircle, redo
        if (dist(x, y, revealCircles[i].x, revealCircles[i].y) <= revealCircles[i].r) {

            valid = false;
            break;
        }
    }

    //if no revealCircle drawn at spot, draw one 
    if (valid) {

        return new revealCircle(x, y, width, height);
    }

    return false;
}

//define the circles
function revealCircle(xPos, yPos, gwidth, gheight){

    this.x = xPos;
    this.y = yPos;
    this.r = 8;

    this.width = gwidth;
    this.height = gheight;

    //controls the look of the revealCircles 
    //randomizes color when mouse is pressed
    this.show = function(){

        fill(255);
        noStroke();
        strokeWeight(1);
        ellipse(this.x, this.y, this.r);

        }
}


////////////////////////////////////////////////
//  TWINKLE   ANIMATION //
///////////////////////////////////////////////

//var that will spell out twinkle
var twinkleCircles;
var twinkleDots;


function twinkleSetup(){
    
    fill(0);
    rect(0, 0, 480, 180);

    twinkleCircles = [];
    twinkleDots = [];
    
    // iterate through pixels
    //image(twinkleImg, 0, 100);
    twinkleImg.loadPixels();
    
    //locate the dark pixels of underlaying image
    //where there is dark, make a twinkleCircle
    for(var i = 0; i < 2 * twinkleImg.width; i++) {
        for(var j = 0; j < twinkleImg.height; j++) {

            var twinkleIndex = i * 2 + (j * twinkleImg.width)*8;
            
            if (twinkleImg.pixels[twinkleIndex] < 200){

                twinkleDots.push(createVector( i / 2, j * 2));
            }
        }
    }

    var num_circles = 0;
    
    //draw certain number of twinkleCircles every frame
    while (num_circles < 300){
        
        var c = twinkleCreateCircle();

        if (c) {

            twinkleCircles.push(c);
            num_circles++;

        }

    }
    
    //draw the twinkleCircles
    for(var i = 0; i < twinkleCircles.length; i++) {
      
        var x = twinkleCircles[i].x;
        var y = twinkleCircles[i].y;
        var r = twinkleCircles[i].r;

        //center image
        push();
        scale(.6, .6);
        translate(50, 80);
        twinkleCircles[i].show();
        pop();
        
    }
}


function twinkleDraw(){

    //if mouse pressed, "redraw" circles
    //so that color is randomized
    if(mouseIsPressed) {
        for(var i = 0; i < twinkleCircles.length; i++) {
      
            var x = twinkleCircles[i].x;
            var y = twinkleCircles[i].y;
            var r = twinkleCircles[i].r;

            //center image
            push();
            scale(.6, .6);
            translate(50, 80);
            twinkleCircles[i].show();
            pop();

        }
    }
}

//While creating a new twinkleCircle
//Do not create one inside existing one
function twinkleCreateCircle(){

    var x;
    var y;
    
    // find a random position to create a twinkleCircle
    var position = int(random(0, twinkleDots.length));

    x = twinkleDots[position].x;
    y = twinkleDots[position].y;

    var valid = true;

    for (var i = 0; i < twinkleCircles.length; i++) {

        //Don't draw inside another twinkleCircle
        // If generate already drawn twinkleCircle, redo
        if (dist(x, y, twinkleCircles[i].x, twinkleCircles[i].y) <= twinkleCircles[i].r) {

            valid = false;
            break;
        }
    }

    //if no twinkleCircle drawn at spot, draw one 
    if (valid) {

        return new twinkleCircle(x, y, width, height);
    }

    return false;
}

//define twinkleCircles
function twinkleCircle(xPos, yPos, gwidth, gheight){

    this.x = xPos;
    this.y = yPos;
    this.r = 8;

    this.width = gwidth;
    this.height = gheight;

    //controls the look of the twinkleCircles 
    //randomizes color when mouse is pressed
    this.show = function(){

        stroke(255);
        strokeWeight(1);

        //start out as empty twinkleCircles
        var value = 0;
        fill(value);

        //change the color every time mouse is pressed
        if (mouseIsPressed) {

        value = random(0, 255);

        fill(value, value, value);

        }

        ellipse(this.x, this.y, this.r);

        }
}


////////////////////////////////////////////
// ERASE  ANIMTATION //
///////////////////////////////////////////

//var for erase animation
var eraseLastMinute;
var eraseCurrentMinute;

//eraseIndex for animations
var eraseIndex = 0;


function eraseSetup() {
    //scale(.5, .5);
    
    fill(0);
    rect(0, 0, 480, 180);
    eraseImg.loadPixels();

    eraseLastMinute = minute();
    
    //make for loop to control how many images we are making
    for (i = 0; i < 50; i++) {

        image(eraseImg, random(-50, 800), 
            random(-50, height), 100, 43);

    }
}

function eraseDraw() {

    fill(0);
    noStroke();
    ellipse(mouseX, mouseY, 30, 30);

    //call setup and reset every minute
    eraseCurrentMinute = minute();

    //if a minute has passed, call setup and generate 
    //different arrangement of words
    if (eraseLastMinute != eraseCurrentMinute) {

    eraseSetup();

    }
}

///////////////////////////////////////////
//  SPRAY  ANIMATION //
//////////////////////////////////////////

var sprayDots; 

function spraySetup() {

    fill(0);
    rect(0, 0, 480, 180);
    noCursor();   
    noStroke();   
  
    sprayDots = [];

}

function sprayDraw() {

    image(sprayHintImage, 50, 100);
    sprayHintImage.resize(300, 100);

    background(0);
  
    var position = createVector(mouseX, mouseY);

    //if mouse is pressed, draw a bunch of sprayCircles
    //that move toward the overlaying image
    if (mouseIsPressed) {
    var target = sprayFindPixel();    
    var spraydot = new sprayDot(position, target);

    sprayDots.push(spraydot);

    //allow user to draw a bunch of dots
    if (sprayDots.length > 2000) sprayDots.shift();    

    }  
          //draws the sprayDots
          for (var i = 0; i < sprayDots.length; i++) {

            //make sure sprayDots align with hint image
            push();
            translate(100, 50);
            sprayDots[i].update();
            sprayDots[i].draw();
            pop();

        }   

            //call image of Spray outline
            image(sprayOverlayImage, 100, 50);
            sprayOverlayImage.resize(300, 100);
}

//calculate where the underlying image is dark
//and then draw a spraydot overtop
function sprayFindPixel() {

var x;
var y;

    for (var i = 0; i < 200; i++) {

        x = floor(random(sprayHintImage.width));
        y = floor(random(sprayHintImage.height));
    
        if (red(sprayHintImage.get(x, y)) < 255) break;

  }

  return createVector(x, y);

}

//create sprayDots and define characteristics
function sprayDot(position, target) {

    this.position = position;
    this.target = target;
    this.diameter = random(10, 20);

}

sprayDot.prototype.update = function() {   
  
    this.position = 
    p5.Vector.lerp(this.position, this.target, 0.1);

};

sprayDot.prototype.draw = function() { 
  
    //color of sprayDots
    fill(255);
    ellipse(this.position.x, this.position.y, this.diameter, this.diameter);

};


For this project, I was interested in creating interactive animations that allowed type to be dynamic. I wanted the user to interact with the text based on the actions the words described (erase = erase the words). This project was super challenging and I wish I had more time to generate more interactive animations but I’m overall satisfied with it because I like exploring how to make type more dynamic that I can now use within my own art and design practice.

Leave a Reply