AI Firefly Meadow - Peaceful Night Scene - xelsed.ai

This sketch creates a peaceful animated night meadow where 70 glowing fireflies drift using Perlin noise and gently gravitate toward the mouse cursor, while 100 stars twinkle above against a gradient sky. Soft blur filters and fading trail rectangles give the fireflies a dreamy, organic glow.

🧪 Try This!

Experiment with the code by making these changes:

  1. Fill the sky with more fireflies — Increasing NUM_FIREFLIES creates a much denser, busier swarm of glowing lights across the meadow.
  2. Make trails longer and dreamier — Lowering the trail rectangle's opacity makes previous firefly positions fade out much more slowly, creating longer glowing light streaks.
  3. Change the firefly glow to blue — Swapping the glowColor turns every firefly's glow from warm yellow-green into a cool, magical blue.
Prefer the full editor? Open it there →

📖 About This Sketch

This sketch fills the screen with a calm nighttime meadow: a gradient sky fades from deep blue to blue-green, faint stars twinkle using Perlin noise, and dozens of fireflies wander around using organic noise-based movement while being gently pulled toward the mouse. The glow effect comes from p5.js's canvas blur filter combined with layered, semi-transparent circles, and the trailing light paths are created by drawing a nearly-invisible black rectangle over the whole canvas every frame instead of a fully opaque background.

The code is organized around two ES6 classes, Firefly and Star, each with its own update() (physics/animation logic) and display() (drawing logic) methods, plus a setup()/draw() loop that creates and cycles through arrays of these objects. By studying it you'll learn how to combine p5.Vector for steering behaviors, noise() for natural-looking randomness, lerpColor() for gradients, and drawingContext.filter for glow effects - all classic building blocks of generative art.

⚙️ How It Works

  1. When the sketch loads, setup() creates a full-window canvas and fills two arrays with 70 Firefly objects and 100 Star objects, each placed at a random position (stars only in the upper 60% of the screen, like a sky).
  2. Every frame, draw() first paints a fresh gradient sky by calling drawNightGradient(), then draws a nearly-transparent black rectangle over everything - because the black is only 5/255 opaque, old firefly positions don't fully disappear, leaving soft trailing glow paths behind moving fireflies.
  3. Still inside draw(), every star and firefly is updated and displayed in its own for loop, so their update() methods run first to move/animate them, then their display() methods draw them at their new position.
  4. Each Firefly uses Perlin noise (this.xoff, this.yoff) to generate a gentle wandering force, and separately calculates a vector pointing toward the mouse, blending both forces into its acceleration to create smooth, organic drifting that subtly follows your cursor.
  5. A timer inside each Firefly randomly toggles its glowState on and off every 60-180 frames, and while glowing, display() applies a CSS blur filter plus a soft transparent halo circle to create the pulsing glow look.
  6. If the browser window is resized, windowResized() rebuilds the canvas and regenerates all fireflies and stars from scratch so they fit the new dimensions.

🎓 Concepts You'll Learn

Perlin noise for organic motionVector-based steering behaviors (p5.Vector)Class-based particle systemsColor interpolation with lerpColorAlpha-based motion trailsCSS blur filters on canvas via drawingContextResponsive canvas with windowResized

📝 Code Breakdown

setup()

setup() runs once when the sketch starts. It's the right place to size your canvas and populate arrays of objects before the animation loop begins.

function setup() {
  createCanvas(windowWidth, windowHeight); // Create a full-window canvas
  noStroke(); // No outlines for shapes

  // Initialize fireflies
  for (let i = 0; i < NUM_FIREFLIES; i++) {
    fireflies.push(new Firefly(random(width), random(height)));
  }

  // Initialize stars in the upper 60% of the canvas
  for (let i = 0; i < NUM_STARS; i++) {
    stars.push(new Star(random(width), random(height * 0.6)));
  }
}
Line-by-line explanation (4 lines)

🔧 Subcomponents:

