juyeonk – Final Project

For this project I wanted to create a game, but not one of those kinds where you feel anxious and competitive while playing the game.

So I created this game where you can enjoy the winter scenery and a cute dog running while given a bit of an entertainment of being able to move around the dog and its sled to collect the presents.

 

How to:

Use the left/right arrow keys to move around the dog and its sled.

Use the space bar to generate more presents (will be falling from the sky)

NEVER HOLD THE KEY DOWN!!!

The sliding motion of the presents was to re-enact the real time inertia of the objects.

 

sketch

//Claire Koh
//juyeonk@andrew.cmu.edu
//Section E
//Final Project

var frames = []; // An array to store the puppy images
var x = 0; // Variable to draw out an image from the array

var houses = []; // An array to store the house images
var housepics = []; // Array to store the passing by houses

var terrainSpeed = 0.0015;
var terrainDetail = 0.01;
var stars = []; // Array to store the snowflakes

var puppyX = 270; // Initial x position of the puppy
var puppyY = 330; // Initial y position of the puppy (remains the same throughout)

var presents = []; //Array to store the newly created presents



function setup() {
    createCanvas(600, 426);
    frameRate(13)
    // Creates the snowflakes at the beginning
    for (var g = 0; g < 150; g ++) {
        var ry = random(width);
        stars[g] = makeStar(ry);
    }
    
    // Creates the houses at the beginning
    var x = 0;
    for(var i = 0; i < 4; i++) {
        var newHouse = new House();
        newHouse.image = housepics[i];
        newHouse.x = x;
        if(i == 2) {
            newHouse.width = 300;
            newHouse.y = 120;
        }
        x += 300;
        houses.push(newHouse);
    }
    
    
    // Creates the presents at the beginning
    for (i = 0; i <= width; i +=40) {
        presents.push(new Present());
    }
}
 
 
function preload(){
    
    var filenames = [];
    filenames[0] = "https://i.imgur.com/Dv85eeW.png";
    filenames[1] = "https://i.imgur.com/kRjE8sW.png";
    filenames[2] = "https://i.imgur.com/AZLU597.png";
    filenames[3] = "https://i.imgur.com/8wakuK8.png";
    filenames[4] = "https://i.imgur.com/7mD1cW9.png";
    filenames[5] = "https://i.imgur.com/tqUCgkx.png";
    filenames[6] = "https://i.imgur.com/yQ4WaYh.png";
    
    //Loads the images into the frames[] array
    for (var i = 0; i < filenames.length; i ++) {
        frames[i]= loadImage(filenames[i]);
    }

    
    var housepic =[];
    housepic[0] = "https://i.imgur.com/RNMEypc.png";
    housepic[1] = "https://i.imgur.com/NgL94xZ.png";
    housepic[2] = "https://i.imgur.com/TRsZkpd.png";
    housepic[3] = "https://i.imgur.com/X6qFGHM.png";
    housepic[4] = "https://i.imgur.com/TKd1cpX.png";
    housepic[5] = "https://i.imgur.com/uVz8Spc.png";

    // Loads teh images into the housepics[] array
    for (var j = 0; j < housepic.length; j ++) {
        housepics[j] = loadImage(housepic[j]);
    }
}
    


function draw() {
    background(200);
    
    var sky1 = color(27, 36, 49);
    var sky2 = color(30, 55, 92);
   

    for (var c = 0; c <= height; c += 1) {
        var amt = map(c, 0, height/2, 0, 1);
        var skygradient1 = lerpColor(sky1, sky2, amt);
        noStroke();
        fill(skygradient1);
        rect(0, c, width, 1);
    }
        
    
    for (var i = houses.length-1; i>=0; i--){
        houses[i].render();
        houses[i].move();  
    }
    
    createHillShadow();
    createHill();
    
    //SLED
    stroke(0);
    strokeWeight(1);
    line(puppyX-10, puppyY+68, puppyX+25, puppyY+50)
    push();
    noStroke();
    
    fill(112, 100, 35);
    ellipse(puppyX-10, puppyY+68, 8);
    
    strokeWeight(8);
    stroke(112,100,35);
    
    line(puppyX-100, puppyY+50, puppyX-80, puppyY+67.5);
    
    noStroke();
    rect(puppyX-80, puppyY+64, 70, 8);
    pop();
    
    
    
    //PUPPY
    image(frames[x], puppyX, puppyY, 90, 90);
        x += 1;
            if (x > 6) {
                x = 0;
            } 
     
    for (var i = 0; i < presents.length; i++) {
        presents[i].draw();
        presents[i].move();
        presents[i].update();
    }
    
    //SNOW
    updateAndDisplayStars();
    removeStarsThatHaveSlippedOutOfView();
    addNewStarsWithSomeRandomProbability();
    
    
    //INSTRUCTIONS
    push();
    if (frameCount < 50) {
        fill(255);
        textAlign(CENTER);
        text("Use left/right arrow keys to move the puppy", width/2, height/2 - 40)
        text("Press the spacebar to generate more presents", width/2, height/2 - 20)
        text("Try to collect as many presents as you want but you don't have to!", width/2, height/2)
    pop();
    }
    

}



