/* Name : Jonathon Liang / Curran Zhang
AndrewID : Jliang2 / Curranz
Section : Section A
Final Project
*/
var terrainSpeed1 = 0.0002;
var terrainDetail1 = 0.015;
var terrainSpeed2 = 0.0004;
var terrainDetail2 = 0.008;
var clouds = [];
var star = [];
var frames = [];
var HeadX = 260;
var HeadY = 325;
var ReflectionY =385
var step= 6;
var machox = 480;
var machoy = 300;
var girlx = 480;
var girly = 340;
var nekx = 480;
var neky = 240;
var towelx = 480;
var towely = 200;
var birdiex = 480;
var birdiey = 300;
function setup() {
createCanvas(480, 480);
//Iniate Clouds
for (var i = 0; i <5; i++) {
var r = random(width);
clouds[i] = makeClouds(r);
}
//Head Image Position
imageMode(CENTER);
frameRate(15);
}
function preload(){
//Cats
cat1 = loadImage("https://i.imgur.com/7hCkrYr.png");
cat2 = loadImage("https://i.imgur.com/TWXWeM0.png");
cat3 = loadImage("https://i.imgur.com/kRxHYt0.png");
cat4 = loadImage("https://i.imgur.com/kkpAzvD.png");
cat5 = loadImage("https://i.imgur.com/Hf9rTYl.png");
birdie = loadImage("https://i.imgur.com/RdcS35J.png");
//Head
var filenames = [];
filenames[0] = "https://i.imgur.com/leN6UXu.png";
filenames[1] = "https://i.imgur.com/dydccNf.png";
filenames[2] = "https://i.imgur.com/dcoiGqR.png";
filenames[3] = "https://i.imgur.com/wez5P2S.png";
filenames[4] = "https://i.imgur.com/9etlno8.png";
filenames[5] = "https://i.imgur.com/yrjv4XT.png";
filenames[6] = "https://i.imgur.com/hW3gKH6.png";
filenames[7] = "https://i.imgur.com/Jg0yJck.png";
filenames[8] = "https://i.imgur.com/dU1rruI.png";
for (var i = 0; i < filenames.length; i++) {
frames.push(loadImage(filenames[i]));
}
}
function draw() {
//Gradient Background
var from = color(250,0,0);
var to = color(270);
gradient(0,width,from,to);
rect(0,0,480,480);
makeMountain1();
makeMoon();
makeStar();
makeMountain1();
makeMountain2();
makeReflection();
updateClouds();
removeClouds();
addClouds();
strokeWeight(.5);
stroke(255);
text("early head gets the bird", 10, 15);
text("touch a cat, you'll be sad", 10, 30);
text("fly too high, and you'll die", 10, 45);
makeHead();
makeCat();
}
function gradient(y,w,from,to){
for (var i = y; i <= height; i++) {
var inter = map(i,y,y+w,0,1);
var col = lerpColor(from,to,inter);
stroke(col);
strokeWeight(2);
line(y,i,y+w,i);
}
}
function makeStar(){
fill(270);
for (var i = 0; i < 100; i++) {
var starX = random(width);
var starY = random(height);
ellipse(starX,starY,1,1);
}
}
function makeMountain1(){
noStroke();
fill(180,0,0);
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail1) + (millis() * terrainSpeed1);
var y = map(noise(t), 0,1.8, height/8, height);
vertex(x, y);
}
vertex(width,height);
vertex(0,height);
endShape();
}
function makeMountain2(){
fill(139,0,0);
noStroke();
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail2) + (millis() * terrainSpeed2);
var y = map(noise(t), 0,2, height/2, height);
vertex(x, y);
}
vertex(width,height);
vertex(0,height);
endShape();
}
function makeReflection(){
fill(220,50,50);
rect(0, 375, width, 105);
fill(255,60,60);
noStroke();
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail2) + (millis() * terrainSpeed2);
var y = map(noise(t), 0,2, height, height*.5);
vertex(x, y);
}
vertex(width,height);
vertex(0,height);
endShape();
}
function makeMoon(){
noStroke();
fill(255,20);
ellipse(2*width/3,height/4,170,170);
ellipse(2*width/3,height/4,160,160);
ellipse(2*width/3,height/4,150,150);
ellipse(2*width/3,height/4,140,140);
fill(255,200);
ellipse(2*width/3,height/4,120,120);
}
function updateClouds(){
for (var i = 0; i < clouds.length; i++) {
clouds[i].move();
clouds[i].display();
}
}
function removeClouds(){
var keepClouds = [];
for (var i = 0; i < clouds.length; i++) {
if (clouds[i].x + clouds[i].breadth > 0) {
keepClouds.push(clouds[i]);
}
}
clouds= keepClouds;
}
function addClouds(){
var newCloud = .007;
if (random(0,1)<newCloud) {
clouds.push(makeClouds(width))
}
}
function cloudMove(){
this.x += this.speed;
}
function displayClouds(){
fill(255,50);
noStroke();
ellipse(this.x,this.y,this.width,this.height);
ellipse(this.x +10,this.y +10,this.width-10,this.height-10);
ellipse(this.x +20,this.y -10,this.width/2,this.height/2);
ellipse(this.x -20,this.y ,this.width-20,this.height-10);
}
function makeClouds(cloudy){
var cloud= {x: cloudy,
y:random(100, height/2),
speed: random(-.2,-.7),
width: random(50,100),
height:random(20,0),
breadth:50,
move:cloudMove,
display:displayClouds
}
return cloud;
}
function makeHead(){
//Main Head
push();
translate(HeadX,HeadY);
scale(.2,.2);
image(frames[frameCount % 8], 0, 0);
pop();
//Reflection
push();
translate(HeadX,ReflectionY);
scale(.2,-.2);
tint(255,127);
image(frames[frameCount % 8], 0, 0);
pop();
if (keyIsDown(ENTER)){
HeadY -= step;
ReflectionY += step;
} else { HeadY += step;
HeadY = min(HeadY, 350);
ReflectionY -= step;
ReflectionY = max(ReflectionY,405);
}
if (HeadY <= 100) {gameOver()};
}
function makeCat(){
//MachoCat
push();
translate(machox,machoy);
scale(.2,.2);
image(cat1, 0,0);
machox-=1.25;
if (machox < 0) {lmachox = 480};
pop();
if (HeadX + 30 > machox & HeadX-30 < machox && machoy > HeadY && HeadY > machoy - 30) {
gameOver()};
//MachoCat Reflection
push();
translate(machox,419);
scale(.2,-.2);
tint(265,160);
image(cat1, 0,0);
machox-=1.25;
if (machox < 0) {machox = 480};
pop();
//School Girl
push();
translate(girlx,girly);
scale(.18,.18);
image(cat3, 0,0);
girlx-=.8;
if (girlx < 0) {girlx = 480};
pop();
if (HeadX + 30 > girlx & HeadX-30 < girlx && girly > HeadY && HeadY > girly - 30) {
gameOver();}
//School Girl Reflection
push();
translate(girlx,409);
scale(.18,-.18);
tint(265,160);
image(cat3, 0,0);
girlx-=.8;
if (girlx < 0) {girlx = 480};
pop();
//Neka
push();
translate(nekx,neky);
scale(.6,.6);
image(cat4, 0,0);
nekx-=.5;
if (nekx < 0) {nekx= 480};
pop();
if (HeadX + 30 > nekx & HeadX-30 < nekx && neky + 40 > HeadY && HeadY > neky - 10) {
gameOver()};
//Neka Reflection
push();
translate(nekx,509);
scale(.6,-.6);
tint(265,160);
image(cat4, 0,0);
nekx-=.5;
if (nekx < 0) {nekx = 480};
pop();
//Towel
push();
translate(towelx,towely);
scale(.15,.15);
image(cat5, 0,0);
towelx-=5.05;
if (towelx < 0) {towelx = 480};
pop();
if (HeadX + 30 > towelx & HeadX-30 < towelx && towely > HeadY && HeadY > towely - 30) {
gameOver()};
//Birdie
push();
translate(birdiex,birdiey);
scale(-.15,.15);
image(birdie, 0,0);
birdiex-=5.05;
if (birdiex < 0) {birdiex = 480};
if (birdiey+30 > HeadY & HeadY> birdiey-30 && HeadX+30 > birdiex && HeadX-30 < birdiex) {
birdiex=480};
pop();
}
function gameOver() {
fill(0);
textSize(75);
textAlign(CENTER);
textStyle(BOLD);
text("GAME OVER", 240, 240);
noLoop();
}
It all starts with an idea, but you can never tell where an idea can end up. Because ideas spread, they change, they grow, they connect us with the world. And in a fast-moving world, where good news moves at the speed of time and bad news isn’t always what is seems. Because when push comes to shove, we all deserve a second chance, to score.
For our Final Project Curran and I wanted to create a game that closely resembled our favorite mobile app game Battle Cats. But in our game we made it so that our protagonist cannot touch any of the white cats and has to try to eat the red chicken. The instructions are as followed: eat the chicken, avoid the white cats, and don’t fly too high; otherwise the game is over. Press enter to make the face move up.
Hope y’all enjoy.
]]>For the final project I kinda of want to blend a character animation with a game. I’ve always wanted to draw to animate a custom drawn character and implement it into an interactive environment. I am still not sure what exactly I want to create yet, but I hope that the sketch below gives y’all a good idea of what I kinda what to do. I don’t think I will be collaborating with any other student for this project.
Two projects that I have been inspired by for my final project are Shanshui DaDA and the IOS game Battle Cats by PONOS. Many of my projects thus far this semester have involved drawing stuff onto the canvas, and Shanshui DaDA is taking that concept and putting in on steroids. This AI program allows any ordinary civilian (no matter how talented they are at drawing) to draw lines on an iPad and then it transforms their creation into a beautiful Chinese landscape painting.
Battle cats inspires me because I always wanted to try making an animated game of some sorts. After project 10 and the walking man assignment, I’ve really been interested in trying to animate some characters I created into p5js.
http://battle-cats.wikia.com/wiki/Main_Page
]]>
//Jonathan Liang
//jliang2
//Section A
//draw lines on people haha
var t1;
var underlyingImage;
var longboy = -1;
function preload() {
var myImageURL = "https://i.imgur.com/UveUHg1l.jpg";
underlyingImage = loadImage(myImageURL); //load picture
}
function setup() {
background(255);
createCanvas(350, 480);
image(underlyingImage, 0, 0);
underlyingImage.loadPixels();
t1 = makeTurtle(width/2, height/2);
frameRate(35);
}
function draw() {
if (longboy == 1) {
t1.goto(mouseX, mouseY);
t1.penDown();
followTheMouse();
}
if (longboy == -1) {
t1.penUp();
// t1.goto(mouseX, mouseY);
}
}
function followTheMouse() {
t1.setColor('black');
t1.setWeight(3);
t1.forward(2);
t1.turnToward(mouseX, mouseY, 10);
}
function mousePressed() {
longboy *= -1;
}
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;
}
It all starts with an idea, but you can never tell where an idea can end up. Because ideas spread, they change, they grow, they connect us with the world. And in a fast-moving world, where good news moves at the speed of time and bad news isn’t always what is seems. Because when push comes to shove, we all deserve a second chance, to score. A simple picture of an ordinary boy can be transformed. Ordinary boy can become the incredible hulk, thanks to turtles.
Adrien Kaeser’s Weather Thingy is a custom built sounds controller that modifies the sounds produced by musical instruments based on real-time climate settings. Weather Thingy is composed of two parts: a weather station on a tripod microphone and a custom built controller connected to a weather station. The station has climate sensors like a rain gauge, a wind vane, and a anemometer that assign various parameters received to audio effects. The main goal of Adrien’s work is to offer a new perspective to a replayability of a song. Since the same song with change based on the surrounding climate, it offers an unique experience each time the song is heard.
]]>
//Jonathan Liang
//jliang2
//section A
var buildings = [];
var lamppost = [];
var tDetail = 0.01;
var tSpeed = 0.0004;
var frames = []; // An array to store the images
var x = 0; //variable to draw image from array
var rexX; // The X location of the character
var rexY; // The Y location of the character
var exampleImgOnly;
function preload() {
var filenames = [];
filenames[0] = "https://i.imgur.com/pUQqpVN.png";
filenames[1] = "https://i.imgur.com/075wwQz.png";
filenames[2] = "https://i.imgur.com/8aFEl6F.png";
for (var i = 0; i < filenames.length; i++) {
frames[i] = loadImage(filenames[i]);
}
exampleImgOnly = loadImage("https://i.imgur.com/pUQqpVN.png");
}
function setup() {
createCanvas(480, 400);
//initial buildings
for (var i = 0; i < 11; i++) {
var ranx = random(width);
buildings[i] = makeBuilding(ranx);
}
rexX = 150;
rexY = 215;
frameRate(10);
}
function draw() {
background(255);
//generate line paper
for(var y = 0; y < height; y += 10) {
stroke(200);
noFill();
line(0, y, width, y);
}
displayHorizon();
makeMountain();
//draw objects
//buildings
updateAndDisplayBuildings();
removeBuildings();
addNewBuilding();
//trex
image(frames[x], rexX, rexY, 150, 150);
x += 1;
if (x > 2) {
x = 0;
}
}
function makeMountain() {
//generates terrain
stroke(0);
strokeWeight(2);
noFill();
beginShape();
for (var x1 = 0; x1 < width; x1++) {
var t1 = (x1 * tDetail) + (millis() * tSpeed);
var y1 = map(noise(t1), 0, 1, 0, height);
vertex(x1, y1 - 20);
}
vertex(width, height);
vertex(0, height);
endShape();
}
function updateAndDisplayBuildings() {
//update and display building position
for (var i = 0; i < buildings.length; i++) {
buildings[i].move();
buildings[i].display();
}
}
function removeBuildings() {
//remove buildings that have gone out of view
var keepBuildings = [];
for (var i = 0; i < buildings.length; i++) {
if (buildings[i].x + buildings[i].breadth > 0) {
keepBuildings.push(buildings[i]);
}
}
buildings = keepBuildings //remember remaining buildings
}
function addNewBuilding() {
//with very little probability, add new building
var newBuildingLikelihood = 0.02;
if (random(0, 1) < newBuildingLikelihood) {
buildings.push(makeBuilding(width));
}
}
// method to update position of building every frame
function buildingMove() {
this.x += this.speed;
}
//drawing building and windows
function buildingDisplay() {
//building
var floorHeight = 20;
var bHeight = this.nFloors * floorHeight;
noFill();
strokeWeight(2);
stroke(0);
push();
translate(this.x, height - 50);
rect(0, -bHeight, this.breadth, bHeight);
//windows
var wGap = this.breadth / 16;
var xW = this.breadth / 16;
for (var w = 0; w < 5; w++) {
for (var i = 0; i < this.nFloors; i++) {
fill('yellow');
strokeWeight(1);
stroke(0);
rect(xW, -15 - (i * floorHeight), wGap * 2, 10);
}
xW += wGap * 3;
}
pop();
}
function makeBuilding(birthLocationX) {
var bldg = {x: birthLocationX,
breadth: 50,
speed: -5.0,
nFloors: round(random(3, 12)),
move: buildingMove,
display: buildingDisplay}
return bldg;
}
//draw the ground
function displayHorizon() {
stroke(0);
strokeWeight(4);
noFill();
line(0, height - 50, width, height - 50);
}
It all starts with an idea, but you can never tell where an idea can end up. Because ideas spread, they change, they grow, they connect us with the world. And in a fast-moving world, where good news moves at the speed of time and bad news isn’t always what is seems. Because when push comes to shove, we all deserve a second chance, to score.
My project is heavily based on doodles I used to do throughout my elementary to high school days. I used to like to draw mountains, buildings, tanks, aliens, and dinosaurs blowing up stuff. I chose to add lines to the background to reflect that lined paper quality and made everything noFill to show that it was just a pen doodle.
]]>Notes on Blindness is a short film by Peter Middleton and James Spinney. The film documents the life of a blind man called John Hull, and uses virtual reality and gameplay mechanics to recreate John’s cognitive and emotional memories. The genius behind the virtual reality component is French artist and art director Béatrice Lartigue. Lartigue is primarily known for her interactive installations and currently works in the interdisciplinary collaborative Lab212. She has won many awards, including the Google International Art Prize, Tribeca Film Festival Storyscapes Award, the Lumen Prize, as well as the Sundance Film Festival.
Notes on Blindness is definitely something to check out: http://epure.it/notes-on-blindness
More of her interesting work can be found on her website:
]]>
//Jonathan Liang
//jliang2
//section A
var springy = 0.7; // how much velocity is retained after bounce
var np = 50; // how many particles
var underlyingImage;
function preload() {
var myImageURL = "https://i.imgur.com/obcoL1tl.jpg";
underlyingImage = loadImage(myImageURL);
}
function particleStep() {
var ix = constrain(floor(this.x), 0, width-1);
var iy = constrain(floor(this.y), 0, height-1);
var theColorAtLocationXY = underlyingImage.get(ix, iy);
noStroke();
fill(theColorAtLocationXY)
ellipse(this.x, this.y, 5);
this.x += this.dx;
this.y += this.dy;
if (this.x > width) { // bounce off right wall
this.x = width - (this.x - width);
this.dx = -this.dx * springy;
} else if (this.x < 0) { // bounce off left wall
this.x = -this.x;
this.dx = -this.dx * springy;
}
if (this.y > height) { // bounce off bottom
this.y = height - (this.y - height);
this.dy = -this.dy * springy;
} else if (this.y < 0) { // bounce off top
this.y = -this.y;
this.dy = -this.dy * springy;
}
}
// create a "Particle" object with position and velocity
function makeParticle(px, py, pdx, pdy) {
p = {x: px, y: py,
dx: pdx, dy: pdy,
step: particleStep,
}
return p;
}
var particles = [];
var randx = [];
var randy = [];
function setup() {
createCanvas(380, 480);
background(0);
underlyingImage.loadPixels();
for (i = 0; i < np; i++) {
randx[i] = random(-50, 50);
randy[i] = random(-50, 50);
}
frameRate(5);
}
// draw all particles in the particles array
//
function draw() {
background(230);
for (var i = 0; i < np; i++) {
// make a particle
var p = makeParticle(200, 350,
randx[i], randy[i]);
// push the particle onto particles array
particles.push(p);
}
for (var i = 0; i < particles.length; i++) { // for each particle
var p = particles[i];
p.step();
}
}
I chose a picture of my friend from high school. I wanted the ellipses that generated the image to first start from his mouth and then bounce everywhere to generate the image. Kind of like vomiting, but with a more artistic result. The ellipses slow down after they hit the walls so that it is clearer that they are bouncing and not just randomly generating wherever they want. Below is a few screenshots of the image being generated over time.
Coral Cities is a project by Craig Taylor that visualizes cities in a unique way. Cities are usually mapped by their buildings, streets, and popular nodes; however, Taylor wanted to show how liveable a city is. He used raw data (such as crime rate, education, political stability, traffic, etc.) to generate a geo-spatial analysis of cities today, visualized as these coral structures.
This post by fellow architecture student Curran Zhang really stood out to me because of the emphasis in our field for mapping. We have been taught to try to find unique ways to map raw data, and Craig Taylor’s Coral Cities really offers a unique representation that could be interpreted in many different ways.
https://towardsdatascience.com/coral-cities-an-ito-design-lab-concept-c01a3f4a2722
]]>The work above is called Prismverse by Hong Kong media artist Chris Cheung. Chris is an artist who tries to integrate his artistic practice with his background in Chinese Philosophy. His work have common themes of integrating the traditional and the futuristic ideas as well as the aesthetics of technological intervention. Chris is currently the founder of an interdisciplinary creative studio called XEX, based in Hong Kong. Their work has been displayed all over Asia.
My personal favorite work of his is Prismverse. Prismverse is an installation that tries to immerse the viewer in infinity through sight and sound. Chris and XEX hoped that the diamond mirrors in the space would give the viewer a sense of the universe populated by infinite stars, and the omnidirectional speakers will present an ambient soundscape that immerses the viewer from all directions.
]]>