Romi Jin – Project-12-Final Project

sketch

/*
Romi Jin
Section B
rsjin@andrew.cmu.edu
Project-12
*/

var pic = {};
pic.bunny = "BUN.gif"; //bunny gif
pic.cloud = "cloud.png"; //cloud ground and movable
pic.carrot = "carrot.png"; //carrots to collect

var posX = 50; //start position
var posY = 50;
var speed = 4;
var jump_height = 15;
var jump = 38;
var left = 37;
var right = 39;
var moveinterval;
var gravityinterval;
var constant = 1;
var bound = 8;
var size = 5000;
var keysDown = [];
var stage;
var bunny;
var carrotnumber;
var above = 1;
var toleft = 3;
var onground = false;
var canjump = true;
var timer = 500;
var BOUNCE_FACTOR = 2;
var movingclouds = [];
var carrots = [];
var objects = [];
var start = 0;
var moveleft = 0;
var moveright = 1;
var movex = moveright;
var objectnumber;

function move(){
  //move bunny and define key pressed functions
  for (key in keysDown){
    switch (keysDown[key]){
      case right:
        posX += speed;
        if (stage.scrollLeft < size)
          stage.scrollLeft = bunny.offsetLeft-(stage.offsetWidth/2)+(bunny.offsetWidth/2);
        if (onground)
          bunny.src = pic.bunny;
        movex = moveright;
        break;
      case jump:
        if (onground & canjump){
          canjump = false;
          setTimeout(function(){canjump=true;},timer);
          constant = -jump_height;
          posY -= jump_height;
          onground = false;
          bunny.src = (movex==moveright) ? pic.bunny : pic.bunny;
        }
        break;
      case left:
        if (onground)
          bunny.src = pic.bunny;
        posX -= speed;
        stage.scrollLeft = bunny.offsetLeft-(stage.offsetWidth/2)+(bunny.offsetWidth/2);
        movex = moveleft;
        break;
      default:
    }
  }
  
  start++;
  //how clouds move up and down
  for (i in movingclouds){
    movingclouds[i].style.top = 150+50*Math.sin(start/50)+"px";
  }
  //when bunny stops in front of objects
   bunnystop();
  //render bunny
  render();
}

function collect(x){
  //collects carrots
  if (carrots.indexOf(x) > -1){
    remove(carrots,x);
    remove(objects, x);
    stage.removeChild(x);
    takeCarrot();
    return true;
  }
  return false;
}

function bunnyjump(a, b, c, d){
  if (c >= b) {
    d();
    return;
  }
  a.style.top = a.offsetTop - c + "px";
  setTimeout(function(){bunnyjump(a, b, c+1, d)}, 50);
}

function takeCarrot(){
  //adds to number of carrots in upper left corner -- keeps count / score
  carrotnumber.innerHTML = parseInt(carrotnumber.innerHTML)+1;  
}

function bunnystop(){
  //when bunny stops moving
  if (posX < stage.offsetLeft) posX = 5;
  if (posX+bunny.offsetWidth>size) posX = size - bunny.offsetWidth;
  
  onground = false;
  objectnumber = 0;
  
  for (c in objects){
      switch (bunnybounds(objects[c])){
        case above:
          if (collect(objects[c])) break;
          posY = objects[c].offsetTop-bunny.offsetHeight;
          onground = true;
          if ((objects[c])) break;
          speed = speed;
        case toleft:
          if (collect(objects[c])) break;
          posX = objects[c].offsetLeft-bunny.offsetWidth;
          if (!canjump)
            speed = 1;
          break;
      }
  }
}

function bunnybounds(x){
  //keep bunny outside objects
  if (posY+bunny.offsetHeight>x.offsetTop & 
    (posX + (bunny.offsetWidth/2)) > x.offsetLeft &&
    (posX + (bunny.offsetWidth/2)) < (x.offsetLeft+x.offsetWidth) &&
    posY < x.offsetTop &&
    posY+bunny.offsetHeight<(x.offsetTop+x.offsetHeight))
    return above;
  if (posX+bunny.offsetWidth>x.offsetLeft & 
    (posY + (bunny.offsetHeight/2)) < (x.offsetTop+x.offsetHeight) && 
    posX < x.offsetLeft && 
    (posY + (bunny.offsetHeight/2)) > x.offsetTop)
    return toleft;
  return 0;
}