// Function to create the presents
function Present() {
    this.x = random(width);
    this.y = -50;
    this.width = this.height = 20;
    this.velocity = random(1,5);
    this.R = random(100,255);
    this.G = random(100, 255);
    this.B = random(100, 255);
    this.w = -20
    this.draw = function() {
        noStroke();
        fill(this.R,this.G,this.B,200)
        rect(this.x, this.y, this.width, this.height);
        push();
        stroke(255);
        line(this.x, this.y+10, this.x + this.width, this.y + 10)
        line(this.x + 10, this.y, this.x + 10, this.y + this.width)
        pop();
    }
    
    this.move = function() {
        this.y += this.velocity;
        
    }
    
    this.update = function() {
        if (this.y >= height-52 & this.y <= height && abs((puppyX-50)-this.x) < 40) {
            this.y = height-52;
            this.velocity = 0;
        }
        if (keyIsDown(LEFT_ARROW) & this.velocity == 0) {
            this.x -= 10;
        }
        
        if (keyIsDown(RIGHT_ARROW) & this.velocity == 0) {
            this.x += 10;
        }
    }        
}



function keyPressed(){
    // Generates more presents
    if (keyCode === 32) {
        for (i = 0; i <= width; i +=40) {
            presents.push(new Present());
        }
    }
    // Moves the puppy with the left/right arrow keys
    if (keyCode === LEFT_ARROW) {
        puppyX -= 10;
        if (Present.velocity == 0) {
            presents[i].x -= 10;
        }
    }
    if (keyCode === RIGHT_ARROW) {
        puppyX += 10;
        if (Present.velocity == 0) {
            presents[i].x += 10
        }
    }
    
    
}




// Draws House 
function House(){
    this.x = width;
    this.y = 180;
    this.width = 200;
    this.speed = 6;
    this.image;

    this.render = function(){
        image(this.image,this.x, this.y, this.width, this.width);
    }
    
    this.move = function(){
        this.x -= this.speed;
        if (this.x < -200) {
            this.x = width + 100;
        }
     
        this.remove = function() {
            if (this.x < -150) {
                return true;
            } 
            else {
                return false;
            }
        }
    }
}



//BACKGROUND ELEMENTS

// Draws the snowflakes
function updateAndDisplayStars(){
    // Update the lantern's positions, and display them.
    for (var i = 0; i < stars.length; i++){
        stars[i].move();
        stars[i].display();
    }
}


function removeStarsThatHaveSlippedOutOfView(){
    var starsToKeep = [];
    for (var i = 0; i < stars.length; i++){
        if (stars[i].x> 0) {
            starsToKeep.push(stars[i]);
        }
    }
    stars = starsToKeep;
}


function addNewStarsWithSomeRandomProbability() {
    // With some possibility, add new snowflakes
    var newStarLikelihood = 0.8;  
    if (random(0,1) < newStarLikelihood) {
        stars.push(makeStar(width));
    }
}


// Makes the snowflakes move
function starMove() {
    this.x -= this.speed*1.2;
}
    

// Draws the snowflakes
function starDisplay() {
    noStroke()
    fill(255, this.transparency);
    ellipse(this.breadth, this.x, this.size)
}


