SHORT DESCRIPTION:
In week 3 of intro to IM, we were introduced to the concept of functions, arrays, and object-oriented programming. For my project. I decided to generate a lily pad pond with unique set of flowers, then for each object they would bounce off the walls or bound off of each other. I create two object instance class, one for the lily pads and one for the flowers whose locations are dependent on the lily pads.
Design Concept
Last week, I had created an abstract water lily pond, and you can call me uncreative, but I just REALLY, REALLY wanted to create an aesthetically looking water lily pond. With last week’s assignment, the art had changed rapidly giving a sense of discomfort and urgency, and I wanted this week’s project to have a slower and relax feeling. Especially for me studying away in Abu Dhabi, I feel like my life has been so chaotic with settling into a new environment, experiencing new cultures and lifestyle, and adjusting into the new academic routine has been overwhelming.
As such, I am glad I choose to do a water lily pond because it kept my grounded and allowed me to relax. While I am happy with the end result, I do wish I could have added more elements into my project (rain, ripples, fish, etc) and made it more interactive. However, due to the time constraints of my schedule, I did the best I could and added as much detail with shading and colors to the elements I currently have on canvas.
Coding Processes
I began my project by referencing Ball Class program we had gone over in class since the shape of my lily pads would also be circular and stay within the boundaries of the screen. Functions with collisions were initially the most confusing part for me, and taking the time to digest the logic ultimately allowed me to then implement a function that checked for object collision – which is shown below. The function below would use the distance formula to calculate the distance between the center of one object to the center of another object. Then if the distance was less than the sum of the objects’ radius, that meant there was an overlap, and the objects must then change direction. To change the direction, I simply just exchange the x-y speeds between the two objects, so they would then move in the opposite direction.
checkLilyCollision(otherLily) { // compute the distance between the current lily with the other lily let distance = dist(this.lilyX, this.lilyY, otherLily.lilyX, otherLily.lilyY); // if the distances between two lilys are less than the sum of the radius if (distance < this.radius + otherLily.radius){ let tempSpeedX = this.lilySpeedX; let tempSpeedY = this.lilySpeedY; // exchange direction and speed of the colliding lilies this.lilySpeedX = otherLily.lilySpeedX; this.lilySpeedY = otherLily.lilySpeedY; otherLily.lilySpeedX = tempSpeedX; otherLily.lilySpeedY = tempSpeedY; } }
Additionally, I had also started by played around with the arc() function, in order to achieve the tiny slit for the lily pad. Below was a code sketch of the degrees which I wanted my lily pads to look. From there, I dove deep into randomization the attributes of the lily pad class. Most properties such as speed, rotation, location, initial angle, etc were randomized using the random() or Math.random() function because I wanted each execution of the program to create a different and unique portrait.
function waterLily() { fill('rgb(42,140,42)'); // color of the lilypad arc(100, 100, 80, 80, 0, 11 * PI/6); }
Admittivity, I had a problem with overlapping lily pads with each execution of the program and had to rely on Chatgpt to help me resolve the issue. They had suggested to test over 1000 attempts and test if a new instance lily pad object would overlap with an existing lily pad object. I did change and delete a few lines of code Chatgbt provided, but below is what I ended up in my code.
function generateLily(){ for (let i = 1; i < numLily + 1; i+= 1){ let validPosition = false; let attempts = 0; while (attempts < maxAttempts && !(validPosition)){ ... if (isLilyPositionValid(newLilyObject)){ gLilyArr.push(newLilyObject); validPosition = true; } attempts += 1; } } } function isLilyPositionValid(newLilyObject){ let initalSpacing = random(3,9) // for each existing lily within the lily array for (let existingLily of gLilyArr) { let distance = dist(newLilyObject.lilyX, newLilyObject.lilyY, existingLily.lilyX, existingLily.lilyY); if (distance < newLilyObject.radius + existingLily.radius + initalSpacing) { return false; // Overlap detected } } return true; // No overlap detected }
When I completed my lily pads, I moved onto the flowers, which were my favorite and proudest section of my program. I created another class for my flowers for it be at the center of the lily pads to have a random number of petals, rotation, and combination of color. I used push() and pop() functions that I learned from my first assignment to save and reset the state of the canvas, alongside translation() which set the center of the flower to the center of the lily pad I was currently working on. I did have a problem with the layers stacking on top of each other and the color and degree of the layers changing each frame, but in the end, I was able to get it fixed by creating a unique array for the flower’s color, rotation, and layers.
Final Design
Below is the final program for this assignment. Overall, I am happy with the movement of the lily pads and how each of the flowers turned out. I liked how it is unique for each execution of the program, but it isn’t too overwhelming to the user. There were a lot of technical problems throughout the project, but the concept of a calm and pretty end project kept me motivated to continue working.