for-loop Create Fireflies for (let i = 0; i < NUM_FIREFLIES; i++) {

Creates NUM_FIREFLIES new Firefly objects at random positions and adds them to the fireflies array

for-loop Create Stars for (let i = 0; i < NUM_STARS; i++) {

Creates NUM_STARS new Star objects positioned only in the top 60% of the canvas to look like a sky

createCanvas(windowWidth, windowHeight);
Makes the canvas fill the entire browser window instead of a fixed size
noStroke();
Turns off outlines so all circles drawn later are solid, borderless shapes
fireflies.push(new Firefly(random(width), random(height)));
Creates a new Firefly object at a random x,y position anywhere on the canvas and adds it to the fireflies array
stars.push(new Star(random(width), random(height * 0.6)));
Creates a new Star, but restricts its y-position to the top 60% of the screen so stars only appear in the 'sky' area

draw()

draw() runs continuously at roughly 60 frames per second. Because it draws a see-through rectangle instead of clearing the background completely, it produces the classic 'fading trail' technique used in generative art.

🔬 This near-invisible rectangle is what creates the glowing trail effect instead of a normal background(). What happens if you change the alpha value 5 to something much higher, like 40 or 100?

  fill(0, 5); // Very slight opacity (lower number = longer trails)
  rect(0, 0, width, height);
function draw() {
  // 1. Draw the gradient nighttime background
  drawNightGradient();

  // 2. Draw a slightly transparent rectangle over the canvas
  // This creates the "trailing glow path" effect by making previous frames fade out.
  fill(0, 5); // Very slight opacity (lower number = longer trails)
  rect(0, 0, width, height);

  // 3. Update and display all stars
  for (let star of stars) {
    star.update();
    star.display();
  }

  // 4. Update and display all fireflies
  for (let firefly of fireflies) {
    firefly.update();
    firefly.display();
  }
}
Line-by-line explanation (7 lines)

🔧 Subcomponents:

for-loop Update & Display Stars for (let star of stars) {

Loops through every star, animating its twinkle and drawing it

for-loop Update & Display Fireflies for (let firefly of fireflies) {

Loops through every firefly, moving it and drawing its glow

drawNightGradient();
Calls the helper function that paints the gradient sky across the whole canvas each frame
fill(0, 5); // Very slight opacity (lower number = longer trails)
Sets a fill color of black with only 5 out of 255 opacity - almost invisible but not fully transparent
rect(0, 0, width, height);
Draws that barely-visible black rectangle over the entire canvas, which slightly darkens everything drawn in previous frames, creating fading light trails
star.update();
Recalculates the star's twinkle brightness for this frame
star.display();
Draws the star at its position with its current twinkle transparency
firefly.update();
Moves the firefly according to noise-based wandering and mouse attraction, and updates its glow timer
firefly.display();
Draws the firefly's glowing body if it is currently in its 'on' glow state

drawNightGradient()

This function shows how to build a custom gradient using lerpColor() and a loop, since p5.js has no built-in gradient() function. It's a useful technique for backgrounds in any generative sketch.

🔬 This loop draws the gradient one line per pixel row. What happens if you change the loop step to skip rows, like 'y += 4', to trade smoothness for speed?

  for (let y = 0; y < height; y++) {
    let inter = map(y, 0, height, 0, 1); // Interpolation amount based on y position
    let c = lerpColor(c1, c2, inter);    // Blend the two colors
    stroke(c); // Set stroke to the interpolated color
    line(0, y, width, y); // Draw a horizontal line across the canvas
  }
function drawNightGradient() {
  // Deep blue at the top, darker blue-green at the bottom
  let c1 = color(0, 0, 50);   // Top color: Deep night blue
  let c2 = color(0, 30, 40);  // Bottom color: Dark meadow green-blue

  for (let y = 0; y < height; y++) {
    let inter = map(y, 0, height, 0, 1); // Interpolation amount based on y position
    let c = lerpColor(c1, c2, inter);    // Blend the two colors
    stroke(c); // Set stroke to the interpolated color
    line(0, y, width, y); // Draw a horizontal line across the canvas
  }
}
Line-by-line explanation (6 lines)

🔧 Subcomponents:

for-loop Draw Gradient Lines for (let y = 0; y < height; y++) {

Draws one horizontal line per pixel row, each blended slightly more toward the bottom color, creating a smooth vertical gradient

let c1 = color(0, 0, 50); // Top color: Deep night blue
Defines the color used at the very top of the sky
let c2 = color(0, 30, 40); // Bottom color: Dark meadow green-blue
Defines the color used at the very bottom of the canvas
let inter = map(y, 0, height, 0, 1); // Interpolation amount based on y position
Converts the current row number y into a 0-1 fraction representing how far down the canvas we are
let c = lerpColor(c1, c2, inter); // Blend the two colors
Blends between the top and bottom colors based on that fraction - near the top it's mostly c1, near the bottom mostly c2
stroke(c); // Set stroke to the interpolated color
Sets the line drawing color to the blended color for this row
line(0, y, width, y); // Draw a horizontal line across the canvas
Draws a single-pixel-tall horizontal line spanning the full width, at height y, in the blended color

windowResized()

windowResized() is a special p5.js function that automatically runs whenever the browser window changes size. Rebuilding your object arrays here keeps positions proportional to the new canvas instead of leaving them clustered in one corner.

function windowResized() {
  resizeCanvas(windowWidth, windowHeight); // Adjust canvas size

  // Re-initialize stars and fireflies to fit the new canvas dimensions
  fireflies = [];
  stars = [];
  for (let i = 0; i < NUM_FIREFLIES; i++) {
    fireflies.push(new Firefly(random(width), random(height)));
  }
  for (let i = 0; i < NUM_STARS; i++) {
    stars.push(new Star(random(width), random(height * 0.6)));
  }
}
Line-by-line explanation (3 lines)

🔧 Subcomponents:

for-loop Rebuild Fireflies for (let i = 0; i < NUM_FIREFLIES; i++) {

Recreates all fireflies at fresh random positions matching the new canvas size

for-loop Rebuild Stars for (let i = 0; i < NUM_STARS; i++) {

Recreates all stars at fresh random positions matching the new canvas size

resizeCanvas(windowWidth, windowHeight); // Adjust canvas size
This p5.js function resizes the existing canvas to match the browser window's new dimensions
fireflies = [];
Empties the fireflies array so old positions (based on the old canvas size) are discarded
stars = [];
Empties the stars array for the same reason

Firefly constructor

The constructor runs once when 'new Firefly(...)' is called, setting up all the starting properties (position, speed limits, noise seeds, glow timing) that update() and display() will use every frame.

constructor(x, y) {
    // Position, velocity, acceleration vectors
    this.pos = createVector(x, y);
    this.vel = createVector();
    this.acc = createVector();

    this.maxSpeed = 1.0; // Maximum movement speed
    this.maxForce = 0.03; // Maximum force applied for movement

    // Perlin noise offsets for organic "floating" movement
    this.xoff = random(1000); // Random start point for noise in x direction
    this.yoff = random(1000); // Random start point for noise in y direction

    // Glow pulsing properties
    this.glowState = false; // true = glowing, false = off
    this.glowTimer = 0;
    this.glowDuration = random(60, 180); // How long it stays on/off (in frames)
    this.glowColor = color(200, 255, 100); // Yellow-green glow color
    this.glowHaloRadius = 15; // Size of the blur effect for the halo
  }
Line-by-line explanation (6 lines)
this.pos = createVector(x, y);
Stores the firefly's position as a p5.Vector so x and y can be manipulated together
this.vel = createVector();
Creates an empty velocity vector (0,0) that will accumulate movement over time
this.acc = createVector();
Creates an empty acceleration vector that forces (noise, mouse attraction) will be added to each frame
this.xoff = random(1000); // Random start point for noise in x direction
Picks a random starting point along the Perlin noise curve so every firefly wanders differently instead of identically
this.glowDuration = random(60, 180); // How long it stays on/off (in frames)
Sets a random number of frames (1-3 seconds at 60fps) before the firefly's glow toggles on or off
this.glowColor = color(200, 255, 100); // Yellow-green glow color
Defines the yellow-green color used for this firefly's glow, mimicking real firefly bioluminescence

Firefly.update()

update() is where classic steering-behavior physics happens: forces are accumulated into acceleration, acceleration changes velocity, and velocity changes position - the same pattern used in flocking simulations, particle systems, and games.

🔬 These four lines make fireflies wrap seamlessly around the screen edges. What happens if you remove all four lines - where do fireflies go over time?

    if (this.pos.x < 0) this.pos.x = width;
    if (this.pos.x > width) this.pos.x = 0;
    if (this.pos.y < 0) this.pos.y = height;
    if (this.pos.y > height) this.pos.y = 0;

🔬 The random(60, 180) range controls how long fireflies stay lit or dark. What happens if you shrink it to random(5, 15) for rapid flickering?

    this.glowTimer++;
    if (this.glowTimer > this.glowDuration) {
      this.glowState = !this.glowState; // Toggle glow state (on/off)
      this.glowTimer = 0; // Reset timer
      this.glowDuration = random(60, 180); // Set a new random duration for the next state
    }
update() {
    // --- Noise-based organic movement ---
    // Generate Perlin noise values between -1 and 1
    let noiseX = noise(this.xoff) * 2 - 1;
    let noiseY = noise(this.yoff) * 2 - 1;

    // Create a force vector from the noise values
    let noiseForce = createVector(noiseX, noiseY);
    noiseForce.setMag(this.maxForce * 0.4); // Apply a subtle noise force
    this.acc.add(noiseForce);

    // Increment noise offsets to create continuous movement
    this.xoff += 0.01;
    this.yoff += 0.01;

    // --- Mouse attraction ---
    let mouse = createVector(mouseX, mouseY); // Get mouse position
    let dir = p5.Vector.sub(mouse, this.pos); // Calculate direction vector from firefly to mouse
    dir.normalize(); // Normalize to get only direction (unit vector)
    dir.mult(this.maxForce * 0.15); // Apply a very subtle attraction force towards the mouse
    this.acc.add(dir);

    // --- Apply movement ---
    this.vel.add(this.acc); // Add acceleration to velocity
    this.vel.limit(this.maxSpeed); // Limit velocity to maxSpeed
    this.pos.add(this.vel); // Add velocity to position
    this.acc.mult(0); // Reset acceleration for the next frame

    // --- Wrap around edges ---
    // If firefly goes off one side, it reappears on the opposite side
    if (this.pos.x < 0) this.pos.x = width;
    if (this.pos.x > width) this.pos.x = 0;
    if (this.pos.y < 0) this.pos.y = height;
    if (this.pos.y > height) this.pos.y = 0;

    // --- Glow pulsing logic ---
    this.glowTimer++;
    if (this.glowTimer > this.glowDuration) {
      this.glowState = !this.glowState; // Toggle glow state (on/off)
      this.glowTimer = 0; // Reset timer
      this.glowDuration = random(60, 180); // Set a new random duration for the next state
    }
  }
Line-by-line explanation (13 lines)

🔧 Subcomponents:

conditional Wrap Left Edge if (this.pos.x < 0) this.pos.x = width;

Teleports the firefly to the right side when it drifts off the left edge

conditional Wrap Right Edge if (this.pos.x > width) this.pos.x = 0;

Teleports the firefly to the left side when it drifts off the right edge

conditional Toggle Glow State if (this.glowTimer > this.glowDuration) {

Flips the firefly between glowing and dark states once its randomized timer expires

let noiseX = noise(this.xoff) * 2 - 1;
noise() returns a value between 0 and 1; multiplying by 2 and subtracting 1 remaps it to -1 to 1 so movement can go in either direction
noiseForce.setMag(this.maxForce * 0.4); // Apply a subtle noise force
Sets the strength (magnitude) of the wandering force to 40% of maxForce, keeping the noise-based movement gentle
this.acc.add(noiseForce);
Adds the wandering force into the firefly's overall acceleration for this frame
let dir = p5.Vector.sub(mouse, this.pos); // Calculate direction vector from firefly to mouse
Subtracting the firefly's position from the mouse position gives a vector pointing from the firefly toward the mouse
dir.normalize(); // Normalize to get only direction (unit vector)
Shrinks or grows the vector to length 1 so only its direction matters, not its distance
dir.mult(this.maxForce * 0.15); // Apply a very subtle attraction force towards the mouse
Scales the direction vector down to a small force so the mouse pull is subtle, not instant snapping
this.vel.add(this.acc); // Add acceleration to velocity
Standard physics: acceleration changes velocity
this.vel.limit(this.maxSpeed); // Limit velocity to maxSpeed
Prevents the firefly from ever moving faster than maxSpeed, keeping motion calm
this.pos.add(this.vel); // Add velocity to position
Standard physics: velocity changes position, actually moving the firefly
this.acc.mult(0); // Reset acceleration for the next frame
Clears acceleration to zero so forces don't accumulate forever - they need to be reapplied fresh every frame
if (this.pos.x < 0) this.pos.x = width;
If the firefly drifts off the left edge, it reappears on the right edge, creating a seamless wrap-around world
this.glowTimer++;
Counts up by 1 every frame, tracking how long the firefly has been in its current glow state
this.glowState = !this.glowState; // Toggle glow state (on/off)
Flips true to false or false to true, switching the firefly between glowing and dark

Firefly.display()

display() demonstrates how to reach past p5.js's normal drawing functions into the underlying browser canvas context (drawingContext) to use native CSS filter effects like blur() for glow effects p5.js doesn't provide out of the box.

🔬 The blur amount comes from this.glowHaloRadius (set to 15 in the constructor). What happens visually if every firefly used a huge blur radius, like 40?

      drawingContext.filter = `blur(${this.glowHaloRadius}px)`;
      fill(this.glowColor);
      circle(this.pos.x, this.pos.y, 8); // Draw the small core firefly body

      // Reset the filter immediately after drawing the blurred circle
      drawingContext.filter = 'none';
display() {
    if (this.glowState) {
      // Create the soft glow halo using CSS blur filter
      // drawingContext is the raw WebGL/Canvas2D context
      drawingContext.filter = `blur(${this.glowHaloRadius}px)`;
      fill(this.glowColor);
      circle(this.pos.x, this.pos.y, 8); // Draw the small core firefly body

      // Reset the filter immediately after drawing the blurred circle
      drawingContext.filter = 'none';

      // Draw a slightly larger, more transparent circle for an even softer outer glow
      // This adds depth to the glow effect
      fill(red(this.glowColor), green(this.glowColor), blue(this.glowColor), 100);
      circle(this.pos.x, this.pos.y, 16);
    }
  }
Line-by-line explanation (6 lines)

🔧 Subcomponents:

conditional Only Draw When Glowing if (this.glowState) {

Skips drawing anything when the firefly is in its 'off' state, making it invisible

if (this.glowState) {
Only draws the firefly if it's currently in its glowing (on) state - otherwise it's completely invisible
drawingContext.filter = `blur(${this.glowHaloRadius}px)`;
Accesses the raw canvas rendering context to apply a CSS-style blur filter to everything drawn next
circle(this.pos.x, this.pos.y, 8); // Draw the small core firefly body
Draws a small solid circle which the blur filter turns into a soft glowing dot
drawingContext.filter = 'none';
Turns the blur filter back off immediately so it doesn't affect other shapes drawn afterward
fill(red(this.glowColor), green(this.glowColor), blue(this.glowColor), 100);
Extracts the red, green, and blue components of the glow color and reuses them with lower alpha (100) for a translucent outer halo
circle(this.pos.x, this.pos.y, 16);
Draws a larger, more transparent circle on top to add extra softness and depth to the glow

Star constructor

The Star constructor is intentionally simple compared to Firefly since stars are static - they only need a position, size, and a noise seed for twinkling, no velocity or acceleration.

constructor(x, y) {
    this.pos = createVector(x, y);
    this.size = random(1, 3); // Random size for the star

    // Perlin noise offset for organic twinkling
    this.twinkleOffset = random(1000);
  }
Line-by-line explanation (3 lines)
this.pos = createVector(x, y);
Stores the star's fixed position as a vector
this.size = random(1, 3); // Random size for the star
Gives each star a slightly different tiny size between 1 and 3 pixels for visual variety
this.twinkleOffset = random(1000);
Picks a random starting point in Perlin noise space so every star twinkles on its own independent schedule

Star.update()

This is a simple but effective use of Perlin noise: instead of randomly picking a brightness every frame (which would look like static), noise() produces smoothly changing values over time, giving a natural twinkling effect.

🔬 The alpha currently ranges from 100 (dim but visible) to 255 (fully bright). What happens if you lower the minimum to 0, so stars sometimes disappear completely?

    this.alpha = map(noise(this.twinkleOffset), 0, 1, 100, 255); // Alpha varies from 100 to 255
    this.twinkleOffset += 0.02; // Increment offset for continuous twinkling motion
update() {
    // Map noise value to alpha for twinkling effect
    this.alpha = map(noise(this.twinkleOffset), 0, 1, 100, 255); // Alpha varies from 100 to 255
    this.twinkleOffset += 0.02; // Increment offset for continuous twinkling motion
  }
Line-by-line explanation (2 lines)
this.alpha = map(noise(this.twinkleOffset), 0, 1, 100, 255); // Alpha varies from 100 to 255
Takes a noise value (0-1) and remaps it to a transparency range between 100 (dimmer) and 255 (fully bright), creating a smooth twinkle rather than random flicker
this.twinkleOffset += 0.02; // Increment offset for continuous twinkling motion
Moves forward along the noise curve each frame so the twinkle brightness continuously and smoothly changes

Star.display()

display() is kept separate from update() so animation logic (calculating alpha) is cleanly separated from drawing logic (putting pixels on screen) - a common and useful pattern in object-oriented p5.js sketches.

display() {
    fill(255, this.alpha); // White color with varying transparency
    circle(this.pos.x, this.pos.y, this.size); // Draw the star as a small circle
  }
Line-by-line explanation (2 lines)
fill(255, this.alpha); // White color with varying transparency
Sets the fill to white with the current twinkle transparency calculated in update()
circle(this.pos.x, this.pos.y, this.size); // Draw the star as a small circle
Draws the star as a tiny circle at its fixed position using its random size

📦 Key Variables

NUM_FIREFLIES number

Constant controlling how many Firefly objects are created in the meadow

const NUM_FIREFLIES = 70;
NUM_STARS number

Constant controlling how many Star objects are created in the sky

const NUM_STARS = 100;
fireflies array

Holds every Firefly object currently in the scene so they can be updated and displayed each frame

let fireflies = [];
stars array

Holds every Star object currently in the scene so they can be updated and displayed each frame

let stars = [];

🔧 Potential Improvements (4)

Here are some ways this code could be enhanced:

PERFORMANCE drawNightGradient()

This function redraws a full-height gradient using one line() call per pixel row, every single frame, even though the gradient itself never changes. On a tall window this can mean hundreds of draw calls per frame just for the background.

💡 Render the gradient once into an offscreen buffer with createGraphics() during setup() (or on windowResized()), then simply image() that buffer to the canvas each frame instead of recalculating it 60 times per second.

BUG Firefly.update()

When a firefly's position is exactly equal to the mouse position, p5.Vector.sub(mouse, this.pos) produces a zero-length vector, and calling .normalize() on it can produce NaN, which would make the firefly's position corrupt (NaN, NaN) and stop it from ever being drawn again.

💡 Check the vector's magnitude before normalizing, e.g. 'if (dir.mag() > 0.01) { dir.normalize(); ... }', or add a tiny random offset before subtracting to avoid an exact zero vector.

STYLE draw()

The for...of loop variables are named 'star' and 'firefly', which are easy to visually confuse with the Star and Firefly class names declared elsewhere in the file, especially for beginners reading the code top to bottom.

💡 Rename loop variables to something clearly distinct, like 's' and 'f', or 'currentStar' and 'currentFirefly', to make it obvious they're individual instances, not the classes themselves.

FEATURE Firefly class

Fireflies always glow the same yellow-green color and pulse at the same size (8px core, 16px halo), so despite the noise-based movement variety, every firefly looks visually identical when lit.

💡 Give each firefly a slightly randomized hue, core size, or halo radius in the constructor (e.g. this.glowColor = color(180 + random(-20,20), 255, random(80,140))) so the swarm feels more organic and varied.

🔄 Code Flow

Code flow showing setup, draw, drawnightgradient, windowresized, fireflyconstructor, fireflyupdate, fireflydisplay, starconstructor, starupdate, stardisplay

💡 Click on function names in the diagram to jump to their code

graph TD start[Start] --> setup[setup] setup --> setup-firefly-loop[Create Fireflies (for-loop)] setup-firefly-loop --> fireflyconstructor[fireflyconstructor] setup --> setup-star-loop[Create Stars (for-loop)] setup-star-loop --> starconstructor[starconstructor] setup --> draw[draw loop] draw --> drawnightgradient[drawnightgradient] draw --> gradient-loop[Draw Gradient Lines (for-loop)] gradient-loop --> draw draw --> draw-star-loop[Update & Display Stars (for-loop)] draw-star-loop --> starupdate[starupdate] draw-star-loop --> stardisplay[stardisplay] draw --> draw-firefly-loop[Update & Display Fireflies (for-loop)] draw-firefly-loop --> fireflyupdate[fireflyupdate] draw-firefly-loop --> fireflydisplay[fireflydisplay] fireflyupdate --> wrap-x-low[Wrap Left Edge (conditional)] fireflyupdate --> wrap-x-high[Wrap Right Edge (conditional)] fireflyupdate --> glow-toggle[Toggle Glow State (conditional)] glow-toggle --> glow-display-check[Only Draw When Glowing (conditional)] glow-display-check --> fireflydisplay draw --> windowresized[windowresized] windowresized --> resize-firefly-loop[Rebuild Fireflies (for-loop)] resize-firefly-loop --> fireflyconstructor windowresized --> resize-star-loop[Rebuild Stars (for-loop)] resize-star-loop --> starconstructor click setup href "#fn-setup" click setup-firefly-loop href "#sub-setup-firefly-loop" click fireflyconstructor href "#fn-fireflyconstructor" click setup-star-loop href "#sub-setup-star-loop" click starconstructor href "#fn-starconstructor" click draw href "#fn-draw" click drawnightgradient href "#fn-drawnightgradient" click gradient-loop href "#sub-gradient-loop" click draw-star-loop href "#sub-draw-star-loop" click starupdate href "#fn-starupdate" click stardisplay href "#fn-stardisplay" click draw-firefly-loop href "#sub-draw-firefly-loop" click fireflyupdate href "#fn-fireflyupdate" click fireflydisplay href "#fn-fireflydisplay" click wrap-x-low href "#sub-wrap-x-low" click wrap-x-high href "#sub-wrap-x-high" click glow-toggle href "#sub-glow-toggle" click glow-display-check href "#sub-glow-display-check" click windowresized href "#fn-windowresized" click resize-firefly-loop href "#sub-resize-firefly-loop" click resize-star-loop href "#sub-resize-star-loop"

❓ Frequently Asked Questions

What visual experience does the AI Firefly Meadow sketch provide?

The sketch creates a tranquil nighttime meadow scene featuring glowing fireflies that pulse and drift toward the mouse cursor, set against a backdrop of twinkling stars.

How can users interact with the AI Firefly Meadow sketch?

Users can interact by moving their mouse across the canvas, which causes the fireflies to respond by drifting towards the cursor.

What creative coding concept is showcased in the AI Firefly Meadow sketch?

The sketch demonstrates the use of object-oriented programming to create dynamic visual elements, such as fireflies and stars, that respond to user interactions.

Preview

AI Firefly Meadow - Peaceful Night Scene - xelsed.ai - p5.js creative coding sketch preview
Sketch Preview
Code flow diagram showing the structure of AI Firefly Meadow - Peaceful Night Scene - xelsed.ai - Code flow showing setup, draw, drawnightgradient, windowresized, fireflyconstructor, fireflyupdate, fireflydisplay, starconstructor, starupdate, stardisplay
Code Flow Diagram