function render(){
  //render bunny start position
  bunny.style.left = posX + "px";
  bunny.style.top = posY + "px";
}

function renderWorld(){
  //create all objects and defines elements of each
  stage = document.getElementById('stage');
  bunny = document.getElementById('bunny');
  carrotnumber = document.getElementById('carrotnumber');
  
  var clouds = [];
  for (var i = 0; i < 24; i++){
    clouds.push(cloudsurface(null, pic.cloud, i*40, stage.offsetHeight-35));
    objects.push(clouds[i]);
  }
  
  setTimeout(function(){
    var a = cloudsurface(clouds[9], pic.cloud);
    var b = cloudsurface(clouds[8], pic.cloud, -10, -100);
    objects.push(b);
    carrots.push(b);
    
    for (var i = 0; i<3; i++){
      var x = cloudsurface(clouds[6], pic.cloud, i*20, -40);
      objects.push(x);
      objects.push(x);

    }
    for (var i = 0; i<3; i++){
      var x = cloudsurface(clouds[4], pic.cloud, i*20, -40);
      objects.push(x);
      objects.push(x);
    }

    var c = cloudsurface(clouds[10], pic.cloud);
    var d = cloudsurface(clouds[20], pic.cloud);
    movingclouds.push(c);
    movingclouds.push(d);
    
    for (var i = 0; i<3; i++){
      var x = cloudsurface(clouds[7], pic.carrot, i*30, -10);
      objects.push(x);
      carrots.push(x);
    }
    for (var i = 0; i<4; i++){
      var x = cloudsurface(clouds[6], pic.carrot, i*30+5, -100-i*30);
      objects.push(x);
      carrots.push(x);
    }
    for (var i = 0; i<3; i++){
      var x = cloudsurface(clouds[10], pic.carrot, i*30, -230);
      objects.push(x);
      carrots.push(x);
    }
    
    for (var i = 1; i<4; i++){
      var x = cloudsurface(clouds[15], pic.cloud, i*20, -60);
      objects.push(x);
      objects.push(x);
      
      var x = cloudsurface(f, pic.carrot, 12, -i*30-140);
      objects.push(x);
      carrots.push(x);
    }
    
    for (var j = 0; j < 9; j++){
      for (var i = 0; i<11; i++){
        if (i <= j) continue;
        var x = cloudsurface(clouds[20], pic.cloud, i*20, -j*20);
        objects.push(x);
      }
    }
    
    var e = cloudsurface(clouds[10], pic.cloud);
    objects.push(e);
    var f = cloudsurface(clouds[20], pic.cloud);
    objects.push(a);
    objects.push(b);
    objects.push(c);
    objects.push(d);
    objects.push(f);

  },1000);
}

function cloudsurface(surface, pic, left, y){
  //cloud ground positioning
    var cloud = document.createElement("img");
    cloud.src = pic;
    stage.appendChild(cloud);
    cloud.style.position = "absolute";
    cloud.style.top = ((surface != null) ? (surface.offsetTop-cloud.offsetHeight + (y||0)) : y) + "px";
    cloud.style.left = ((surface != null) ? surface.offsetLeft + (left||0) : left) + "px";
    return cloud;
}

function gravity(){
  //bunny positioning in terms of gravity
  if (!onground)
    posY += constant;
  constant++;
  if (constant > bound) constant = bound;
}

function remove(x, y){
  //removes the carrots
  if (x.indexOf(y) > -1)
    x.splice(x.indexOf(y),1);
}

function onkeyDown(i){
  //defines key down pressed
  var down = window.event || i;
  var keypress = i.charCode || i.keyCode;
  if (down.preventDefault)
    down.preventDefault();
  else{
    down.returnValue = false;
  }
  if (keysDown.indexOf(keypress) > -1) return;
  keysDown.push(keypress);
  return false;
}

