Assignment 2: Flowers in the Wind

For this week’s assignment, we were asked to create a peice of artwork utilizing loops. I struggled to think of a concept at first, but while walking around the campus, inspiration struck. I saw flowers across the campus moving in the wind. Thus, my assignment takes inspiration from that image.

In my peice, 10 flowers are randomly generated throughout the canvas, with their size and color also being randomized.

I had to watch some tutorials in order to understand the way angles worked in p5.js to get my flowers to spin. Due to this learning curve, I am especially proud of the rotation of the flowers within my peice. It took quite some time for me to get the hang of it, but it made the end result all the more satisfying to accomplish.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function draw() {
//refreshing the background each time
background("#9dc183");
//iterating over every item in the flower array
for (let flower of flowers) {
push();
//makes the drawing start at the center of the flower
translate(flower.x, flower.y);
//makes the flower spin from the center
rotate(flower.angle);
drawFlower(flower.size, flower.color);
pop();
flower.angle += spinSpeed;
}
//if statement that will call the generate flower function as long as the flower array isnt longer than 10 and will generate every second
if (flowers.length < maxFlowers && frameCount % 60 == 0) {
generateFlower();
}
}
function draw() { //refreshing the background each time background("#9dc183"); //iterating over every item in the flower array for (let flower of flowers) { push(); //makes the drawing start at the center of the flower translate(flower.x, flower.y); //makes the flower spin from the center rotate(flower.angle); drawFlower(flower.size, flower.color); pop(); flower.angle += spinSpeed; } //if statement that will call the generate flower function as long as the flower array isnt longer than 10 and will generate every second if (flowers.length < maxFlowers && frameCount % 60 == 0) { generateFlower(); } }
function draw() {
  //refreshing the background each time
  background("#9dc183");
  

  //iterating over every item in the flower array
  for (let flower of flowers) {
    push();
    //makes the drawing start at the center of the flower
    translate(flower.x, flower.y);
    //makes the flower spin from the center
    rotate(flower.angle);
    drawFlower(flower.size, flower.color);
    pop();
    flower.angle += spinSpeed;
  }

  //if statement that will call the generate flower function as long as the flower array isnt longer than 10 and will generate every second
  if (flowers.length < maxFlowers && frameCount % 60 == 0) {
    generateFlower();
  }
}

 

Initially I had wanted a more detailed background for my peice, rather than a solid color, however, I struggled with the background flickering every frame. Another thing I think that can be further improved on is the variety of flowers chosen. It would be fun to implement more kinds of flowers, rather than simply just having them in different colors.

Reading Reflection – Week 2

The first thing about Casey’s presentation that made me challenge my beliefs is that digital art is not real art. I used to think that things that are ‘generated’ are not authentic enough to be considered a unique piece of art. Yet, seeing how much thought and structure it takes to create an abstract pattern with the help of algorithms made me reevaluate my views. It’s fascinating how a series of flat geometric shapes drawn over and over again can create such a lively picture.  This idea is reflected in the quote by Michael Noll, “The computer is a unique device for the arts, since it can function solely as an obedient tool with vast capabilities for controlling complicated and involved processes. But then again, full exploitation of those unique talents for controlled randomness and detailed algorithms can result in an entirely new medium—a creative, artistic medium.” In my future works, I’d like to work more on thinking creatively within a limited range of functions I know.

I believe that uncontrolled randomness leads to complete chaos, while good digital artwork takes a little bit of randomness and a lot of decision-making. As humans, we are set to think in patters, thus it can be quite challenging to create something inherently random, something that has no beginning or end, or doesn’t follow standard rules of composition. I like how Casey uses randomness as a jumping-off point for his artworks such as rolling a dice to trigger the final composition, which is built based on a series of carefully designed algorithms.  

Looking at Casey’s journey, I admire how meticulous he is about building an algorithm and exploring it to the fullest before moving onto a new concept. It seems like he won’t leave his idea until he has tried visualizing it in all ways possible. This reminds me of how famous artists such as Picasso, who went though different ‘eras’ in his art, ended up creating a series of artworks known as The Blue Period. 

My final takeaway from this talk is that true randomness can not be generated by a computer – it has to be “borrowed” from nature, like the patters that bacteria create while reacting to sunlight, where computer serves as a tool to make randomness make sense. 

Week 2 – artwork

Concept

This artwork explores the balance between structure and unpredictability through a dynamic grid of circles. The grid itself represents order and repetition, while the interaction with the mouse introduces an element of spontaneity. As the user moves their cursor, the circles respond by changing size and color, creating a sense of movement and fluidity. This interaction turns the viewer into an active participant, making the piece feel more alive and engaging. The idea behind it is to show how external influences can transform something predictable into something unexpected.

Code Highlight

One of the most interesting aspects of the code is the way it uses a double for-loop to generate a grid of circles. This helps arrange the shapes evenly on the canvas. The interactive part is driven by the dist() function, which calculates how far each circle is from the mouse pointer. That distance then determines the size and color of each circle, making them look as if they reacted to the user’s mouse movements. The map() function helps smooth out these changes by scaling the distance values into a range that works well for the visual effect.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
let d = dist(mouseX, mouseY, x, y);
let circleSize = map(d, 0, width, maxSize, minSize);
fill(map(d, 0, width, 255, 100), 100, 200);
ellipse(x, y, circleSize);
}
}
for (let i = 0; i < cols; i++) { for (let j = 0; j < rows; j++) { let d = dist(mouseX, mouseY, x, y); let circleSize = map(d, 0, width, maxSize, minSize); fill(map(d, 0, width, 255, 100), 100, 200); ellipse(x, y, circleSize); } }
for (let i = 0; i < cols; i++) {
  for (let j = 0; j < rows; j++) {
    let d = dist(mouseX, mouseY, x, y);
    let circleSize = map(d, 0, width, maxSize, minSize);
    fill(map(d, 0, width, 255, 100), 100, 200);
    ellipse(x, y, circleSize);
  }
}