function makeStar(birthLocationX) {
    var star = {x: birthLocationX,
                y: random(10,70),
                breadth: random(width),
                breadthy: random(height),
                speed: random(0.1,4),
                move: starMove,
                display: starDisplay,
                size: random(2,7),
                transparency: random(150, 255)
               }
    return star;
}



// Creates the shadow of the hill
function createHillShadow() {
    var noiseScale = 0.001;
    var forestDetail = 0.0005;
    var forestSpeed = 0.0005;

    for (var g = 0; g < width; g++) {
        h = (g * forestDetail * 7 + millis() * forestSpeed/8);
        i = map(noise(h), 0, 1, 40, 100);
           stroke(30,70);
           line(g, i+200, g, height-80);
    }  
}


// Creates the hill
function createHill() {
    var noiseScale = 0.001;
    var forestDetail = 0.0005;
    var forestSpeed = 0.0005;

    for (var g = 0; g < width; g++) {
        h = (g * forestDetail * 8 + millis() * forestSpeed/4);
        i = map(noise(h), 0, 1, 40, 100);
           stroke(255);
           line(g, i+250, g, height);
    }  
}




juyeonk-Proposal-12

For the final project, I will be creating an interactive game that is similar to both Flappy Bird and the T-Rex game of Google Chrome (the one that shows up when there’s no internet connection)

It is designed to make the user feel competitive and want to play more just like any typical games, but also to make the user feel happy while playing. That is why I decided to make the ‘main character’ of the game to be the dog. This dog will be flying in the air with the landscape passing by in the background. The goal of the game is not to shoot anything or avoid shooting or anything violent, but is to obtain bunch of floating items in the air. When it encounters a hat, the dog will wear the hat, and when it encounters a piece of clothes, the dog will wear it.

I believe that I will be able to create this by using randomly-created-landscape functions and loadImage() commands. Since The dog will be constantly changing its posture, I would need to use the for loop to constantly load different images.

 

juyeonk-LookingOutwards-12

Title: Nyan Cat

Year of Creation: 2011

Link to the Game: http://www.nyan.cat/

Nyan Cat is a name of the YouTube Video that was uploaded in 2011. It features a cat with a pop-tart body flying in the space forever while leaving a trail of rainbow behind. Although it may seem simple and pointless, Nyan Cat has been re-published in various games and apps that often allow the users to control how the Cat moves around in the space. Sometime it has to pick up the candies on the way, or sometime the user can even personalize the cat with different costumes (i.e. different types of the pop-tarts) and accessories. I love the idea of it being the friendly game, rather than the majority of the flying action game where you have to either destroy some aircraft or avoid the shooting that is coming from those aircraft.

Image result for nyan cat

^Screenshot of the Nyan Cat video.

 

Title: T-Rex Jumping Game

Artist: Google

Year of Creation:

Link to the Article: https://www.nytimes.com/2017/11/14/technology/personaltech/chrome-dinosaur-internet-connection.html?_r=0

Link to the Game:

The T-Rex Jumping Game has been providing Chrome users with a source of entertainment and a way to relieve the frustration and the stress they may find when stumbled upon the ‘no internet sign’. It uses the randomly generated landscape with cacti and during the later stage, birds as the obstacle to the ever-running T-Rex. I appreciate Google’s intention of creating something that could help with our emotion, or helping us forget the brutality of the reality for a split second. Similarly, for the final project, I would like to create something that uses the similar mechanisms (using the keyboard to control the object, perhaps using a randomly-generated landscape as well) to create an interactive game that would boost the user’s mood.

Old unable to connect to the internet page

^Message that shows up on Chrome when you don’t have an access to Internet.

Google dinosaur game

^ But you can still play the game!

juyeonk-Project-11-Composition

sketch

//Claire Koh
//Section E
//juyeonk@andrew.cmu.edu
//Project-11

var t1; // Linked to makeTurtle

function setup() {
    createCanvas(480, 300);
    
    t1 = makeTurtle(width/2,height/2); // sets the starting coordinate for the turtle
    t1.penDown();
    
}



function draw() {
    background(0);
    t1.forward(1)
    t1.turnToward(mouseX, mouseY, 10);
    
    drawCarrots(); // draws the Carrot
}


