For this final project, I wanted to create a drawing program for users. I wanted to create a platform that inspired users to be creative for themselves. In 2020, practicing my creative interest was a great way for me to keep my mind off of the current social climate, and focus on something that I enjoyed doing – I wanted others to experience that. It is a simple program, but it works, and it is enjoyable. Just run the program, and start drawing!
If I had more time, I would have added stroke features and visuals that effectively guide the user through choosing color and stroke. And perhaps a randomly generating image relating to 2020 asking users to copy the image.
var strokeColor;
var hover;
function setup() {
createCanvas(600, 600);
strokeColor = color(0);
}
function draw() {
noStroke();
fill(0);
//borders
rect(0, 0, width, 80);
rect(0, height - 20, width, 50);
rect(0, 0, 20, height);
rect(width - 20, 0, 20, height);
//text color
fill(255);
textSize(10);
text("Press the circle button to change the color", 20, 55);
text("Press Q to clear canvas", 20, 70);
//title
strokeWeight(5);
textSize(15);
text("Draw your favorite moment from 2020!", 20, 30);
stroke(strokeColor);
//calculating distance between mouse and circle
var distance = dist(mouseX, mouseY, 540, 120);
//making sure disatnce is less than circle's radius
if(distance < 15) {
hover = true;
} else {
hover = false;
}
push();
//draw a circle
ellipseMode(CENTER);
ellipse(540, 120, 30, 30);
pop();
//testing is mouse is over the circle
if(hover == true) {
fill(200);
cursor(HAND);
} else {
fill(255);
cursor(ARROW);
}
}
function mousePressed() {
//changing color when button is pressed
if(hover == true) {
strokeColor = color(random(255), random(255), random(255));
}
}
function mouseDragged() {
//creating the brush tool
strokeWeight(8);
stroke(strokeColor);
line(mouseX, mouseY, pmouseX, pmouseY);
}
function keyPressed() {
//clearing canvas
if(key == 'q' || key == 'Q') {
clear();
}
}
For this project, I wanted to create a simple winter landscape, because Christmas is coming and it’s quite exciting. Take a close look at this landscape and close your eyes and imagine that you are Santa Claus on a nice warm sled on your way to California.
I used the noise function to generate the mountains, and objects to create snowflakes and buildings.
var buildings = [];
var mountains = [];
var noiseParam = 0;
var noiseStep = 0.03;
let snowflakes = [];
function setup() {
createCanvas(400, 240);
for(var i = 0; i < width/5; i++){
var n = noise(noiseParam);
mountains[i];
var value = map(n, 0, 1, 0, height);
mountains.push(value);
noiseParam += noiseStep;
}
// create an initial collection of buildings
for (var i = 0; i < 10; i++){
var rx = random(width);
buildings[i] = makeBuilding(rx);
}
frameRate(25);
}
function draw() {
background(23, 39, 174);
noStroke();
fill(187, 223, 250);
ellipse(200, 70, 70);
fill(255, 30);
cloud(40, 47, 1);
cloud(275, 15, 0.8);
cloud(380, 70, 1.5);
let t = frameCount / 20; // update time
// create a random number of snowflakes each frame
for (let i = 0; i < random(5); i++) {
snowflakes.push(new snowflake()); // append snowflake object
}
// loop through snowflakes with a for..of loop
for (let flake of snowflakes) {
flake.update(t); // update snowflake position
flake.display(); // draw snowflake
}
}
// snowflake class
function snowflake() {
// initialize coordinates
this.posX = 0;
this.posY = random(-50, 0);
this.initialangle = random(0, 2 * PI);
this.size = random(2, 5);
// radius of snowflake spiral
// chosen so the snowflakes are uniformly spread out in area
this.radius = sqrt(random(pow(width / 2, 2)));
this.update = function(time) {
// x position follows a circle
let w = 0.6; // angular speed
let angle = w * time + this.initialangle;
this.posX = width / 2 + this.radius * sin(angle);
// different size snowflakes fall at slightly different y speeds
this.posY += pow(this.size, 0.5);
// delete snowflake if past end of screen
if (this.posY > height) {
let index = snowflakes.indexOf(this);
snowflakes.splice(index, 1);
}
};
this.display = function() {
ellipse(this.posX, this.posY, this.size);
};
//for animating the mountains
mountains.shift();
var n = noise(noiseParam);
var value = map(n, 0, 1, 0, height);
mountains.push(value);
noiseParam += noiseStep;
//for mountains
beginShape();
for(var i = 0; i < width/5; i++){
//filling the mountain with color
fill(44, 67, 184);
noStroke();
//vertex funciton to fill the mountain
vertex((i * 5), mountains[i]);
vertex((i + 1) * 5, mountains[i + 1]);
vertex(width/2, 10000000);
}
endShape(CLOSE);
displayHorizon();
updateAndDisplayBuildings();
removeBuildingsThatHaveSlippedOutOfView();
addNewBuildingsWithSomeRandomProbability();
}
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 > 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.007;
if (random(0,1) < newBuildingLikelihood) {
buildings.push(makeBuilding(width));
}
}
// method to update position of building every frame
function buildingMove() {
this.x += this.speed;
}
// draw the building and some windows
function buildingDisplay() {
var floorHeight = 20;
var bHeight = this.nFloors * floorHeight;
fill(105, 135, 213);
noStroke();
push();
translate(this.x, height - 40);
rect(0, -bHeight, this.breadth, bHeight);
fill(151, 186, 236);
for (var i = 0; i < this.nFloors; i++) {
rect(5, -15 - (i * floorHeight), this.breadth - 10, 3);
}
pop();
}
function makeBuilding(birthLocationX) {
var bldg = {x: birthLocationX,
breadth: 50,
speed: -3.0,
nFloors: round(random(2,8)),
move: buildingMove,
display: buildingDisplay}
return bldg;
}
function displayHorizon(){
fill(68, 91, 193);
rect(0, height-50, width, height-50);
}
function cloud(x, y, size) {
fill(68, 91, 193);
noStroke();
arc(x, y, 25 * size, 20 * size, PI + TWO_PI, TWO_PI);
arc(x + 10, y, 25 * size, 45 * size, PI + TWO_PI, TWO_PI);
arc(x + 25, y, 25 * size, 35 * size, PI + TWO_PI, TWO_PI);
arc(x + 40, y, 30 * size, 20 * size, PI + TWO_PI, TWO_PI);
}
Lorna Barnshaw
For this Looking Outwards post, I will be talking about Lorna Barnshaw’s project called Reality Reduction (2013). Lorna Barnshaw is a 3D designer from London, United Kingdom, with a bachelor’s degree of Fine Arts from Winchester School Of Art. She works as a freelance designer, creating 3D designs during her free time. Her project, Reality Reduction consists of random people 3D scanned in 360 views and using computation to reduce their features to low-poly shapes. She simplifies the person’s features and pixels to visualize what a person may look like after reduction. This project is really interesting to me because it uses advanced technology to effectively communicate her concept. It is both eerie and interesting at the same time, captivating the viewer by its realistic scans.
View her portfolio here
]]>For my project, I created a story of Santa Clause delivering presents and running into a penguin. Now that Halloween is over, it is Christmas time.
I used Illustrator to create vector drawings correlating to the canvas size.
//general story
//Santa Clause was delivering presents when he ran into a penguin
let snowflakes = [];
function setup() {
createCanvas(400, 200);
useSound();
}
function soundSetup() {
osc = new p5.Oscillator();
osc.amp(0.25);
osc.setType('square');
osc.start();
}
// Frequencies in Hz for each of the white and black keys, left to right
var white_freqs = [261.625, 293.665, 329.63, 349.23, 392, 440, 493.88, 523.25];
var black_freqs = [277, 311, 0, 370, 415, 466]; // index 2 not used
function draw() {
background(0, 0, 68);
noStroke();
fill(230, 249, 255);
rect(0, 180, 400, 200);
penguin();
tree();
santa();
elf();
present();
let t = frameCount / 60; // update time
// create a random number of snowflakes each frame
for (let i = 0; i < random(5); i++) {
snowflakes.push(new snowflake()); // append snowflake object
}
// loop through snowflakes with a for..of loop
for (let flake of snowflakes) {
flake.update(t); // update snowflake position
flake.display(); // draw snowflake
}
}
// snowflake class
function snowflake() {
// initialize coordinates
this.posX = 0;
this.posY = random(-50, 0);
this.initialangle = random(0, 2 * PI);
this.size = random(2, 5);
// radius of snowflake spiral
// chosen so the snowflakes are uniformly spread out in area
this.radius = sqrt(random(pow(width / 2, 2)));
this.update = function(time) {
// x position follows a circle
let w = 0.6; // angular speed
let angle = w * time + this.initialangle;
this.posX = width / 2 + this.radius * sin(angle);
// different size snowflakes fall at slightly different y speeds
this.posY += pow(this.size, 0.5);
// delete snowflake if past end of screen
if (this.posY > height) {
let index = snowflakes.indexOf(this);
snowflakes.splice(index, 1);
}
};
this.display = function() {
ellipse(this.posX, this.posY, this.size);
};
}
function mousePressed() {
if(mouseY >= 0 & mouseY < 200 && mouseX >= 25 && mouseX < 325) {
var keynum = constrain(floor((mouseX - 25) / 50), 0, 5);
if(keynum != 2) {
osc.start();
osc.freq(black_freqs[keynum]);
}
}
}
function penguin() {
push();
noStroke();
translate(0, 0);
fill(50);
rectMode(CENTER);
//face
ellipse(49.5, 90.5, 39, 39);
fill(20);
//wings
ellipse(35, 131.5, 8, 55);
//wings
ellipse(64, 131.5, 8, 55);
fill(50);
//body
rect(49.5, 142, 29, 82);
//belly
fill(255);
ellipse(50, 137.5, 16, 55);
fill(255, 255, 0);
//foot
ellipse(35.5, 182.5, 15, 9);
//foot
ellipse(64.5, 182.5, 15, 9);
fill(255, 255, 0);
//beak
ellipse(37, 90.5, 22, 3);
fill(255);
//eyes
ellipse(40.5, 83.5, 3, 3);
//eyes
ellipse(55.5, 83.5, 3, 3);
pop();
}
function tree() {
push();
noStroke();
translate(0, 0);
fill(210, 105, 30);
rectMode(CENTER);
rect(100, 162, 7, 43);
//triangle 1
fill(34, 139, 34);
beginShape();
vertex(100, 69.7388);
vertex(82.5, 130.5);
vertex(117.8899, 130.5);
endShape();
//triangle 2
beginShape();
vertex(100, 100.7388);
vertex(82.5, 161.5);
vertex(117.8899, 161.5);
endShape();
fill(255, 255, 0);
//star
ellipse(100, 71, 9 ,9);
pop();
}
function santa() {
push();
noStroke();
translate(0, 0);
//body
fill(255, 0, 0);
ellipse(200, 150.5, 44, 61);
fill(255);
ellipse(200, 70, 9, 9);
//face
fill(255, 230, 204);
ellipse(200.5, 110.5, 31, 31);
//hat
fill(255, 0, 0);
beginShape();
vertex(200.0522, 70);
vertex(187.2356, 101.5);
vertex(213.1543, 101.5);
endShape();
//boots
fill(0);
ellipse(189.5, 179.5, 15, 9);
ellipse(211.5, 179.5, 15, 9);
fill(255);
//buttons
ellipse(200, 135, 9, 9);
ellipse(200, 150, 9, 9);
ellipse(200, 165, 9, 9);
//eyes
fill(0);
ellipse(193, 110, 4, 4);
ellipse(209, 110, 4, 4);
pop();
}
function elf() {
push();
noStroke();
translate(0, 0);
rectMode(CENTER);
//arm
fill(0, 102, 0);
rect(242, 155.5, 7, 30);
rect(258, 155.5, 7, 30);
//body
fill(51, 153, 51);
rect(250, 159, 17, 43);
//face
fill(255, 230, 204);
ellipse(249.5, 130.5, 29, 29);
//ears
ellipse(234.5, 131, 3, 14);
ellipse(264.5, 131, 3, 14);
//shoes
fill(255, 0, 0);
ellipse(241.5, 181, 15, 6);
ellipse(258.5, 181, 15, 6);
//hat
beginShape();
vertex(249.0522, 94);
vertex(236.2356, 125.5);
vertex(263.1543, 125.5);
endShape();
//hat top
fill(255);
ellipse(249, 92, 9, 9);
//eyes
fill(0);
ellipse(243, 129, 4, 4);
ellipse(256, 129, 4, 4);
pop();
}
function present() {
push();
noStroke();
translate(0, 0);
rectMode(CENTER);
//present
fill(204, 0, 0);
rect(299.5, 166.5, 35, 35);
//ribbon
fill(255, 204, 0);
rect(299.5, 166.5, 5, 35);
rect(299.5, 166.5, 35, 3);
noFill();
strokeWeight(2);
stroke(255, 204, 0);
ellipse(295, 148, 10, 8);
ellipse(304, 148, 10, 8);
pop();
}
Nigel Stanford
For my Looking Outwards post, I will be talking about a sound visualization project done by Nigel Stanford. For his latest music video for Cymatics, Stanford decided to use various methods of visualizing sound through natural materials, demonstrating how sound waves affect different types of matter. He uses instruments and computation to effectively convert the sound to waves that can be demonstrated physically. I admire this project because the main focus was creating the visuals of sound: “I looked for interesting science experiments that showed how sound waves affect things, figured out what looked good, and then wrote the musical parts for each experiment” (Stanford). Not only is he using his creativity for his music, but also pushes himself to visualize sound, which allows for a whole new experience for the viewer.
View his portfolio here
View the video here
]]>Joris Laarman
For this looking outwards post, I took a look at Jubbies’ post on Generative Art regarding Joris Laarman’s Bone Chair. In reading her response to Laarman’s work, I agree with what she said – As a design student myself, I find meaning and great appreciation for beautiful things, but something that embodies both form and function. As stated in her post, Laarman uses algorithms to mimic the natural growth of bones and trees to create a chair that has the most minimal structure to support the human body. I found this very intriguing because this piece represents the patterns of nature through a physical object that we interact with on a daily basis, yet still considering the form and function of the said object. From afar, this piece may seem like a “cool” surface level chair but the process of discovery and learning is required thus appreciating the chair even more.
View original LO here
View portfolio here
]]>For this project, I wanted to create Van Gogh’s self portrait with the text “Van Gogh.” By using custom pixels, I was able to make words appear on the canvas in relation to the pixel color of the original image. Wait a little bit to view the full portrait!
let img;
function preload() {
//preloading the van gogh image
img = loadImage("https://i.imgur.com/wUgkJwF.jpg");
}
function setup() {
createCanvas(300, 400);
imageMode(CENTER);
background(0);
img.loadPixels();
}
function draw() {
//coverage of the words on the canvas
let randomWords = random(0, 400);
let randomWordstwo = random(0, 300);
//placement of words in relation to the image width and height
let x = floor(random(img.width));
let y = floor(random(img.height));
//pixel and text relationship
let pixel = img.get(x, y);
fill(pixel, 800);
textSize(5);
text('van gogh', x, y, randomWords, randomWordstwo);
}
Image Source: https://i.imgur.com/wUgkJwF.jpg
Meow Wolf
I watched the Vimeo video about Meow Wolf, where they talk about reasons why they succeeded, and the early history of Meow Wolf as an art collective. Meow Wolf is an arts and entertainment group based in Santa Fe, New Mexico. They established in 2008 as an art collective with a special emphasis on the DIY technological aspects of immersive art. I admire this group because of their work (obviously) but also their mission statement. They believe in accomplishing artists being compensated on an equal level with other skilled, in-demand professionals (a societal issue that is very prominent today) and that successful businesses must give back and participate in their communities. As an art collective, not only do they create mesmerizing user experiences, but also provide financial assistance, expertise, and other forms of active support. Meow Wolf captivates the audience by introducing their mission through anecdote and humor adding levity to the expo.
View Portfolio here
]]>By Stamen Design
Today, I will be talking about an AI Project called Penny done by Stamen Design. This simple tool is designed to help understand what wealth and poverty look like to a artificial intelligence built on machine learning using neural networks. Penny is built using income data from the U.S. Census Bureau, overlaid on DigitalGlobe satellite imagery. This information was then given to a neural network. Trained to predict the average household incomes in any area in the city using data from the census and the satellite. The AI looks for patterns in the imagery that correlate with the census data, and over time, users are able to ask the model what it thinks income levels are for a place just from a satellite image. This project is really interesting to me because this visualization and AI can be used to improve the quality of life, and physically see the imbalances within a neighborhood for better wealth distribution.
View project here
]]>For this project, I wanted to draw a single object but in different ways. I took the functions from the website provided in the project brief and decided to draw a heart by plugging in functions for “x” and “y” and using the “beginShape()” function. I first began by using a “for loop” to draw a circle by creating a local variable that adds in increments for every loop. By altering this variable, I was able to draw the heart in different ways.
Click to change colors:
function setup() {
createCanvas(400, 480);
background(220);
text("p5.js vers 0.9.0 test.", 10, 15);
}
function draw() {
background(0);
translate(width / 2, height / 2);
//heart one
push();
translate(-100, -130);
noFill();
strokeWeight(0.5);
stroke(255);
beginShape();
for(var a = 0; a < TWO_PI; a += 0.3) { //this function draws a circle before the equation is put in
if(mouseIsPressed){
stroke(random(255), random(255), random(255)); //color change
}
//drawing the first heart
var r = constrain(mouseX / 180, 1, 70); //movement of mouse
var x = r * 16 * pow(sin(a), 3);
var y = -r * (13 * cos(a) - (5 * cos(2 * a)) - 2 * cos(3 * a) - cos(4 * a));
vertex(x, y);
//drawning the second heart
var b = r/2 * 16 * pow(sin(a), 3);
var c = -r/2 * (13 * cos(a) - (5 * cos(2 * a)) - 2 * cos(3 * a) - cos(4 * a));
vertex(b, c);
}
endShape(CLOSE);
pop();
//heart two
push();
translate(100, -130);
noFill();
strokeWeight(0.5);
stroke(255);
beginShape();
for(var a = 0; a < TWO_PI; a += 0.2) {
if(mouseIsPressed){
stroke(random(255), random(255), random(255)); //color change
}
//drawing the first heart
var r = constrain(mouseX / 180, 1, 70); //movement of mouse
var x = r * 16 * pow(sin(a), 3);
var y = -r * (13 * cos(a) - (5 * cos(2 * a)) - 2 * cos(3 * a) - cos(4 * a));
vertex(x, y);
//drawing the second heart
var b = r/2 * 16 * pow(sin(a), 3);
var c = -r/2 * (13 * cos(a) - (5 * cos(2 * a)) - 2 * cos(3 * a) - cos(4 * a));
vertex(b, c);
}
endShape(CLOSE);
pop();
//heart three
push();
translate(-100, 0);
noFill();
strokeWeight(0.5);
stroke(255);
beginShape();
for(var a = 0; a < TWO_PI; a += 0.1) {
if(mouseIsPressed){
stroke(random(255), random(255), random(255)); //color change
}
//drawing the first heart
var r = constrain(mouseX / 180, 1, 70);
var x = r * 16 * pow(sin(a), 3);
var y = -r * (13 * cos(a) - (5 * cos(2 * a)) - 2 * cos(3 * a) - cos(4 * a));
vertex(x, y);
//drawing the second heart
var b = r/2 * 16 * pow(sin(a), 3);
var c = -r/2 * (13 * cos(a) - (5 * cos(2 * a)) - 2 * cos(3 * a) - cos(4 * a));
vertex(b, c);
}
endShape(CLOSE);
pop();
//heart four
push();
translate(100, 0);
noFill();
strokeWeight(0.5);
stroke(255);
beginShape();
for(var a = 0; a < TWO_PI; a += 0.08) {
if(mouseIsPressed){
stroke(random(255), random(255), random(255)); //color change
}
//drawing the first heart
var r = constrain(mouseX / 180, 1, 70);
var x = r * 16 * pow(sin(a), 3);
var y = -r * (13 * cos(a) - (5 * cos(2 * a)) - 2 * cos(3 * a) - cos(4 * a));
vertex(x, y);
//drawing the second heart
var b = r/2 * 16 * pow(sin(a), 3);
var c = -r/2 * (13 * cos(a) - (5 * cos(2 * a)) - 2 * cos(3 * a) - cos(4 * a));
vertex(b, c);
}
endShape(CLOSE);
pop();
//heart five
push();
translate(-100, 130);
noFill();
strokeWeight(0.5);
stroke(255);
beginShape();
for(var a = 0; a < TWO_PI; a += 0.06) {
if(mouseIsPressed){
stroke(random(255), random(255), random(255)); //color change
}
//drawing the first heart
var r = constrain(mouseX / 180, 1, 70);
var x = r * 16 * pow(sin(a), 3);
var y = -r * (13 * cos(a) - (5 * cos(2 * a)) - 2 * cos(3 * a) - cos(4 * a));
vertex(x, y);
//drawing the second heart
var b = r/2 * 16 * pow(sin(a), 3);
var c = -r/2 * (13 * cos(a) - (5 * cos(2 * a)) - 2 * cos(3 * a) - cos(4 * a));
vertex(b, c);
}
endShape(CLOSE);
pop();
//heart six
push();
translate(100, 130);
noFill();
strokeWeight(0.5);
stroke(255);
beginShape();
for(var a = 0; a < TWO_PI; a += 0.04) {
if(mouseIsPressed){
stroke(random(255), random(255), random(255)); //color change
}
//drawing the first heart
var r = constrain(mouseX / 180, 1, 70);
var x = r * 16 * pow(sin(a), 3);
var y = -r * (13 * cos(a) - (5 * cos(2 * a)) - 2 * cos(3 * a) - cos(4 * a));
vertex(x, y);
//drawing the second heart
var b = r/2 * 16 * pow(sin(a), 3);
var c = -r/2 * (13 * cos(a) - (5 * cos(2 * a)) - 2 * cos(3 * a) - cos(4 * a));
vertex(b, c);
}
endShape(CLOSE);
pop();
}