Concept: My generative art created using P5.js presents a captivating display of colorful circles arranged in a dynamic pattern using OOPS, Arrays and Functions. I have integrated few interactive functions to make it more interesting. Inspired by the interplay of randomness and user interaction as discussed in class, this artwork embodies the concept of controlled chaos.
Main Inspiration:
At initial phase: At first, I had the idea to create artwork like the one in the video, but instead of using curves, I wanted to use circles. Each circle in my artwork has its own size, color gradient, and movement, which all come together to make the overall picture interesting. I added an interactive feature so people can join in and make the artwork themselves by clicking the mouse to add new circles. This makes the artwork more dynamic and engaging. The colors of the circles change gradually based on their position on the screen, which gives the artwork depth and liveliness. Additionally, each circle rotates at its own speed, adding a sense of flow and motion. Overall, my artwork demonstrates how randomness can be controlled to create harmony, inviting viewers to appreciate the beauty of unpredictability.
[Initial Output] This is how it looks! Try tapping anywhere in canvas to create more fun circles..
Initial Art Code:
let circles = []; function setup() { createCanvas(600, 600); // Create an initial set of circles for (let i = 0; i < 50; i++) { let circle = new Circle(random(width), random(height), random(10, 50)); circles.push(circle); } } function draw() { background(255); // Update and display each circle for (let circle of circles) { circle.update(); circle.display(); } } function mousePressed() { // Add a new circle at the mouse position when clicked let newCircle = new Circle(mouseX, mouseY, random(10, 50)); circles.push(newCircle); } // Circle class definition class Circle { constructor(x, y, diameter) { this.x = x; this.y = y; this.diameter = diameter; this.color1 = color(random(255), random(255), random(255)); this.color2 = color(random(255), random(255), random(255)); this.speedX = random(-2, 2); this.speedY = random(-2, 2); this.rotation = random(TWO_PI); // Random initial rotation this.rotationSpeed = random(-0.05, 0.05); // Random rotation speed } update() { // Move the circle this.x += this.speedX; this.y += this.speedY; // Bounce off the walls if (this.x > width || this.x < 0) { this.speedX *= -1; } if (this.y > height || this.y < 0) { this.speedY *= -1; } // Update rotation this.rotation += this.rotationSpeed; } display() { // Draw the circle with color gradient and rotation let gradientColor = lerpColor(this.color1, this.color2, map(this.y, 0, height, 0, 1)); fill(gradientColor); noStroke(); push(); translate(this.x, this.y); rotate(this.rotation); ellipse(0, 0, this.diameter, this.diameter); pop(); } }
I felt that my artwork needed some additional features to make it more engaging, so I decided to incorporate three new elements:
1. Interactive Drawing: Now, users can click and drag their mouse to draw colorful circles directly onto the canvas. This adds an interactive dimension to the artwork, allowing people to actively participate in its creation.
2.Dynamic Color Palette: To enhance visual appeal, I introduced a dynamic color palette. Each circle is filled with colors randomly selected from a predefined palette, adding variety and vibrancy to the overall composition.
3.Transparency Effect: To create a sense of depth and visual interest, I implemented a transparency effect. The transparency of each circle varies based on its diameter, resulting in a captivating depth effect as circles overlap on the canvas.
Final Output (Tap and drag the mouse anywhere in the canvas)
This is how it looks if the user added more circles:
Final Code:
let circles = []; let colorPalette = ['#FFC857', '#F4A35F', '#EE6C4D', '#F95738', '#FF5733', '#FF355E', '#D40C6B', '#7A00FF', '#0045FF', '#0088FF']; //Creating an array filled with color palettes. function setup() { createCanvas(800, 600); // Creating an initial set of circles for (let i = 0; i < 100; i++) { let x = random(width); let y = random(height); let diameter = random(10, 50); let colorIndex = floor(random(colorPalette.length)); let circle = new Circle(x, y, diameter, colorPalette[colorIndex]); circles.push(circle); } // Adding interactive features (just need to tap and drag) background(0); textAlign(CENTER, CENTER); textSize(36); fill(255); text("Click and drag to draw!", width / 2, height / 2); } function draw() { // Updating and displaying each circle for (let circle of circles) { circle.update(); circle.display(); } } function mouseDragged() { // Add a new circle at the mouse position when dragged let diameter = random(10, 50); let colorIndex = floor(random(colorPalette.length)); let circle = new Circle(mouseX, mouseY, diameter, colorPalette[colorIndex]); circles.push(circle); } // Defining Circle class class Circle { constructor(x, y, diameter, color) { this.x = x; this.y = y; this.diameter = diameter; this.color = color; this.speedX = random(-2, 2); this.speedY = random(-2, 2); this.rotation = random(TWO_PI); // Random initial rotation this.rotationSpeed = random(-0.05, 0.05); // Random rotation speed } update() { // Moving the circle this.x += this.speedX; this.y += this.speedY; // Bouncing off the walls if (this.x > width || this.x < 0) { this.speedX *= -1; } if (this.y > height || this.y < 0) { this.speedY *= -1; } // Updating rotaion this.rotation += this.rotationSpeed; } display() { // Drawing the circle with rotation and transparency effect push(); translate(this.x, this.y); rotate(this.rotation); fill(this.color); noStroke(); let alpha = map(this.diameter, 10, 50, 50, 200); // Varrying transparency based on diameter fill(red(this.color), green(this.color), blue(this.color), alpha); ellipse(0, 0, this.diameter, this.diameter); pop(); } }
Code I’m proud of: Initially, I found implementing the transparency effect challenging in my artwork. Understanding how to vary the transparency based on the diameter of each circle was tricky. However, I managed to overcome this difficulty by experimenting with the map()
function in the display()
method of the Circle
class. By mapping the diameter of each circle to a range of transparency values, I was able to achieve the desired effect. This involved adjusting the parameters of the map()
function until I achieved the desired transparency levels, ultimately resulting in a visually appealing depth effect as circles overlapped on the canvas. Overall, successfully implementing this feature added an extra dimension to my artwork that I’m proud of.
Additional Art Work: With Valentine’s Day approaching, I decided to enhance my artwork by making some adjustments to the code. Here’s the updated look!
Here’s the code for the Valentine’s Day themed artwork:
let hearts = []; let colorPalette = ['#FF4D6D', '#FF6381', '#FF7992', '#FF8BA3', '#FFA3B5', '#FFBFC7', '#FFD1D9', '#FFEDF2']; function setup() { createCanvas(800, 600); // Addinng a sweet message background(255); textAlign(CENTER, CENTER); textSize(36); fill(150); text("Happy Valentine's Day!", width / 2, height / 2 - 50); text("Click and drag to create love!", width / 2, height / 2 + 50); } function draw() { // Updating and displaying each heart for (let heart of hearts) { heart.update(); heart.display(); } } function mouseDragged() { // Adding a new heart at the mouse position when dragged let size = random(30, 100); let colorIndex = floor(random(colorPalette.length)); let heart = new Heart(mouseX, mouseY, size, colorPalette[colorIndex]); hearts.push(heart); } // Heart class definition class Heart { constructor(x, y, size, color) { this.x = x; this.y = y; this.size = size; this.color = color; this.speedX = random(-2, 2); this.speedY = random(-2, 2); this.rotation = random(TWO_PI); // Random initial rotation this.rotationSpeed = random(-0.05, 0.05); // Random rotation speed } update() { // Moving the heart this.x += this.speedX; this.y += this.speedY; // Bounce off the walls if (this.x > width || this.x < 0) { this.speedX *= -1; } if (this.y > height || this.y < 0) { this.speedY *= -1; } // Update rotation this.rotation += this.rotationSpeed; } display() { // Drawing the heart with rotation and transparency effect push(); translate(this.x, this.y); rotate(this.rotation); fill(this.color); noStroke(); let alpha = map(this.size, 30, 100, 50, 200); // Vary transparency based on size fill(red(this.color), green(this.color), blue(this.color), alpha); beginShape(); vertex(0, -this.size / 2); bezierVertex(this.size / 2, -this.size / 2, this.size, 0, 0, this.size); bezierVertex(-this.size, 0, -this.size / 2, -this.size / 2, 0, -this.size / 2); endShape(CLOSE); pop(); } }