//Draws the carrot that follows around the cursor
function drawCarrots () {
    noStroke();
    fill(56, 88, 48);
    triangle(mouseX, mouseY, mouseX+3, mouseY - 20, mouseX+6, mouseY)
    triangle(mouseX+6, mouseY, mouseX + 9, mouseY - 20, mouseX+10, mouseY-3)
    fill(255,156,0);
    triangle(mouseX, mouseY - 10, mouseX-5, mouseY + 30, mouseX + 10, mouseY - 3)
}



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) {
    push();
    
   
    if (this.penIsDown) {
      strokeJoin(MITER);
      strokeCap(PROJECT);
      stroke(this.color);
      strokeWeight(this.weight);
      line(this.x, this.y, x, y);
      this.x = x;
      this.y = y;
        
        
        noStroke();
    fill(174, 237, 201);
    ellipse(this.x, this.y, 30,50);
    
    fill(56, 88, 48);
    ellipse(this.x, this.y, 20,40);
    
    ellipse(this.x, this.y + 31, 12)
    }
    pop();
    
    
    
    
}


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;
    
}




For this project I wanted to take the term “turtle” literally and make a turtle that follows around the cursor. The turtle is constantly moving, but its point of destination is always changing according to the new location of mouseX and mouseY. When reaches the cursor, it will circle around the cursor, but as soon as you move the mouse it will start moving towards the mouse again.

One thing that I could have done is rotating the turtle towards the mouse so that its head will always facing the cursor. But unfortunately the push and pop commands and the translate and rotate commands did not work as I expected.

juyeonk-LookingOutwards-11

Title: The Classyfier

Artist: Benedict Hubener, Stephanie Lee, Kelvyn Marte, with the help of Andreas Refsgaard

Year of Creation: 2017

Link to the Article: http://www.creativeapplications.net/processing/the-classyfier-ai-detects-situation-and-appropriates-music/

The Classyfier is a machine that chooses an appropriate song that suits your mood. It does so by detecting the kind of beverages people are consuming by using the built-in microphone to catch the characteristic sounds and comparing it to the pre-trained examples (ex: clinking of the wine glasses or opening a can of beer), and the main programs used to create the algorithms were Wekinator, Processing and the OFX collection. The Classyfier will then “classify” the drinks into one of the three categories: hot beverages, wine, and beer, then it would start playing the music from the playlist that is designated to each category. The user could also knock on the table to navigate through the playlist.

It is interesting to me how machines could help us in social situations and help everything to go naturally with the flow when machines are generally expected to be a hindrance to interactions between people. It’s exciting to see how technology is getting more and more seamlessly integrated to our lives.

 

juyeonk-project-10

 

sketch

var terrainSpeed = 0.0005;
var terrainDetail = 0.01;
var buildings = [];
var stars = [];
var balls = []; 
var clouds = [];


function preload() {
    castleImage = loadImage("https://i.imgur.com/enlJeCX.png");
}

function setup() {
    createCanvas(480, 320);
    frameRate(10);
    
    for (var i = 0; i < 3; i++){
        var rx = random(width);
        buildings[i] = makeBuilding(rx);
    }
    
    for (var g = 0; g < 150; g ++) {
        var ry = random(width);
        stars[g] = makeStar(ry);
    }
    
    for (var h = 0; h < 5; h ++) {
        var rz = random(width);
        clouds[h] = makeCloud(rz);
    }
}   
 


