(higher amplitude = longer sleep; larger frequency = longer lifespan)
Conception
In this project I wanted to demonstrate the idea of passing moments and how your total lifespan affects how fast you may perceive each moment. Since I love animals, the project started with me just wanting to play around with some data regarding animals; however, I was struggling to find something interesting.
At first I had some data with brain mass and wanted to compare each animal’s brain mass to body mass ratio using circles but it ended up looking very bland so I completely scrapped that sketch.
Then I looked around online for some more databases until I found one that had both lifespan and sleep durations. I thought I could perhaps make something to visualize the impermanence of life and demonstrate the idea of “passing moments.” You could say it’s a bit of a memento mori in a way for both you and the animal mentioned on screen.
Development
I was thinking of how I could represent lifespan and I thought about the heart rate monitors beside hospital beds. I thought perhaps I could use sin waves to represent life span and have the amplitude and frequency be scaled with different things, so that’s what I went with.
I matched the frequency with their life span
let frequency = map(chosenMammal.lifeSpan, 2, 80, 0.02, 0.08); ... sin(x*frequency - frameCount * 0.1)
Then I matched the amplitude with hours of sleep per day
let sleepHours = chosenMammal.totalSleep; let ampMult = 8; ... let y = height/2 + sin(x*frequency - frameCount * 0.1) * sleepHours * ampMult;
Together, I was able to use the beginShape() and endShape() functions to create a continuous animated sine wave for the mammal. However, that felt like it lacked a frame of reference so I added another wave behind it in gray to represent humans. This way, it could really put into perspective just how fast each moment for us vs the chosen mammal was. I was quite proud of how this part turned out.
function drawSleepSpiral(chosenMammal, color){ let sleepHours = chosenMammal.totalSleep; let ampMult = 8; let frequency = map(chosenMammal.lifeSpan, 2, 80, 0.02, 0.08); push(); noFill(); if (chosenMammal == allMammals[21]){ //21 is human stroke(200); } else{ stroke(color); } strokeWeight(6); beginShape(); for (let x = 0; x < width; x+=1){ let y = height/2 + sin(x*frequency - frameCount * 0.1) * sleepHours * ampMult; vertex(x,y); } endShape(); pop(); }
I wasn’t happy with how the default font looked so I loaded in a very beloved font, Helvetica, into the project with what we learned last week.
textFont("Helvetica"); textAlign(CENTER, CENTER);
I was also thinking of adding a text input for the user to put in how many hours they sleep and compare that to the mammal onscreen but I felt like that took away from the idea of lifespan and sounded more like I wanted the user to acknowledge how healthy their sleep schedule was, which I thought would greatly detract from the memento mori effect I was aiming for.
Lastly I added a mousePressed function to cycle through the database without having to hit the start button each time.
function mousePressed(){ chosenMammal = random(allMammals); // switch to a new mammal on click randomColor = random(colorArray); //changes to a random color with the same click }
Conclusion / Difficulties Endured
I didn’t even realize I could upload my own files and create folders in the sketch files until this past week so this production piece provided me with a lot more insight into what p5js is capable of.
I initially had some trouble figuring out how to get the data out from the CSV file in a natural and efficient way but then I remembered I could extract each column data as a separate characteristic of my object like this:
for (let i = 0; i < table.getRowCount(); i++) { let mammalObject = { species: table.getString(i, "Species of animal"), bodyMass: table.getNum(i, "Body Weight (kg)"), brainMass: table.getNum(i, "Brain Weight (g)"), totalSleep: table.getNum(i, "Total sleep (hrs/day)"), lifeSpan: table.getNum(i, "Maximum life span (years)") }; allMammals.push(mammalObject) //now i can obtain mammalObject.bodyMass for instance }//closes for() after appending all mammals
This made the process of finding specific attributes of the chosen mammal so much more convenient and efficient.
I also made sure credit the source of my database at the very end of my code: https://gist.github.com/yppmark/d907dc265a84cac76ba7