function onKeyUp(i){
  //allows bunny to move backwards
  var down = window.event || i;
  var keypress = i.charCode || i.keyCode;
  remove(keysDown, keypress);
}

function loadPics(load){
  //load all images and gifs
    for (i in pic){
      var img = new Image();
      img.src = pic[i];
      img.onload = (function(h,i){
          return function(){
            i = h;
          }
        })(img.src, pic[i]);

    }
    load();
}

$(document).ready(function(){
  loadPics(function(){
    renderWorld();
    stage.scrollLeft = 0;
  });
  setTimeout(function(){
    moveinterval = setInterval(function(){move();},15);
    gravityinterval = setInterval(function(){gravity();},30);
    $(this).keydown(onkeyDown);
    $(this).keyup(onKeyUp);
  },500);
});
    

For my final project, I initially tried to create like mario run, but it ended up being a lot more complicated than I had expected, so I made the game a lot more simpler than what I had imagined it would be. The bunny can move left and right to collect carrots while running and jumping on clouds (some move, some don’t), and the goal is to collect all of the carrots. I have a separate js file and text in the html file, so I am not sure how to upload them all and make the file show up on WordPress, so I have attached a screenshot of what the final product looks like on my screen:

Romi Jin – Project-12-Proposal

For my final project, I am interested in making an interactive game, but I am not too certain what all the details will be yet. Like in mario games, there will be a character you play as and move throughout a two-dimensional landscape, collecting coins and finding mystery items by jumping on and over things, except instead of Mario, it will be a bunny collecting carrots and avoiding enemies along the way. If the bunny bumps into an enemy, it would lose, and if it gets a certain amount of carrots, it would win. I would like to create something like the image below:

in which the bunny hopping along a grassy landscape, and possibly through houses, go underground and jump onto trees to find carrots and eventually win the game. Somehow, I’d like to be able to make this a two-player game as well if I have the time.

Romi Jin – Looking Outwards 12

For my final project, I want to create an interactive game with a moving landscape. The initial examples that I thought of were Super Mario Bros, developed by Shigeru Miyamoto, and Fireboy and Watergirl, developed by Oslo Albert. Growing up playing these games, I have always wanted to be able to create something similar. In each of the games, the characters try to avoid enemies to collect items they need to win the game. However, in mario bros, the enemies move around while in the other, the “enemies” are stationary in that they are bodies of water and fire. I am interested in creating something like the former, with moving objects towards the bunny with a moving landscape like one of the previous projects we have done (generative landscape). But I like how Fireboy and Watergirl has a multiplayer component to it (as the mario bros game I grew up playing did not).


(Super Mario Bros)


(Fireboy and Watergirl)

Romi Jin – Project-11-Composition

sketch

/*
Romi Jin
Section B
rsjin@andrew.cmu.edu
Project-11
*/


function setup() {

    createCanvas(480, 480);
    background("black");

}

function draw() {

    var myTurtle = makeTurtle(width/2, height/2);
    myTurtle.penDown();
    myTurtle.setColor("white");
    myTurtle.setWeight(0.05);
    strokeJoin(MITER);
    strokeCap(PROJECT);
    var step = 1; //different patterns

    for (i = 0; i <= 150; i++) { 

        //flower drawing
        myTurtle.forward(step);
        myTurtle.left(step);
        myTurtle.forward(step);
        myTurtle.left(step);
        myTurtle.forward(step);
        myTurtle.left(step);
        myTurtle.forward(step);
        myTurtle.left(step);

        //angle
        myTurtle.right(200);
        //spacing
        myTurtle.forward(i*3);
    }

}


/////////////////////////////////////////////////////////////

//turtle code

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

For this project, I decided to play around with angles and lines and see what kind of shapes I could make with different patterns and sizing. I eventually ended up with a flower / pinwheel, drawn spiraling out to a certain angle. It was interesting to see the difference between using turtle graphics to draw this versus not using it.

Romi Jin – Looking Outwards 11

