1. Concept
As I have experienced implementing OOP before, I was supposed to be extra challenged with creativity. I brainstormed various ideas:
- drawing a large galaxy spiral, planets and regular shapes (squares, triangles) on the canvas
- intially an all black canvas except potentially the area around the cursor which can “glow” and reveal dots that are part of a representation of face portrait. integrate interesting elements such as planets as earrings.
- Using Weighted Voronoi Image Stipling – this looked cool but I couldn’t see a way to use OOP with it.
The challenge in this process was trying to avoid generic ideas. Based on the reading for this week, interactive design is important. So I considered ideas for it, especially idea 2:
- change colour of features (eg. hair) based on music
- ask user to put in music file
- upon user’s click, display new art with dots closely resembling image input
But the problem with it was that idea 2 would take so much time. I had learned from the first assignment that I should plan on a project that appears objectively doable/achievable within the time constraint. I found the ideation phase time-consuming and particularly challenging, and discussion with friends was helpful. I decided that the ideas I had brainstormed could be stored and used instead for a later assignment. I decided to use simple objects where I could implement OOP.
The concept for my art is “PARTY TIME.” It displays an evergreen tree with snow in the winter season. There needs to be a Tree class and Snow class. Since multiple snowballs are used, an array can be used to store snow objects. I wanted to try twinkling lights (if time permits).
2. Code Highlights
I started with creating the Tree class. A simple evergreen tree could be represented using three green triangles for its leafy parts (of increasing size as you go downwards) and one brown rectangle for the wooden trunk. So I defined attributes for each triangle’s top point x-coordinates and y-coordinates. At Professor Shiloh’s advice, I tried not to hard-code the numbers in.
class Tree { constructor() { this.topTriangleTopX = width/2; this.topTriangleTopY = (2 / 7) * height + 10; this.middleTriangleTopX = width/2; this.middleTriangleTopY = (3 / 7) * height; this.bottomTriangleTopX = width/2; this.bottomTriangleTopY = (4 / 7) * height; this.woodCenterX = width/2; this.woodCenterY = (6/7) * height; this.woodWidth = width/10; this.woodHeight = height/7; this.color = color('hsb(160, 100%, 50%)'); } ... }
At first I created a Snow class. The idea was to have falling circles representing falling snowballs. But the issue was that my draw function would draw one row of falling circles that falls together. Even if I were to place a function to set these circles back to the top of the canvas when it reaches the ground, the prime issue is that between the time the snow moves from the top to the bottom of the canvas, there is only one row of snow falling. This was not lifelike at all.
There was one thing to appreciate, though, which was that the snow didn’t move in a straight-down manner, it could move leftward or rightward as it moved down, which was pretty realistic.
class Snow { constructor(xSpeed0, ySpeed0) { this.xPos = random(0,600); this.yPos = 20; this.xSpeed = random(-1,1); this.ySpeed = this.diameter = 10; } move() { // move the ball this.xPos += this.xSpeed; this.yPos += this.ySpeed; } draw() { fill(255); noStroke(); circle(this.xPos, this.yPos, this.diameter); } }
To resolve this issue, I researched online. I found that p5js had a Snowflake class, which worked pretty similarly. I really appreciated its organic-ness that was beyond my attempt – it used a sine function to create a wavy falling down motion akin to being affected by wind – which, I have to say is pretty incredible to see even after watching it multiple times.
I played around with the Snowflake class, experimenting and researching to find out what some line does, and keeping what I liked. For instance, I watched a Khan Academy video to understand angular speed and changed it to 0 (snow falls down straight) and 100 (the rotational movement of the snow was super obvious which I didn’t want). The value 35 was nice so I kept it. I also learned that different size snowflakes fall at different y speeds, smaller snowflakes fall faster while bigger snowflakes fall slower using an equation with a graph that has a similar shape to 1/x graph.
class Snowflake { constructor() { this.posX = 0; this.posY = random(-height, 0); this.initialAngle = random(0, 360); this.size = random(2, 5); this.radius = sqrt(random(pow(width / 4, 2))); this.color = color(random(200, 256), random(200, 256), random(200, 256)); } update(time) { // Define angular speed (degrees / second) let angularSpeed = 35; // Calculate the current angle let angle = this.initialAngle + angularSpeed * time; // x position follows a sine wave, using the parametric equation for x coordinate (x = r sin(theta)) this.posX = width / 2 + this.radius * sin(angle); // Different size snowflakes fall at different y speeds, smaller snowflakes fall faster while bigger snowflakes fall slower using an equation with a graph that has a similar shape to 1/x graph let ySpeed = 8/this.size; this.posY += ySpeed; // When snowflake reaches the bottom, move it to the top if (this.posY > height) { this.posY = -50; } } display() { fill(this.color); noStroke(); ellipse(this.posX, this.posY, this.size); } }
For the stars, I tried to use a starry night source code. But as I tried to integrate it, I faced an issue which I couldn’t resolve, even after debugging attempts (by following p5js instructions: p5.js says: you have used a p5.js reserved function “currentTime” make sure you change the function name to something else.) and using AI. I couldn’t get the stars to appear and dynamically expand and contract as they should – they just seemed like dashes.
Once I moved the background color of the canvas from the draw() to setup(), I found that you can see the trailing movements of the canvas. It was supposed to be a bug, and I knew how to resolve it, but since I thought this looked so cool, I decided to keep it. I took out the stars, and used the trailing, colourful snow as the main cool and creative feature.
A slight dynamic element is a trailing cursor 🙂
3. Embedded sketch
4. Reflection and ideas for future work
There are several important experiences I had through this art process. Personally, I was able to create the snowfall animation that I had wanted to try from week 1, was able to meet my goals of implementing OOP, arrays and functions. Since I couldn’t add the music, I hope to try that in the upcoming week(s).
This work could be further extended through expanding the concept and adding design interactivity. One idea I have is that at the user’s click, the seasons would change, showing summer, fall, winter and spring, with the music changing based on Vivaldi’s Four Seasons piece. I love the idea of music complementing the visuals.