function draw() {
    background(255);
    
    var sky1 = color(33, 25, 64);
    var sky2 = color(6, 41, 100);
    var sky3 = color(135, 110, 168);
    var sky4 = color(201, 159, 161);
    var sky5 = color(254, 219, 155);
    var sky6 = color(246, 179, 124);

    
    for (var c = 0; c <= height/3.5; c += 1) {
        var amt = map(c, 0, height/3.5, 0, 1);
        var skygradient1 = lerpColor(sky1, sky2, amt);
        noStroke();
        fill(skygradient1);
        rect(0, c, width, 1);
    }
    
    for (var d = 0; d <= height/2.5; d ++ ) {
         var amt = map(d, 0, height/2.5, 0, 1);
         var skygradient2 = lerpColor(sky2, sky4, amt);
         noStroke();
         fill(skygradient2);
         rect(0, c + d, width, 1);
         }
    
    for (var e = 0; e <= height/5; e ++ ) {
         var amt = map(e, 0, height/5, 0, 1);
         var skygradient3 = lerpColor(sky4, sky2, amt);
         noStroke();
         fill(skygradient3);
         rect(0, c + d + e, width, 1);
         }
    
    
    image(castleImage, 20, 70, 120,120);
    
    updateAndDisplayStars();
    removeStarsThatHaveSlippedOutOfView();
    addNewStarsWithSomeRandomProbability();
    createHill();
    drawRectangle();
    createHillShadow();
   
    updateAndDisplayBuildings();
    removeBuildingsThatHaveSlippedOutOfView();
    addNewBuildingsWithSomeRandomProbability(); 
    
    makeballs();
    
    updateAndDisplayClouds();
    removeCloudsThatHaveSlippedOutOfView();
    addNewCloudsWithSomeRandomProbability();
    
    newBalls = []; // Creates an empty array that will store the values of the newly-created balls
        for (var i = 0; i < balls.length; i++) { 
            var p = balls[i];
            p.speedy(); //returns the function speed() which makes the balls move
            p.balls(); //returns the function balls() which assigns the balls their properties
            newBalls.push(p); 
        }
    balls = newBalls;
}



function updateAndDisplayStars(){
    // Update the lantern's positions, and display them.
    for (var i = 0; i < stars.length; i++){
        stars[i].move();
        stars[i].display();
    }
}


function removeStarsThatHaveSlippedOutOfView(){
    var starsToKeep = [];
    for (var i = 0; i < stars.length; i++){
        if (stars[i].x> 0) {
            starsToKeep.push(stars[i]);
        }
    }
    stars = starsToKeep;
}


function addNewStarsWithSomeRandomProbability() {
    // With some possibility, add a new lantern
    var newStarLikelihood = 0.5; 
    if (random(0,1) < newStarLikelihood) {
        stars.push(makeStar(width));
    }
}


// Makes the lanterns move
function starMove() {
    this.x -= this.speed;
}
    

// Draws the lanterns
function starDisplay() {
    fill(250, 254, 149);
    rect(this.breadth, this.x, this.size, this.size*1.5)
}


function makeStar(birthLocationX) {
    var star = {x: birthLocationX,
                y: random(10,70),
                breadth: random(width),
                breadthy: random(height),
                speed: random(0.1,4),
                move: starMove,
                display: starDisplay,
                size: random(2,7)
               }
    return star;
}




function createHill() {
    var noiseScale = 0.001;
    var forestDetail = 0.0005;
    var forestSpeed = 0.0005;

    for (g = 0; g < width; g++) {
        h = (g * forestDetail * 8 + millis() * forestSpeed/8);
        i = map(noise(h), 0, 1, 40, 100);
           stroke(30);
           line(g, i+100, g, height-80);
    }  
}




function drawRectangle() {
    var sky1 = color(33, 25, 64);
    var sky2 = color(37, 55, 127);
    var sky3 = color(135, 110, 168);
    var sky4 = color(201, 159, 161);
    var sky5 = color(254, 219, 155);
    var sky6 = color(246, 179, 124);
    
    for (var e = 0; e <= height/5; e ++ ) {
         var amt = map(e, 0, height/5, 0, 1);
         var skygradient3 = lerpColor(sky6, sky1, amt);
        noStroke();
        fill(skygradient3);
        rect(0, 240+e, width, 1);
         }
    
    fill(sky1);
    rect(0, 240+e, width, height-(240+e))
    
    
}


function createHillShadow() {
    var noiseScale = 0.001;
    var forestDetail = 0.0005;
    var forestSpeed = 0.0005;

    
    var noiseScale = 0.001;
    var forestDetail = 0.0005;
    var forestSpeed = 0.0005;
    
    push();
    translate(0,480)
    scale(1,-1)
    // 3rd "layer" of forest
    for (g = 0; g < width; g++) {
        h = (g * forestDetail * 8 + millis() * forestSpeed/8);
        i = map(noise(h), 0, 1, 40, 100);
           stroke(30,70);
           line(g, i+150, g, height-80);
    }  
    pop();
}