Keiko Uenishi is known for experimenting with “restructuring and reanalyzing one’s relationship with sounds in sociological, cultural and/or psychological environments.” One of her works that stood out to me is an installation entitled CDL, or Car Décalé (Légèrement)/Because Shifted (Slightly). Since Uenishi dabbles with the questioning of ideas of space through what she calls aural perceptions, and her experiments expose people to temporal spatial experiences that are usually new to them.

(Below is an example of one of her sound experiments about found objects.)

CDL is an “experiential/phenomenological sound-performance/installation/method” that uses audio-feedback to redefine a space. Uenishi uses simple spatial parameters as a setting for the experience (i.e. no decorations, no special flooring or walls, no furniture, no columns, etc.) as there should be no unnecessary distractions. The version of CDL above uses found objects (mainly construction materials) to create a part to whole experience — a series of smaller, temporary structures within a larger structure (the room). After attempted experiments, she would add or alter the objects to, in conjunction, alter the spatial experience of this specific CDL.

Romi Jin – Project-10-Landscape

sketch

/*
Romi Jin
Section B
rsjin@andrew.cmu.edu
Project-10
*/

var terrainSpeed1 = 0.0005;
var terrainDetail1 = 0.015;
var terrainSpeed2 = 0.0005;
var terrainDetail2 = 0.005;
var frames = []; 

function setup() {
  createCanvas(480, 480);

    imageMode(CENTER);
    frameRate(11); //speed of doggos
} 

function preload(){
    var filenames = [];
      filenames[0] = "https://i.imgur.com/ejRANDS.png";
      filenames[1] = "https://i.imgur.com/coVxjO1.png";
      filenames[2] = "https://i.imgur.com/qJKozUu.png";
      filenames[3] = "https://i.imgur.com/ukTPJk3.png";
      filenames[4] = "https://i.imgur.com/KlTBTOl.png";
      filenames[5] = "https://i.imgur.com/Yei5uel.png";
      filenames[6] = "https://i.imgur.com/srcpeKV.png";
      filenames[7] = "https://i.imgur.com/3mbE69u.png";
      filenames[8] = "https://i.imgur.com/EKPZJMw.png";
      filenames[9] = "https://i.imgur.com/L6GOIGZ.png";

    for (var i = 0; i < filenames.length; i++) {
        frames.push(loadImage(filenames[i]));
    } 

}

function draw() {
    background('black');
    mountain1();
    mountain2();
    push();
    doggos();
    pop();

    //ground
    fill(255, 174, 76);
    rect(0, 375, width, 105);
}


function mountain1(){
  noStroke();
  fill(139, 64, 0); 
  beginShape(); 
  for (var x = 0; x < width; x++) {
    var t = (x * terrainDetail1) + (millis() * terrainSpeed1);
    var y = map(noise(t), 0, 2, height/8, height);
    vertex(x, y); 
  }
  vertex(width, height);
  vertex(0, height);
  endShape();
}

function mountain2(){
  fill(217, 119, 0); 
    noStroke();
    beginShape(); 
      for (var x = 0; x < width; x++) {
            var t = (x * terrainDetail2) + (millis() * terrainSpeed2);
            var y = map(noise(t), 0, 1.75, height/2, height);
            vertex(x, y); 
      }
      vertex(width, height);
      vertex(0, height);
    endShape();
}


function doggos(){

    //dooggos scaled down and translated to center
    translate(width/2,360);
    scale(.2,.2);
    image(frames[frameCount % 10], 0, 0);

}

I decided to do a Halloween themed project! Using a gif I found online and editing it on Photoshop (editing out the background and creating separate png files), the two dressed-up dogs are walking along the horizon against an black background and orange mountains.

Romi Jin – Looking Outwards 10

Something I have always been interested in is the field of virtual reality. Milica Zec, a NYC-based film and virtual reality director, created a virtual reality experience entitled “Giant”. This experience is based on true events and represents what her and her family went through in Serbia during the 1990s, pulling directly on personal experience. This kind of virtual reality reminds me of an exhibit I saw at the Whitney about a year or two ago — a violent but symbolic VR scene, except this one is based on real events. The media takes you through an American family attempting to survive in an active war zone by hiding in a basement during bombing outside their home. The parents fabricate a story about a giant to tell to their six-year old daughter and says he wants to play with her, creating a parallel between the footsteps outside and the loud explosions (similar to the story of Life is Beautiful, one of my favorite movies, in which the father tells his son that they are in a competition to win a tank instead of WWII).


