The goal of my final project was to create some interactive project that is simple but playful. When working on this project I took it very incrementally, building on the previous versions and trying to add more elements or making the previous ones better. As I worked my way through the code, I got more comfortable and became more efficient with the way I wrote it. I enjoyed working this way because I found it a lot less intimidating. I really enjoyed making this project. I think if I wanted to I could continue to add on to this. I think a logical next step could be incorporating sound.
Note: I made the canvas size larger then what wordpress can handle because I liked the look of it being a larger area. Below is a zip file of the full size files. The one on wordpress is basically the same just with a few composition adjustments.
Instructions: just use the mouse to play around with the scene. Type into the input bar and hit enter to change the type displayed on the screen.
//Margot Gersing - Final project - mgersing@andrew.cmu.edu - Section E
//for blob shapes
//object one
var xOne;
var yOne;
var dOne;
var opaCityOne = 120;
var overOne = false;
//object two
var xTwo;
var yTwo;
var dTwo;
var opaCityTwo = 120;
var overTwo = false;
//object three
var xThree;
var yThree;
var dThree;
var opaCityThree = 110;
var overThree = false;
//object four
var xFour;
var yFour;
var dFour;
var opCityFour = 110;
var overFour = false;
//object five
var xFive;
var yFive;
var dFive;
var opCityFive = 110;
var overFive = false;
//snake -- code refrenced and modified from p5js examples
//https://p5js.org/examples/interaction-follow-3.html --- link to code refrenced
var snakeX = []; //arrays for snake
var snakeY = [];
var snakeJoint = 10; //amount of joints
var snakeLength = 10; //length between
for (let i = 0; i < snakeJoint; i++) { //loading the joints and lenght into to x and y arrays
snakeX[i] = 0;
snakeY[i] = 0;
}
//for "pong" letters on screen
var letterString = "hello!"; //starting string
var playArray = []; //store the objects (letters and their movements)
var d = [-1, 1]; //direction of array
var input; //for typing
function setup() {
createCanvas(800, 600);
noStroke();
//for type
textFont("Courier New"); //type style
textSize(60); //typesize
//for input bar
input = createInput(); //create the bar to type into
input.position(50, 20);
//for bouncing type, put string into array
for(var i = 0; i < letterString.length; i++){ //load array with objects
var x = map(i, 0, letterString.length, 100, width - 100); //map letters to begin
var vvx = random(1, 5) * d[round(random(0, 1))]; //random velocity in x direction
var vvy = random(1, 5) * d[round(random(0, 1))]; //random velocity in y direction
playArray[i] = createLetter(x, width/2, letterString.charAt(i), vvx, vvy) //call object
}
}
function draw() {
background(250, 120, 110);
//call blob shapes
thingOne();
thingTwo();
thingThree();
thingFour();
thingFive();
//for snake
stroke(87, 156, 128);
strokeWeight(10);
dragSnake(0, mouseX, mouseY); //make snake move with mouse
for (let i = 0; i < snakeX.length - 1; i++) { //create the moevment quality for the snake
dragSnake(i + 1, snakeX[i], snakeY[i]);
}
//get the letters to move around
noStroke();
fill("black");
for(var i = 0; i < playArray.length; i++){
var t = playArray[i];
if(dist(mouseX, mouseY, t.x, t.y) < 30){ //when mouse hovers over letter
t.vx = random(1, 5) * d[round(random(0, 1))]; //get new random velocity x
t.vy = random(1, 5) * d[round(random(0, 1))]; //get new random velocity x
}
if(t.x > width -30 || t.x < 30 || t.y > height - 30 || t.y < 30){ //when the letters hit the walls
t.vx = -t.vx; //reverse the direction
t.vy = -t.vy;
}
t.x = t.x + t.vx; //update the location of the letters
t.y = t.y + t.vy;
text(t.letter, t.x, t.y); //display it
}
}
function thingOne(){
//activation circle
xOne = 25; //location
yOne = 100;
dOne = 600; //diameter
// Test if the cursor is over the box
if(dist(mouseX, mouseY, xOne, yOne) < dOne / 2){ //if the mouse is over the activation ellipse -- var over one is true
overOne = true;
if (overOne == true) { //if true, then change value of opacity which chnages fill color of blob
opaCityOne = 200;
fill(250, opaCityOne, 110); //changing the fill
}
} else { //other wise go back to orignal color
if (opaCityOne >= 120) opaCityOne = opaCityOne - 3; //fades out
fill(250, opaCityOne, 110);
overOne = false;
}
drawOne();
}
function drawOne(){ //location and shape of blob in top left
noStroke();
ellipse(25, 100, 620, 700);
ellipse(50, 300, 450, 320);
}
function thingTwo(){ //same as function thingOne but for bottom right blob
xTwo = 650;
yTwo = 600;
dTwo = 500;
// Test if the cursor is over the box
if(dist(mouseX, mouseY, xTwo, yTwo) < dTwo / 2){
overTwo = true;
if (overTwo == true) {
opaCityTwo = 200;
fill(250, opaCityTwo, 110);
}
} else {
if (opaCityTwo >= 120) opaCityTwo = opaCityTwo - 5;
fill(250, opaCityTwo, 110);
overTwo = false;
}
drawTwo();
}
function drawTwo(){ //location and shape of blob in bottom right
noStroke();
ellipse(650, 600, 600, 500);
ellipse(800, 450, 400, 400);
}
function thingThree(){ //same as function thingOne but for top right blob
xThree = 700;
yThree = -20;
dThree = 500;
// Test if the cursor is over the box
if(dist(mouseX, mouseY, xThree, yThree) < dThree / 2){
overThree = true;
if (overThree == true) {
opaCityThree = 255;
fill(250, 120, opaCityThree);
}
} else {
if (opaCityThree >= 110) opaCityThree = opaCityThree - 3;
fill(250, 120, opaCityThree);
overThree = false;
}
drawThree();
}
function drawThree(){ //location and shape of blob in top right
noStroke();
ellipse(700, -20, 550, 300);
}
function thingFour(){ //same as function thingOne but for center blob
xFour = 475;
yFour = 225;
dFour = 200;
// Test if the cursor is over the box
if(dist(mouseX, mouseY, xFour, yFour) < dFour / 2){
overFour = true;
if (overFour == true) {
opCityFour = 255;
fill(250, 120, opCityFour);
}
} else {
if (opCityFour >= 110) opCityFour = opCityFour - 3;
fill(250, 120, opCityFour);
overFour = false;
}
drawFour();
}
function drawFour(){ //location and shape of blob in center
noStroke();
ellipse(475, 225, 225, 200);
}
function thingFive(){ //same as function thingOne but for bottom left
xFive = 150;
yFive = 600;
dFive = 200;
// Test if the cursor is over the box
if(dist(mouseX, mouseY, xFive, yFive) < dFive / 2){
overFive = true;
if (overFive == true) {
opCityFive = 255;
fill(250, 120, opCityFive);
}
} else {
if (opCityFive >= 110) opCityFive = opCityFive - 3;
fill(250, 120, opCityFive);
overFive = false;
}
drawFive();
}
function drawFive(){ //location and shape of blob in bottom left
noStroke();
ellipse(150, 600, 225, 200);
}
function dragSnake(i, xin, yin) { // for snake
const dx = xin - snakeX[i];
const dy = yin - snakeY[i];
const angle = atan2(dy, dx);
snakeX[i] = xin - cos(angle) * snakeLength;
snakeY[i] = yin - sin(angle) * snakeLength;
joint(snakeX[i], snakeY[i], angle);
}
function joint(x, y, a) { //for snake
push();
translate(x, y);
rotate(a);
line(0, 0, snakeLength, 0);
pop();
}
function createLetter(x, y, letter, vx, vy){ //object for each letter from the array, with loction, velocity
return{x: x, y: y, letter: letter, vx: vx, vy: vy}
}
function keyPressed(){ //when hit enter key call word function
if(keyCode == ENTER) word();
}
function word() { //for changing the letters on the screen
playArray = []; //empty array that holds letters from string
letterString = input.value(); //make the value of the input the new string (what you type)
//print(input.value());
//reload the newstring into the array
for(var i = 0; i < letterString.length; i++){ //load array with objects
var x = map(i, 0, letterString.length, 100, width - 100); //map letters to begin
var vvx = random(1, 5) * d[round(random(0, 1))]; //random velocity
var vvy = random(1, 5) * d[round(random(0, 1))];
playArray[i] = createLetter(x, width/2, letterString.charAt(i), vvx, vvy) //call object
}
}
]]>For my final project I want to create an interactive scene or compostion that the user can use to reveal things. I really want to incorporate the alphabet into the ‘environment’. I imagine this could act as a teaching tool that kids could play with and potentially help learn the alphabet.
In order to interact with the environment the mouse would the catalyst for things to happen (using a mouseX() and mouseY() a lot). I also want the environment to be very graphic and abstract. I don’t want to create a literal scene but more of a interactive composition.
I hope to incorporate simple animation for the scene and the different interactions like the revealing and how the letters move. Also I want there to be very simple sound, like when events occur (revealing letters) and maybe some basic ambient noise.
I am really inspired by Paul Rand and his playful simple imagery. I also feel like this visual style will lend itself well to my goal and p5.js.
When looking for projects that inspired me for my final project I came across a collection of projects called interactive haikus. This is a collection of very short interactive pieces. They are inspired by the short and concise mastering of haikus. This collection is curated by William Uricchio a professor of Comparative Media Studies at MIT and MIT game lab.
All 12 of the videos are really simple but fun and exciting. I want my final project to be a simple and playful. These projects also follow a loose narrative through the imagery and sound.
One haikus I really liked was Cat’s Cradle by Thibaut Duverneix, David Drury, Jean-Maxime Couillard and Stephane Poirier. It is a interactive constellation builder combined with a interactive musical instrument. I like how the user gets to control what is happening and create their own music/experience. It is also very intuitive and simple. The use of sound is also really effective here.
The other project that I was inspired by was called The Seasonal Stroller by Theo Le De Fuentes and Illustrated by Barbra Govin. This project simulates walking on a path and going on a little journey. Again, I love how simple and peaceful this project is. The is more of a narrative used in this piece. This project also has little hidden surprises throughout, which is something I want to incorporate in mine.
This week the female creator I decided to focus on is Yael Braha. She is a designer and creative director from Italy. She focuses a lot on large scale interactive projects and sculptures in her personal time. I was really inspired by her project Animal Race. This project was done for California Academy of Sciences in 2013.
This project is a very simple and effective data visualization. People can decided what animal they want to race and then in real time the race with a projected animation. The animation reflects the real speed of the animals so you can see if you are actually faster than a elephant for example. The data from the race is immediately displayed, stored and compared to all the other ‘runs’.
What I really like about this project is how it is so simple and so effective. She used Arduino, Processing, animation software, Resolume and electronics like a projector. It is so playful that people are drawn in and want to participate. It is also a teaching tool about data, data visualization and animals.
]]>//Margot Gersing - Project 11 - mgersing@andrew.cmu.edu - section E
var stars = [];
var terrainSpeedOne = 0.0002; //dark green moutain speed
var terrainSpeedTwo = 0.0004; // water speed
var terrainSpeedThree = 0.0006; // ligth green ground speed
var terrainDetailOne = 0.008; //green moutian
var terrainDetailTwo = 0.001; //water
var terrainDetailThree = 0.005; //light green moutain
function setup() {
createCanvas(480, 480);
frameRate(20);
//fills stars array
for (var i = 0; i < 75; i ++){
var strX = random(width);
var strY = random(0, height / 2);
stars[i] = makeStars(strX, strY);
}
}
function draw() {
background(214, 197, 204);
//moon
fill(169, 47, 35);
ellipse(375, 100, 150, 150);
displayStars(); //stars
moutainTwo(); //background moutians
water(); //water
moutainThree(); //foreground
}
function moutainTwo() {
noStroke();
fill(22, 56, 32); //darkgreen
beginShape();
for(var x = 0; x < width; x++){
var t = (x * terrainDetailOne) + (millis() * terrainSpeedOne);
var y = map(noise(t), 0, 1, 300, 250);
vertex(x, y);
}
vertex(width, height);
vertex(0, height);
endShape(CLOSE);
}
function water() {
noStroke();
fill(72, 90, 103); //blue
beginShape();
for(var x = 0; x < width; x++){
var t = (x * terrainDetailTwo) + (millis() * terrainSpeedTwo);
var y = map(noise(t), 0, 2, 400, 300);
vertex(x, y);
}
vertex(width, height);
vertex(0, height);
endShape(CLOSE);
}
function moutainThree() {
noStroke();
fill(110, 135, 84); //light green
beginShape();
for(var x = 0; x < width; x++){
var t = (x * terrainDetailThree) + (millis() * terrainSpeedThree);
var y = map(noise(t), 0, 2, 500, 300);
vertex(x, y);
}
vertex(width, height);
vertex(0, height);
endShape(CLOSE);
}
function drawStars(){ //what stars will look like
noStroke();
fill(201, 165, 180, 150);
push();
translate(this.x, this.y);
ellipse (1, 10, 5, 5);
pop();
}
function makeStars(strX, strY){ //stars object
var star = {x: strX,
y: strY,
speed: -1,
move: moveStars,
draw: drawStars}
return star;
}
function moveStars(){ //how stars move
this.x += this.speed;
if(this.x <= -10){
this.x += width;
}
}
function displayStars(){ //display stars
for(i = 0; i < stars.length; i++){
stars[i].move();
stars[i].draw();
}
}
For this project I decided to go with mountain landscapes. I had a good time messing with colors to create something a little different. I also generated stars in the sky. I decided to make the stars transparent so they were more subtle and you could see them pass over the moon. I also made the objects further back move slower so it would imitate what you see when you look out the window.
//Margot Gersing - Project 10 - mgersing@andrew.cmu.edu - Section E
var oneX = 50; //for mouse press
var oneY = 50;
var act1 = false; //peach shape 'activation'
var twoX = 200; //for mouse press
var twoY = 350;
var act2 = false; //rusty orange shape 'activation'
var threeX = 400; //for mouse press
var threeY = 100;
var act3 = false; //pink shape 'activation'
var fourX = 500; //for mouse press
var fourY = 500;
var act4 = false; //gray shape 'activation'
var nPoints = 100;
var blop;
var plop;
var vpop;
var ting;
function preload(){
blop = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/11/Blop.wav");
plop = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/11/plop.wav");
vpop = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/11/pop.wav");
ting = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/11/Ting.wav");
}
function setup() {
createCanvas(600,600);
frameRate(10);
}
function draw(){
background(29, 19, 46);
noStroke();
one();
four();
two();
three();
//filler shapes (static)
fill(192, 80, 49);
ellipse(50, 600, 400, 150);
fill(219, 160, 65);
ellipse(600, 125, 100, 150);
fill(114, 48, 35);
ellipse(150, 150, 25, 25);
ellipse(175, 175, 20, 20);
ellipse(135, 180, 25, 25);
ellipse(185, 135, 25, 25);
ellipse(155, 115, 20, 20);
ellipse(500, 500, 20, 20);
ellipse(490, 535, 25, 25);
ellipse(600, 275, 25, 25);
ellipse(575, 250, 25, 25);
ellipse(560, 285, 20, 20);
ellipse(60, 480, 25, 25);
}
function one(){
//peach shape
var w1 = 200;
var h1 = 200;
//click to activate otherwise static
if(act1){
w1 = mouseX * .75;
h1 = mouseY * .75;
} else{
w1 = 200;
h1 = 200;
}
fill(117, 182, 129);
ellipse(50, 50, w1, h1);
}
function two(){
//epitrochoid
var x;
var y;
var a = 80.0;
var b = a / 2.0;
var h2 = constrain(100 / 8.0, 0, b);
var ph2 = 100 / 50.0;
//click to activate otherwise static
if(act2){
h2 = constrain(mouseX / 8.0, 0, b);;
ph2 = mouseX / 50.0;
} else{
h2 = constrain(100 / 8.0, 0, b);
h1 = 100 / 50.0;
}
fill(235, 231, 201);
beginShape(); //drawing shape
for (var i = 0; i < nPoints; i++) {
var t = map(i, 0, nPoints, 0, TWO_PI);
x = (a + b) * cos(t) - h2 * cos(ph2 + t * (a + b) / b);
y = (a + b) * sin(t) - h2 * sin(ph2 + t * (a + b) / b);
vertex(x + 200, y + 350);
}
endShape(CLOSE);
}
function three(){
//cranioid
var x;
var y;
var r;
var a = 40.0;
var b = 10.0;
var c = 100.0;
var p = constrain((width/2), 0.0, 1.0);
var q = constrain((height/2), 0.0, 1.0);
//click to activate otherwise static
if(act3){
var p = constrain((mouseX / width), 0.0, 1.0);
var q = constrain((mouseY / height), 0.0, 1.0);
} else{
var p = constrain((width/2), 0.0, 1.0);
var q = constrain((height/2), 0.0, 1.0);
}
fill(235, 231, 201);
beginShape(); //drawing shape
for (var i = 0; i < nPoints; i++) {
var t = map(i, 0, nPoints, 0, TWO_PI);
r =
a * sin(t) +
b * sqrt(1.0 - p * sq(cos(t))) +
c * sqrt(1.0 - q * sq(cos(t)));
x = r * cos(t);
y = r * sin(t);
vertex(x + 400, y + 100);
}
endShape(CLOSE);
}
function four(){
//gray shape
var w4 = 200;
var h4 = 300;
//click to activate otherwise static
if(act4){
w4 = mouseX;
h4 = mouseY;
} else{
w4 = 200;
h4 = 300;
}
fill(41, 89, 50);
ellipse(475, 475, w4, h4);
}
function mousePressed(){
//if clicked within in defined distance then activation state is...
//changed from true to false so the mouseX and mouseY will now take over
var d = dist(oneX, oneY, mouseX, mouseY);
if(d < 200){
act1 = !act1;
blop.play(0, 1, 2);
}
var d2 = dist(twoX, twoY, mouseX, mouseY);
if(d2 < 100){
act2 = !act2;
vpop.play(0, 1, 2);
}
var d3 = dist(threeX, threeY, mouseX, mouseY);
if(d3 < 100){
act3 = !act3;
plop.play(0, 1, 2);
}
var d4 = dist(fourX, fourY, mouseX, mouseY);
if(d4 < 100){
act4 = !act4;
ting.play(0, 1, 2);
}
}
For this project I decided to add sound to my previous project from week seven. The way I set up that project worked really well with how I was already planning on utilizing sound. I think this turned out pretty cute, the original project was meant to be playful and I think the sounds just added to it. Lastly, I changed up the colors just for fun.
]]>This week I looked at a project called Weather Thingy by Adrien Kaeser. This project that uses a sound controller that takes weather and climate events to modify the musical instrument and the sound it makes.
Part of why I liked this project so much it is works in real time. It has sensors that collect data from the climate it is in and the controller interprets the data to create different sounds. The machine has a weather data collection station which includes a rain gauge, a wind vane and a anemometer. It also has a brightness sensor. The user then uses the interface to choose what sensor he is working with and uses a potentiometer to modify the data and create different sounds.
I think this project is so interesting because of its presence in real time and its ability to act as a diary. This device can also store data from a specific time and then you can use that pre-recorded data later on. This way it is almost like a window to a certain time and what was going on then. I can see the potential of using this to see how climate change has affected the same spot over time. I can almost imagine a soundscape being made in one spot and then in the same spot 20 years later and see how different it is.
]]>I decided to look at Julia Nishizaki’s post on the Vespers. Theses are 3D-printed ‘death masks’ by Neri Oxman and her Mediated Matter Group at MIT. These are modern interpretations of traditional death masks using cutting edge materials, processes and visuals. Part of the reason why I decided to write on this post in particular was because I had never heard of a death mask before. After reading about this a death mask is a traditional mask that was supposed to capture the wearer’s last breath.
At MIT, Oxman, has interpreted this as a representation of the past present and future. My favorite part about these mask is the part representing the future synthetically engineered microorganisms to produce specific pigments or chemicals and are specific to the individual’s genetic makeup. It is so cool how they utilize living organisms within the artificial mask and they work together to create one cohesive piece.
Julia mentions the possibilities of this being a step towards wearable technology and interfaces and I thought this was a really interesting point. I like the idea that these technologies in the future might use microorganisms as part of the piece.
]]>//Margot Gersing - Project 09 - mgersing@andrew.cmu.edu - section E
var img; //original image
var sizeOne; //pixel size one
var sizeTwo; //pixel size two
function preload() {
img = loadImage('https://i.imgur.com/Tx6sITJ.jpg?2'); //preload the image
}
function setup() {
createCanvas(500, 761); //cnavas side of the image
sizeOne = 1; //setting pixel size one to one
sizeTwo = 20; //setting pixel size two to 20
imageMode(CENTER);
noStroke();
background(255);
img.loadPixels(); //pixelate the image
frameRate(10000); //fast frame rate to load pixels faster
}
function draw() {
//map the pixels size from 1 to 20, based on mouse postion
var size = map(mouseY, 0, height, sizeOne, sizeTwo);
var sizeW = map(mouseX, 0, width, sizeOne, sizeTwo);
var x = floor(random(img.width));
var y = floor(random(img.height));
var pix = img.get(x, y);
fill(pix, 128);
ellipse(x, y, size, sizeW); //pixel is a ellipse based on the mapped size from mouse position
}
For this project I decided to do a portrait of my grandmother when she was 11 or 12. I really like this photo of her and how it serves as a view into the past. It’s interesting to use such an old photo (1940s) in such a modern context and project.
I decided to have the pixels size dependent on the mouse position. This way you can control the way the image looks. The timing of when and where your mouse is also affects how the image will turn out.
For this week the I watched a lecture by Theo and Emily of Design I/O from Eyeo 2012. I decided to choose this one because I had seen some of their projects before and really like their work.
Their studio works with design, research and coding to create immersive interactive environments. The environments use design and code as tools to makes theses experiences come to life. Behind all of their projects are the goal to create “delight and wonder” to encourage open play and exploration in children. They have offices in California and New York but their work appears all over the world.
I love this studio so much because all the work they make is essentially my dream job. I love working with children and (I work in a preschool) and it has always been my dream to mix teaching, and design to create things for children. All of the projects they do encourage children to explore and openly play. Some of their projects have teaching elements too. They utilize the game and play nature to have the children actually learn something. One of their projects is a games about sharing resources and sustainability and the children not only have to interact with the program but also each other in order to keep up the simulation. They use the Kinect tracking device quite a lot in their projects and hack it different ways to do what they want, like make giant animated and interactive shadow hand puppets.
In this lecture they go through some of their recent projects and talk about the entire design process; research, to prototyping to implementation. they talk about the importance of testing projects at different levels of completion and how testing to scale is so important. They stress the importance of ensuring that the audience is well defined and that it makes sense with that in mind. In order to present and document their projects they use a lot of video, screen capture and photography. They also save all of the tests that they do throughout the process. In the lecture they show a lot of these test and it is so interesting to see the project come together from the early stages.
Other Projects:
]]>