//Below: set of functions that create the boats
function updateAndDisplayBuildings(){
    // Update the building's positions, and display them.
    for (var i = 0; i < buildings.length; i++){
        buildings[i].move();
        buildings[i].display();
    }
}


function removeBuildingsThatHaveSlippedOutOfView(){
    var buildingsToKeep = [];
    for (var i = 0; i < buildings.length; i++){
        if (buildings[i].x + buildings[i].breadth +30 > 0) {
            buildingsToKeep.push(buildings[i]);
        }
    }
    buildings = buildingsToKeep; // remember the surviving buildings
}


function addNewBuildingsWithSomeRandomProbability() {
    // With a very tiny probability, add a new building to the end.
    var newBuildingLikelihood = 0.009; 
    if (random(0,1) < newBuildingLikelihood) {
        buildings.push(makeBuilding(width));
    }
}


// method to update position of a boat every frame
function buildingMove() {
    this.x -= this.speed;
}
    

// draw the boats
function buildingDisplay() {
    var floorHeight = 20;
    var bHeight = this.nFloors * floorHeight; 
    fill(this.R, this.G, this.B); 
    noStroke(); 
    push();
    translate(this.x, height-this.y);
    rect(0, -bHeight, this.breadth, bHeight);
    triangle(-30, -bHeight, 0, -bHeight, 0, 0);
    triangle(this.breadth+30, -bHeight, this.breadth, -bHeight, this.breadth, 0)
    stroke(200); 
    pop();
    
    
    //draws the reflections of the boats
    push();
    fill(this.R, this.G, this.B, 80);
    translate(this.x, height-this.y);
    scale(1,-1)
    rect(0, -bHeight/2, this.breadth, bHeight);
    triangle(-30, -bHeight/2, 0, -bHeight/2, 0, 0);
    triangle(this.breadth+30, -bHeight/2, this.breadth, -bHeight/2, this.breadth, 0)
    stroke(200); 
    pop();
}


function makeBuilding(birthLocationX) {
    var bldg = {x: birthLocationX,
                cloudx: random(width),
                y: random(10,70),
                breadth: random(60,90),
                speed: random(2,3),
                cloudspeed: random(0.5,1),
                R: random(70,90),
                G: random(50,70),
                B: random(10,40),
                transparency: random(100,200),
                nFloors: round(random(1,1.5)),
                move: buildingMove,
                display: buildingDisplay
               }
    return bldg;
}





//Below: set of functions that generate the clouds
function updateAndDisplayClouds(){
    for (var i = 0; i < clouds.length; i++){
        clouds[i].move();
        clouds[i].display();
    }
}


function removeCloudsThatHaveSlippedOutOfView(){
    var cloudsToKeep = [];
    for (var i = 0; i < clouds.length; i++){
        if (clouds[i].x + clouds[i].breadth +30 > 0) {
            cloudsToKeep.push(clouds[i]);
        }
    }
    clouds = cloudsToKeep;
}


function addNewCloudsWithSomeRandomProbability() {
    // With a very tiny probability, add a new building to the end.
    var newCloudLikelihood = 0.02; 
    if (random(0,1) < newCloudLikelihood) {
        clouds.push(makeCloud(width));
    }
}



function cloudMove() {
    this.x -= this.speed;
}
    


function cloudDisplay() { 
    push();
    fill(255, this.transparency);
    translate(this.x+50, 100 + this.y);
    ellipse(0, 0, this.y, this.y*0.5);
    pop();
}


function makeCloud(birthLocationX) {
    var cloud = {x: birthLocationX,
                y: random(10,70),
                breadth: random(60,90),
                speed: random(0.5,1),
                transparency: random(100,200),
                move: cloudMove,
                display: cloudDisplay
               }
    return cloud;
}




function makeballs() {
    var ix = constrain(floor(this.xx), 0, width-1);
    var iy = constrain(floor(this.yy), 0, height-1);
    
    fill(250, 254, 149) 
    noStroke();
    rect(this.x, this.y, this.ballsize, this.ballsize*1.5); // Draws the ellipse at (x,y) with the width and the height dimension of 'ballsize' which is a random number between 2 and 8
}