(Giant VR experience still.)

Zec states that it was difficult to create this film in that many technical aspects of the project had not been tackled previously, requiring technology that had not been fully developed yet. The process also included live-action actors (instead of computer renders) with depth data and three-dimensional environments inside a video-game engine. Combining reality with technology was a challenge, but she wanted to create an emotional impact, making the viewer feel trapped in this dangerous and frightening situation. Virtual reality possesses the power to do so, and it amazes and excites me at how much potential (whether scary or not) this type of technology has.

Romi Jin – Looking Outwards 09

For this week’s looking outwards post, I looked at Ying’s looking outward-05. She is my architecture mentee and posts a lot about interesting architecture projects. What especially intrigued me was this post about a three-dimensional rendering project called Somerset Isle by Tomer Meltser. It is fascinating to see how much is put into this rendered landscape:


Sample image of the rendered landscape.

Architecture set placed in the rendering.

Foliage set used throughout the rendering.

One day I’d love to do something like this; it seems like so much fun to create and to see the final outcome come together so beautifully created like Meltser’s final rendering video. This makes me think of how far an architect can take their drawings and ideas — into a realistic three-dimensional journey that displays in depth details of each plant, landscape element, building, objects, etc.

Romi Jin – Project-09-Portrait

sketch

/*
Romi Jin
Section B
rsjin@andrew.cmu.edu
Project-09
*/

var img;

function preload() {

    var imgur = "https://i.imgur.com/tbSmZ90.jpg";
    img = loadImage(imgur);
}

function setup() {

    createCanvas(360, 479); //resize image in photoshop
    background(255, 225, 225);
    imageMode(CENTER);
    frameRate(500); //speed that pixels are drawn 
    img.loadPixels();
    noStroke();

}

function draw() {

    var x = constrain(floor(random(width)), 0, width); //constrains random x values of pixels
    var y = constrain(floor(random(height)), 0, height); //constrains random y values of pixels

    var rgb = img.get(x, y); //extracts colors from image pixels

    fill(rgb);
    ellipse(x, y, 7); //circles drawing the image

}

For this project, I used an image of my best friend from home, Mina! It was a lot easier than I expected! From just a few lines of code, you can produce such a cool animated image! I am excited to try this out with different images and shapes in the future.

Romi Jin – Project-07-Curves

sketch

/*
Romi Jin
Section B
rsjin@andrew.cmu.edu
Project-07
*/

var x;

function setup() {
    createCanvas(480, 480);
    
}

function draw() {
    
    background(174, 198, 207);

    x = constrain(mouseX, 0, width);
    y = constrain(mouseY, 0, height);
    
    //three intersecting hypotrochoids

    push();
    translate(width/2, height/2);
    drawHypotrochoid();
    pop();

    push();
    translate(width/3, height/3);
    drawHypotrochoid();
    pop();

    push();
    translate(width-width/3, height-width/3);
    drawHypotrochoid();
    pop();

}

function drawHypotrochoid() {

    //link: http://mathworld.wolfram.com/Hypotrochoid.html
    //roulette by drawing along two cirles (radius a and b below)

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

        a = map(y, 0, height, 100, 200); 
        b = map(x, 0, width, 0, 75); 
        h = 100;

        x = (a - b) * cos(i) + h*cos(((a-b)/b) * i);
        y = (a - b) * sin(i) - h*sin(((a-b)/b) * i);

        noFill();
        stroke(255);
        strokeWeight(1);
        ellipse(0, 0, x, y);

    }

}

For this project, I chose the shape hypotrochoid and drew it three times to create three intersecting hypotrochoids. The parameters are the mouse X and mouse Y position, and the mouse X changes one ellipse’s radius while mouse Y changes the other. It is intriguing to watch the three intersect as they create even more curves together.