Reflection: Floating Bubbles
This artwork is inspired by the simple joy of blowing soap bubbles we used to do as kids. Just like real bubbles, the circles appear wherever you click, float around randomly, and slowly fade away or pop. I wanted each click to feel like blowing a new batch of bubbles, watching them drift and disappear. The way they change color and move in different directions makes them feel alive, conveying the playful nature of real soap bubbles.
Structure
The Circle class manages each individual bubble’s movement, opacity, and lifespan, ensuring that they appear and disappear naturally over time. Functions like setup()
, draw()
, and mousePressed()
organize different parts of the code, keeping it easy to understand and modify.
Challenges
One issue was finding the right balance between movement and fading, so that that bubbles did not disappear too quickly while still feeling transient. Another challenge was making the interaction feel engaging, which I solved by adjusting the number of bubbles created per click and giving them different speeds and directions. Additionally, I had to optimize performance to prevent the sketch from slowing down over time, so circles are now removed once their lifespan ends.
Overall, I appreciate how this piece captures the lighthearted beauty of soap bubbles in a digital form. To make it more realistic, I’d try to make the direction that bubbles take more random and add the effect of abrupt popping.
// Array to store circles let circles = []; let circleSize = 50; let numCirclesPerClick = 5; // Number of circles generated per mouse click function setup() { createCanvas(windowWidth, windowHeight); noFill(); // No fill for circles, only stroke } function draw() { background(20, 20, 30, 50); // Loop through circles in reverse order for (let i = circles.length - 1; i >= 0; i--) { circles[i].update(); circles[i].display(); // Remove circle when its lifespan reaches zero if (circles[i].lifespan <= 0) { circles.splice(i, 1); } } } // Circle class (individual moving and fading circles) class Circle { constructor(x, y, size) { this.x = x; this.y = y; this.vx = random(-2, 2); // Assign random speed in x direction this.vy = random(-2, 2); // Assign random speed in y direction this.baseSize = size; this.size = size; this.opacity = random(100, 200); this.growthSpeed = random(0.5, 2); this.color = color(random(255), random(255), random(255)); this.lifespan = 200; // Circle disappears after a set time } // Update circle properties (position, size, opacity, lifespan) update() { this.x += this.vx; this.y += this.vy; this.size = this.baseSize + sin(frameCount * 0.05) * 10; // Oscillating size effect this.opacity -= 2; this.lifespan -= 2; } // Display the objects display() { stroke(this.color); strokeWeight(2); fill(this.color.levels[0], this.color.levels[1], this.color.levels[2], this.opacity); // fading effect ellipse(this.x, this.y, this.size, this.size); } } // generates multiple circles at the mouse click location function mousePressed() { for (let i = 0; i < numCirclesPerClick; i++) { circles.push(new Circle(mouseX, mouseY, circleSize)); } }