function ballspeed() {
    this.y += this.dy; // MouseY will be later assigned as 'y'
}



function drawPortrait(placeholderx, placeholdery, placeholderdy) {
    p = {x: placeholderx, 
         y: placeholdery,
         dy: placeholderdy,
         speedy: ballspeed,
         balls: makeballs,
         ballsize : random(4,10)
        }
    return p;
}


// Lanterns generated when the mouse is moved
function mouseMoved() {
        var newball = drawPortrait(mouseX, mouseY, random(-20, 20));
        balls.push(newball);
        x += random(x-3, x+3);
}

 

I wanted to recreate a scenic setting from my favorite Disney movie – Tangled!!!! There are total five components of the landscape, which are the moving clouds, the hill, the shadow of the hill, the lanterns, and the moving boats. There’s a little surprise hidden in this code; you could perhaps try moving your mouse to find out what it is!

Initially I wanted to make Rapunzel and Flynn Rider to randomly pop up on one of the boats but I had some difficulty coding it. It was a little annoying that I had to make multiple sets of the functions for different objects, but at the end it was rewarding because I got to recreate my favorite Disney movie.

Also I’d like to use one of my grace days for this project. Thank you!

juyeonk-LookingOutwards-10

^Shantell using the motion sensor device to leave the trail.

^ Rhino screen showing the trail of the device.

Title: Drawing Trails

Artist:  Shantell Martin

Year of Creation: 2016

Link to the Article of the Project:  https://shantellmartin.art/work/drawing-trails/

Link to the Bio of the Artist: https://shantellmartin.art/info/

 

Drawing Trails was a collaboration between visual/digital artist Shantell Martin and architect Maria Yablonina as a way to visualize the trail that we leave behind our motions. The concept was to explore the idea that whatever we do and wherever we go we leave an inevitable traces behind us and what they would look like if they were to be digitally captured and 3-d printed.

First, the motion sensor device will detect the movement of the object and transfer the information to the computer, which will use Rhino and Grasshopper with a customized program to visually map the data on the screen. The visual information on Rhino workspace will be then 3-d printed, giving us a chance to visually and sensibly observe the invisible trails that we have left behind for the first time.

The idea that we could observe our own trails is very interesting, but I am still a little dubious if it could be practical in capturing a larger degree of motion. However, simply as a new means of creating a sculptural art, this was a very unique attempt.

^ Sculptures created as Drawing Trails

juyeonk-project-09

sketch

//Claire Koh
//Section E
//juyeonk@andrew.cmu.edu
//Project-09


var balls = []; // An array that will store the little balls that make up the portrait


// Loads the image
function preload() {
    var myImageURL = "https://i.imgur.com/AOyeLOo.jpg";
    underlyingImage = loadImage(myImageURL);
}


function setup() {
    createCanvas(480, 480);
    background(0);
    underlyingImage.loadPixels(); // Loads the pixel data of the image
}



// Determines the properties of the balls
function makeballs() {
    var ix = constrain(floor(this.x), 0, width-1);
    var iy = constrain(floor(this.y), 0, height-1);
    var theColorAtLocationXY = underlyingImage.get(this.x, this.y); //gets the color value of the image at (x,y)
    
    fill(theColorAtLocationXY) // Fills the balls with the color of the image at (x,y)
    noStroke();
    ellipse(this.x, this.y, this.ballsize); // Draws the ellipse at (x,y) with the width and the height dimension of 'ballsize' which is a random number between 2 and 8
}



// Makes the ball move
function ballspeed() {
    this.y += this.dy; // MouseY will be later assigned as 'y'
}



// Sets up the function that returns the properties of the object p, which contains information like the coordinate point of x, y, dy, a function that determines the speed of the ball, a function that creates balls, and the size of the ball
function drawPortrait(placeholderx, placeholdery, placeholderdy) {
    p = {x: placeholderx, 
         y: placeholdery,
         dy: placeholderdy,
         speed: ballspeed,
         balls: makeballs,
         ballsize : random(2,8)
        }
    return p;
}



function draw() {
    newBalls = []; // Creates an empty array that will store the values of the newly-created balls
    for (var i = 0; i < balls.length; i++) { 
        var p = balls[i];
        p.speed(); //returns the function speed() which makes the balls move
        p.balls(); //returns the function balls() which assigns the balls their properties
        newBalls.push(p); 
    }
    balls = newBalls;
}


