Inspiration
For this project, the task was to create a generative art piece. I decided I wanted to create something that captured the beauty of natural randomness, yet felt interactive and personal. I really love stargazing so this idea was immediately accompanied by a desire to incorporate stars (in a night sky setting) in some way. I thought it would be interesting to also use the stars to make randomly generated constellations. Initially, most of my ideas were all over the place and ended up progressing along with different stages of project.
Concept
After combining all of these concepts and also trying to add an element of interactivity, I arrived at a more cohesive idea. This piece essentially generates stars that slowly drift across the canvas and form constellations by connecting with nearby stars. These connections fade as the stars move farther apart, creating an ever-changing night sky. By clicking on the canvas, users can add new stars, and hovering the mouse near existing stars creates connections with the mouse pointer, making the viewer an active part of the art. I tried to replicate a portion of the night sky by creating a background gradient, which shifts from dark blue to a purplish hue.
Implementation
Here’s what it looks like!
The core of the project focuses on the generative placement and connection of stars, while other features such as mouse interactions and background gradients enhance the experience.
Most of the functionality of the code resides in the Star()
class. I also initially created a global variable numStars
which controls the initial number of stars that appear on the canvas (currently set to 70). However, more stars can be added when the user clicks on the screen.
Here are important aspects of the code that I’m proud of :))
1. Generating Stars and Constellations
The star generation begins by randomly placing stars across the canvas. Each star drifts slowly, giving the impression of a calm, subtly changing night sky. The stars are connected by lines if they are within a specific distance from each other, creating constellations. These lines fade with increasing distance between the stars they connect and disappear completely once they cross a certain threshold. The distance threshold is adjustable (maxDistance
), allowing for varying constellations as stars drift closer or further from one another.
/ Connecting stars that are within a certain distance
connect(stars) {
for (let i = 0; i < stars.length; i++) {
let d = dist(this.x, this.y, stars[i].x, stars[i].y);
if (d < maxDistance) {
stroke(255, 255, 255, map(d, 0, maxDistance, 255, 0)); // making line fade as distance increases
line(this.x, this.y, stars[i].x, stars[i].y);
}
}
}
2. User Interaction
User interaction is a key feature of the project. Clicking anywhere on the canvas creates a new star at the mouse’s location.
// Adding a new star at the mouse position when the mouse is clicked
function mousePressed() {
let size = random(2, 5); // the star created has a randomized size
stars.push(new Star(mouseX, mouseY, size)); // creating a new star at the mouse position (with given size)
}
In addition to adding stars, the mouse also exerts an influence on the stars already in place. When the mouse hovers near a star, stronger and thicker connections are drawn between the star and the mouse, creating a sense of gravitational pull. This connection changes based on the distance between the mouse and the stars, offering a layered sense of interactivity.
// Connecting stars according to mouse position
mouseConnect() {
let mouseDist = dist(this.x, this.y, mouseX, mouseY);
// If the star is within the influence of the mouse, create more prominent connections
if (mouseDist < mouseInfluenceDistance) {
stroke(233, 217, 255, map(mouseDist, 0, mouseInfluenceDistance, 255, 50)); // Stronger lines with mouse
strokeWeight(map(mouseDist, 0, mouseInfluenceDistance, 2, 0.5)); // Thicker lines near the mouse
line(this.x, this.y, mouseX, mouseY); // Draw line to the mouse position
}
}
3. Gradient Background
The background gradient is crucial to creating a more realistic cosmic atmosphere. A vertical gradient transitions from a deep, dark blue at the top to a lighter, purplish hue at the bottom, simulating the natural gradient of a night sky fading into early dawn. This gradient creates a contrast to the white stars and their connections, making the work feel more immersive. In creating this gradient, I learnt how to use lerpColor()
, which allowed me to smoothly blend two colors based on a transition value. By mapping the vertical position of each line to a gradient value, I was able to simulate the soft shift from night to early morning. The setGradient()
function essentially draws horizontal lines from the top to the bottom of the canvas (slightly changing the color each time to create a smooth gradient).
// Creating a vertical gradient
function setGradient(x, y, w, h, c1, c2) {
for (let i = y; i <= y + h; i++) {
let inter = map(i, y, y + h, 0, 1);
let c = lerpColor(c1, c2, inter); // when inter is 0, the colour is c1 and when inter is 1, the colour is c2 (for any other value it is a mix of c1 and c2)
stroke(c);
line(x, i, x + w, i); // drawing a line across the width of the gradient area
}
}
Reflections and Further Improvements
This assignment gave me the chance to play around with randomness and interactivity in a simple yet engaging way. I enjoyed seeing how small things like mouse movement and clicks could bring the stars to life and create an immersive atmosphere. The project feels peaceful yet active, and I’m happy with how the core mechanics came together.
Looking ahead, I’d like to add more depth to the stars—maybe a twinkling effect or layered constellations with different star types. It could also be interesting to introduce sound, where each star interaction triggers a soft note, giving the project an audio element. Another idea is to have the background gradient shift gradually over time, mimicking the change from night to dawn for added realism. I could maybe also experiment with adding other celestial bodies like planets and nebulae.
Overall, I am pretty proud of how this turned out and look forward to making more advanced projects :))