Reflection & Improvements for Future Work

I believe that my project does a great job of showing how loops and interaction can be used to create something visually engaging in p5.js. The grid of circles reacting to the mouse makes the piece feel dynamic, and the changes in size and color add a nice touch of unpredictability. It’s simple, but it keeps things interesting as you move the mouse around.

That being said, there’s definitely room for improvement. Right now, the transitions feel a bit abrupt, so adding some smoothing or easing effects could make the movement more natural. It would also be fun to experiment with extra elements like rotation, fading effects, or even some subtle animation when the mouse isn’t moving. Another cool idea would be giving users more control—maybe letting them change the colors or grid size with sliders or buttons. And if sound was added, it could create an even more immersive experience where the visuals react to music or voice input.

Overall, this was a fun experiment in generative art.

Week 2 – Computer Artwork

Concept :

For this computer artwork, I decided to take inspiration from a stress relieving toy called Pop It. Basically the user can pop the silicon molds as a form of stress relief. I decided to use this idea and create a grid of colours and patterns, where one clicking the mouse, the colour and pattern changes.

I tried to use all the concepts we learned in class, including for loops, arrays, functions; both built in and user defined. Trying to use these different concepts in my code taught me how to use and incorporate them.

Highlight:

One part of the code I’m particularly proud of is the switching between patterns. I used switch statements, a concept I learned from CS in highschool,  to create pattern changing from circle to strikes.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function drawPattern(x, y, patternType) {
push();
stroke(0);
strokeWeight(2);
switch (patternType) {
case 0:
line(x, y, x + boxSize, y + boxSize); //strike pattern
break;
case 1:
ellipse(x + boxSize / 2, y + boxSize / 2, boxSize / 2); //ellipse pattern
break;
}
pop();
}
function drawPattern(x, y, patternType) { push(); stroke(0); strokeWeight(2); switch (patternType) { case 0: line(x, y, x + boxSize, y + boxSize); //strike pattern break; case 1: ellipse(x + boxSize / 2, y + boxSize / 2, boxSize / 2); //ellipse pattern break; } pop(); }
function drawPattern(x, y, patternType) {
  push();
  stroke(0);
  strokeWeight(2);
  switch (patternType) {
    case 0:
      line(x, y, x + boxSize, y + boxSize); //strike pattern
      break;
    case 1:
      ellipse(x + boxSize / 2, y + boxSize / 2, boxSize / 2); //ellipse pattern
      break;
  }
  pop();
}

Embedded sketch:

What I love the most about this artwork is the fact that its never the same, its always changing. We can create art out of the art itself, and the whole “pressing the mouse to change colours and patterns” is so satisfying. I also love the colours, which

I made using a colour palette using arrays. I like how we can create patterns with the colours themselves.

Reflections:

Overall, I felt that this assignment was such a good way to revisit all the concepts we learned in class and create something beautiful out of it. In the future, I’d like to try and make the code more precise and versatile. Maybe more patterns, colours and animations in the grids themselves.

 

Reading Response 1 – Chance Operations (Week 2)

In his talk, Casey Reas explores the theme of order and chaos in art, emphasizing the role of randomness in creative processes. He also focuses on the notion of “controlled randomness” , where artists establish specific rules and parameters within code, allowing for unexpected outcomes while maintaining the overall coherence.

First of all, I really enjoyed listening to Reas’ talk. I appreciated the way he showcased his work and explained his philosophy on creativity and art. Reflecting on his insights, I aimed to incorporate the concept of controlled randomness in my most recent p5.js sketch, which I titled randomness. The overall structure of the artwork is straightforward—featuring a 10×10 grid of circles. However, the element of controlled randomness comes into play when the user interacts with the piece. Each time the user clicks on the canvas, the circles in the grid change in shape and size, creating a dynamic balance between order and unpredictability. While users can grasp the overall structure, every interaction (mouse click) generates a unique and evolving pattern. I wouldn’t go so far as to claim that my artwork revolutionizes the concept of generative art, but I believe it is an engaging and enjoyable piece to explore.

That being said, Reas’ perspective on art and the creative process encourages me to explore the potential of chance in my work. With every new p5.js sketch I create, I will keep the notion of “controlled randomness” in mind.

Week 2 – Animation, Conditionals, Loops

Concept

In this p5.js sketch, my main objective was to practice for loops and play around with the concept of randomness a bit. It is a simple generative art piece. The idea was to generate a grid of circles, where each circle varies in size, color and level of transparency. So by clicking on the window/canvas, the user can regenerate a completely random pattern (this adds an element of interactivity and makes the artwork dynamic).

Demo (Click on canvas)

Code Highlight:

One of the parts I’m most proud of is the loop structure that efficiently places the circles while maintaining randomness in their size and color:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
for (let x = 0; x < width; x += spacing) {
for (let y = 0; y < height; y += spacing) {
let size = random(10, spacing * 0.8);
let r = random(100, 255);
let g = random(100, 255);
let b = random(100, 255);
fill(r, g, b, 180); // Semi-transparent random color
noStroke();
ellipse(x + spacing / 2, y + spacing / 2, size, size);
}
}
for (let x = 0; x < width; x += spacing) { for (let y = 0; y < height; y += spacing) { let size = random(10, spacing * 0.8); let r = random(100, 255); let g = random(100, 255); let b = random(100, 255); fill(r, g, b, 180); // Semi-transparent random color noStroke(); ellipse(x + spacing / 2, y + spacing / 2, size, size); } }
for (let x = 0; x < width; x += spacing) {
  for (let y = 0; y < height; y += spacing) {
    let size = random(10, spacing * 0.8);
    let r = random(100, 255);
    let g = random(100, 255);
    let b = random(100, 255);

    fill(r, g, b, 180); // Semi-transparent random color
    noStroke();
    ellipse(x + spacing / 2, y + spacing / 2, size, size);
  }
}

Reflection & Improvements for Future Work

This project reinforced my understanding of looping structures in p5.js and the power of randomness in generative art. It was interesting to see how slight variations in parameters can lead to visually engaging results.

Future Work:
Experiment with different shapes (e.g., triangles, squares, or custom polygons). Add animation so circles gradually fade in and out.  Allow users to save their favorite generated patterns.

This was a fun dive into creative coding, and I look forward to exploring more complex generative techniques!

Week 1 – Self-Portrait

Concept:
I wanted to make my self-portrait in a minimalistic style that would accurately represent my appearance while being limited to the use of simple geometric primitives. I chose to not use outlines to add to that flat, minimalist aesthetic. I also wanted to add some simple interactivity, which came in the form of the background changing colours through a day-night palette when clicked.

Embed:

Highlight:
I was proud of this snippet, where I used an array of hex codes to implement my colour cycling feature. It is perhaps more simple than I had hoped for, but I’m happy with how it turned out overall.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// // Array containing possible background colours
let bgs = ["#fff2bd", "#f4d797", "#c9ebff", "#abb5ff", "#7475b6", "#5148b2"];
let curr_bg = 0;
function mouseClicked() {
// // Change to next bg colour on click
curr_bg = (curr_bg + 1) % bgs.length;
}
// // Array containing possible background colours let bgs = ["#fff2bd", "#f4d797", "#c9ebff", "#abb5ff", "#7475b6", "#5148b2"]; let curr_bg = 0; function mouseClicked() { // // Change to next bg colour on click curr_bg = (curr_bg + 1) % bgs.length; }
// // Array containing possible background colours
let bgs = ["#fff2bd", "#f4d797", "#c9ebff", "#abb5ff", "#7475b6", "#5148b2"];
let curr_bg = 0;

function mouseClicked() {
  // // Change to next bg colour on click
  curr_bg = (curr_bg + 1) % bgs.length;
}

Reflection:
I feel a bit conflicted about this assignment, since on the one hand it was an interesting change of pace to try and create art directly using code, but also very annoying. I found myself frequently trying to force coordinates or dimensions to be multiples of the canvas’ dimensions to allow it to scale, but often found it to be an exercise in frustration. Having to essentially guess-and-check all my numbers was another aspect I didn’t enjoy, since there were little quirks I wouldn’t expect such as circle’s being plotted by their center versus rectangles by their top-left corner.

In the future, I would like to try and plan things out more before starting, especially in regards to using custom variables. The built-in width and height variables made sense at first, but I quickly gave up on sticking to them and added pixel offsets instead. I think the most important thing for me is finding a way to streamline my workflow, since my struggle to put my concept on paper/screen caused me to fall short of where I wanted to be in terms of both artistic and programmatic aspects.

Assignment 1: Self-Portrait

For this assignment, we had to create a self-portrait in p5js. I began by deciding which elements of myself were important to incorporate. Of course, this includes basic features like eyes, nose, mouth but also things like my wavy hair or silver earrings. Once I figured out what to incorporate, I began making shapes in p5js, making sure the layers were right to get the results I wanted. The final result of my self-portrait is as follows:

As I worked, I realized making shapes in this program is quiteee annoying, especially because you need to play guess and check when figuring out coordinates. This led to it taking more time than expected, especially when it came to places where there are many shapes combined. For example, the eyes are something I am proud of because I went a step further to make them a tad bit more realistic by adding a flash spot. You can see the code for this below:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
//eyes
push()
stroke('black')
fill('white');
ellipse(220,190,30,19)
fill('black');
circle(220,190,12)
fill('white')
circle(224,186,4)
pop()
push()
stroke('black')
fill('white');
ellipse(280,190,30,19)
fill('black')
circle(280,190,12)
fill('white')
circle(284,186,4)
pop()
//eyes push() stroke('black') fill('white'); ellipse(220,190,30,19) fill('black'); circle(220,190,12) fill('white') circle(224,186,4) pop() push() stroke('black') fill('white'); ellipse(280,190,30,19) fill('black') circle(280,190,12) fill('white') circle(284,186,4) pop()
//eyes
  push()
  stroke('black')
  fill('white');
  ellipse(220,190,30,19)
  fill('black');
  circle(220,190,12)
  fill('white')
  circle(224,186,4)
  pop()
  push()
  stroke('black')
  fill('white');
  ellipse(280,190,30,19)
  fill('black')
  circle(280,190,12)
  fill('white')
  circle(284,186,4)
  pop()

Overall though, I think this assignment was a great introduction to creating objects in Javascript and required a lot of self-teaching from the references on the p5js website when it came to things like arcs, rounding out rectangles, push and pop, ellipses, etc. Breaking down myself into simple shapes really pushed my creativity when it came to combining shapes like ellipses and rectangles and circles for my hair and bangs. I was able to think outside the box on how to create what I wanted because I wasn’t even sure what the best way to get what I wanted to create was. My hope for the future is the be able to understand curves better to be able to make more custom shapes from scratch. Perhaps one day I can revisit this self-portrait and make it more realistic.

 

Week 1: Self-Portrait

Concept:

This was my first project using p5.js, and also my first for this class. So, I decided to experiment and explore as much as I could to build a solid foundation for the projects ahead.

To start, I used a photo of myself to get a rough idea of how to align my basic features. The goal was to create a portrait as realistic and true to life as possible. I used different shapes, like ellipses, arches, and rectangles, to form the features, and added line strokes to bring in more detail.

Since I’m a computer science major, I wanted to add some movement and interactivity, instead of just making a still portrait. First, I made the eyes follow the cursor by adjusting their position as the cursor moved. At first, though, the pupils kept escaping the eyes, so I had to put some limits on the movement to keep them inside the eyes. Then, since I love flowers, I created a function that draws small flowers whenever the mouse clicks anywhere on the screen. This made it look like I was looking in the direction where each flower appeared, reflecting my interest and excitement for flowers. After every five flowers, I added a little celebration with confetti falling from above. Once the confetti finished, the flowers slowly started falling too. The user would then need to refresh the page to draw more flowers.

Ideally, I would’ve made the flower creation loop infinite, so the user wouldn’t have to refresh to make new flowers. However, I’ve been feeling really worn out with work lately, so I decided to leave it as is. The idea was that I needed to refresh before getting more work — since the project is meant to reflect me, not just being a simple program, it kind of shows that I need a break too.

Click anywhere to make flowers. I’ll be super happy if you can make 5 !

Highlights:

I think the highlight of my project was the confetti and the flowers falling down. It added a fun sense of celebration and reflected my love for flowers.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// confetti falling down if celebration has started
if (celeb_start) {
for (let i = 0; i < confetti.length; i++) {
confetti[i].y += confetti[i].speedY; // move the confetti down
confetti[i].x += confetti[i].speedX; // move the confetti horizontally to give a wavy effect
fill(confetti[i].color);
noStroke();
ellipse(confetti[i].x, confetti[i].y, 10, 10);
}
// removing confetti that has gone off the screen
confetti = confetti.filter(c => c.y < height);
}
// falling flowers after celebration
if (flower_count >= 5 && !celeb_start) {
celeb_start = true;
// pause for 1 second before the celebration starts
setTimeout(() => {
generateConfetti(); // start the confetti
}, 300);
// pause for 5 seconds after confetti
setTimeout(() => {
makeFlowersFall(); // making flowers fall
}, 3000); // confetti and delay time
}
// move the falling flowers
for (let i = 0; i < fall_flowers.length; i++) {
fall_flowers[i].y += fall_flowers[i].speedY; // make flowers fall
fall_flowers[i].x += fall_flowers[i].speedX; // adding horizontal drift to the flowers
drawFlower(fall_flowers[i].x, fall_flowers[i].y);
}
// removing flowers that have fallen off the screen
fall_flowers = fall_flowers.filter(f => f.y < height);
}
// confetti falling down if celebration has started if (celeb_start) { for (let i = 0; i < confetti.length; i++) { confetti[i].y += confetti[i].speedY; // move the confetti down confetti[i].x += confetti[i].speedX; // move the confetti horizontally to give a wavy effect fill(confetti[i].color); noStroke(); ellipse(confetti[i].x, confetti[i].y, 10, 10); } // removing confetti that has gone off the screen confetti = confetti.filter(c => c.y < height); } // falling flowers after celebration if (flower_count >= 5 && !celeb_start) { celeb_start = true; // pause for 1 second before the celebration starts setTimeout(() => { generateConfetti(); // start the confetti }, 300); // pause for 5 seconds after confetti setTimeout(() => { makeFlowersFall(); // making flowers fall }, 3000); // confetti and delay time } // move the falling flowers for (let i = 0; i < fall_flowers.length; i++) { fall_flowers[i].y += fall_flowers[i].speedY; // make flowers fall fall_flowers[i].x += fall_flowers[i].speedX; // adding horizontal drift to the flowers drawFlower(fall_flowers[i].x, fall_flowers[i].y); } // removing flowers that have fallen off the screen fall_flowers = fall_flowers.filter(f => f.y < height); }
// confetti falling down if celebration has started
if (celeb_start) {
for (let i = 0; i < confetti.length; i++) {
confetti[i].y += confetti[i].speedY; // move the confetti down
confetti[i].x += confetti[i].speedX; // move the confetti horizontally to give a wavy effect
fill(confetti[i].color);
noStroke();
ellipse(confetti[i].x, confetti[i].y, 10, 10);
}

// removing confetti that has gone off the screen
confetti = confetti.filter(c => c.y < height);
}

// falling flowers after celebration
if (flower_count >= 5 && !celeb_start) {
celeb_start = true;

// pause for 1 second before the celebration starts
setTimeout(() => {
generateConfetti(); // start the confetti
}, 300);

// pause for 5 seconds after confetti
setTimeout(() => {
makeFlowersFall(); // making flowers fall
}, 3000); // confetti and delay time
}

// move the falling flowers
for (let i = 0; i < fall_flowers.length; i++) {
fall_flowers[i].y += fall_flowers[i].speedY; // make flowers fall
fall_flowers[i].x += fall_flowers[i].speedX; // adding horizontal drift to the flowers
drawFlower(fall_flowers[i].x, fall_flowers[i].y);
}

// removing flowers that have fallen off the screen
fall_flowers = fall_flowers.filter(f => f.y < height);
}

I also liked the idea of making the shirt with a round neckline using a skin-colored semi-circle (to extend the neck skin), which gave the clothes a more realistic look. This saved me time because creating the shirt itself with that structure would have been much more difficult than simply extending the neck.

Reflections, ideas for future work & Improvements:

I have slightly wavy hair and wanted to capture that instead of using simple straight line strokes. I tried using sin() functions to create the waves, but I couldn’t get it right due to time constraints. Since the thing I love most about myself is my hair, I really want to make it more realistic and true to mine. I also hope to make my bangs look more natural by using arches instead of line strokes.

I could definitely improve the aesthetics of the background and add a more appealing scenery. Since the theme of this portrait is all about flowers and positive vibes, I could create a garden in the background to complement that idea. Lastly, I’d love to make a full-body portrait with a nice dress in the future.

Week 1: Self Portrait

Project Concept

For my first assignment, I envisioned creating a  portrait using only one shape thats minimalist yet offers visual depth. I decided that pixel art was the perfect medium for this idea since Its built out of squares yet shading features help provide the sense of depth. Its structured grid format and the ability to control each individual “pixel” felt ideal for achieving the clean aesthetic I had in mind.

Challenges Faced

While my initial plan was to use nested loops to generate the grid and automate the process, as a complete coding beginner, I encountered errors that made it difficult to implement this approach. To overcome this, I decided to hardcode each pixel manually. This allowed me to fully control the placement and colors but turned the process into a labor-intensive task. Every pixel had to be individually positioned and assigned a color, which made the project take much longer than anticipated. It obviously isn’t ideal but I gained a hands-on understanding of positioning features , drawing features.

Key Takeaways

Despite the challenges, this project turned out to be a significant learning experience. Some of the key insights I gained include:

  1. The necessity of loops and conditions: Hardcoding each pixel gave me total control, but it also highlighted how essential loops are for reducing repetitive tasks and improving efficiency in coding. When I wanted to change my background in the end, it wasn’t possible because that’d need me to hardcode everything all over again.
  2. Improved understanding of p5.js positioning: By working manually on every pixel, I developed a solid understanding of how p5.js handles positioning and coordinates, which will undoubtedly help me in future projects.
  3. Patience and problem-solving: This project tested my patience but also pushed me to find doable solutions when my initial approach didn’t work as planned.