// When the mouse is moved it replaces the placeholderx placeholdery and placeholderdy values with mouseX, mouseY and random(-20,20) and make the drawPortrait function actually happen and to be stored in the newball array
function mouseMoved() {
        var newball = drawPortrait(mouseX, mouseY, random(-20, 20));
        balls.push(newball);
        x += random(x-3, x+3);
}

For this project I wanted to make the portrait appear as if it is being drawn by bunch of rain droplets. I tried to take a break from using the function-based operation and and use the object-based operation for once. Overall I think this project was a good opportunity for me to break down how the object-based operation works and to actually learn how to use it.

Initially I tried to make the little rain droplets to drop from the sky and to collect at the bottom without overlapping each other but I legitimately could not figure out how to make that happen so I just made the little droplets to crawl up or down at a constant speed and go beyond the canvas.

^ Original sketch

^

^ While it’s being drawn

^ Almost done

 

**Credit to Grace Hou for letting me use her picture!!**

juyeonk-LookingOutwards-09

Credit to Ryu Kondrup and his post on The Mylar Typology by Paul Prudence

Title: The Mylar Typology

Artist: Paul Prudence

Year of Creation: 2017

Link to the Project: http://www.transphormetic.com/The-Mylar-Topology

Link to the bio of the Artist: http://www.transphormetic.com/Biography

 

While I was browsing through the Looking Outwards posts I came across multiple artworks that caught my attention. Among these, Ryu’s post on the audiovisual artwork titled The Mylar Typology by Paul Prudence seemed especially interesting for its unique concept and the high-tech methods that was used to create the artwork.

The Mylar Typology is a combination of an ever-evolving visual abstract landscape (that was created by closely filming the reflections on the Mylar sheets and distorting them) and the oscillating tones that are supposed to affect our brainwaves in a way that would make us feel relaxed. Both the oscillating visual art and the audio that are synchronized to each other work as stimuli to our brains by affecting the frequency, amplitude, and periodicity of the brainwaves that are shared by the optical and visual waves as well.

It’s interesting to me how the artist combined both the visual and the audio aid to double the effect that his work has on the audience. I had come across multiple ‘relaxing sounds that are good for studying and relaxation’ that incorporate oscillating sounds but none of them had a visual aid that is just as abstract and science-based as this one.

I also admire the high-technological aspect of the artwork; unlike most other artwork or music that is supposed to calm you down by evoking a peaceful memory or having a mild tone that is associated with a calm atmosphere, this artwork literally manipulates a part of our brain to make us feel relaxed. Without the help of the scientific studies on brains or modern technology that can detect the brain waves and produce them as well, this artwork could have not existed.

 

juyeonk-LookingOutwards-08

 

Artist: Sarah Williams

Year: 2014

Link to the Artist’s Website: http://civicdatadesignlab.mit.edu/

Link to the Brief Bio of the Artist: http://eyeofestival.com/2014/speaker/sarah-williams/

 

Sarah Williams is currently an Assistant Professor of Urban Planning and the Director of the Civic Data Design Lab at the MIT School of Architecture and Planning. Her work at Civic Data Design Lab focuses mainly on digitally visualizing urban patterns and data for the purpose of making them more accessible to the general public.

I was amazed at the scope and the variety of data that her team and she have created in the past. The scale of her maps range from few blocks in the city to the entire country and include general topics like population, transportation and urban growth as well as some less familiar topics such as natural disaster and the route of the New York Fashion Designers. However multifaceted the topics and ranges of her maps may be, they all have a single purpose: to deliver the information in the most efficient and helpful way. She creates these informational maps to solve the growing urban problems such as traffic, congestion, pollution and other social problems and to inform the audience of how their city looks like in both quantitative and qualitative terms.

In her presentation she mentioned that there are 6 elements of data visualization. This was a good way to organize different aspects of data visualization and to offer a clear steps to how you may visualize the data on your own. I was impressed by the fact that she included the “being open with data” as one of the elements because it seems to imply how open and friendly the society has become, that information and data is something to be shared and not to be kept secret from others.