AI Firework Show - Click to Launch Explosions

This sketch creates an interactive fireworks show where clicking anywhere launches a rocket that streaks upward and bursts into a shower of colorful particles. Multiple fireworks can be in flight or exploding simultaneously, and a semi-transparent background creates trailing light streaks against a dark night sky.

🧪 Try This!

Experiment with the code by making these changes:

  1. Slow-motion fireworks — Reducing the launch speed makes rockets drift up slowly for a more dramatic, cinematic feel.
  2. Mega explosions — Cranking up the particle count range creates much denser, more spectacular bursts.
  3. Longer glowing trails — Lowering the background alpha makes old frames linger longer, so rockets and sparks leave longer streaking trails.
Prefer the full editor? Open it there →

📖 About This Sketch

This sketch turns mouse clicks into fireworks: each click launches a bright rocket from the bottom of the screen toward the click point, and once it arrives it bursts into 30-50 particles that scatter outward, fall under gravity, and fade away. It's a great example of a lightweight particle system built entirely from plain JavaScript objects and p5.Vector, without any classes. Key techniques on display include vector math for movement and direction, array-based state management with splice() for cleanup, and using a semi-transparent background() call to create glowing motion trails instead of hard-edged animation.

The code is organized around one global array, fireworks, that holds every rocket and explosion currently on screen, plus a small helper function explode() that converts a rocket into a burst of particles. setup() just prepares the canvas and color palette, mousePressed() adds a new rocket object to the array, and draw() loops through that array every frame to move, draw, and eventually delete each firework. Studying this sketch teaches you how to manage many independent animated objects with a single array and a couple of well-placed loops.

⚙️ How It Works

  1. When the page loads, setup() creates a full-window canvas, defines five hex-color strings in the cols array, and paints the canvas almost-black to set the night-sky mood.
  2. Every time the mouse is pressed, mousePressed() calculates a vector from the bottom-center of the screen toward the click position, sets its length (speed) to 8, and pushes a new firework object into the fireworks array with a random color from cols.
  3. On every frame, draw() first paints a translucent dark rectangle over the whole canvas instead of fully clearing it - this partial fade is what makes moving points leave short glowing trails instead of vanishing instantly.
  4. draw() then loops backward through the fireworks array: any rocket that hasn't exploded yet moves along its velocity vector and is drawn as a single bright point, while explode() is triggered once the rocket comes within 10 pixels of its target.
  5. Once a firework has exploded, draw() instead loops through its list of particles, applying a small downward gravity nudge to each one's velocity, moving it, counting down its life, and drawing it with fading alpha based on remaining life.
  6. Dead particles are removed with splice() as soon as their life reaches zero, and once a firework's particle list is completely empty the whole firework object is removed from the fireworks array, keeping memory use bounded.

🎓 Concepts You'll Learn

p5.Vector for movement and directionParticle systems with plain objectsArray management with push/spliceAlpha transparency for motion trailsRandom color and value selectionSimulated gravity via velocity updates

📝 Code Breakdown

setup()

setup() runs once when the sketch starts. It's the right place to size the canvas and initialize any starting data, like the color palette used throughout the sketch.

function setup(){
  createCanvas(windowWidth,windowHeight);
  cols=['#ff4b5c','#ffd93d','#4cd137','#00a8ff','#9b59b6'];
  background(3,5,15);
}
Line-by-line explanation (3 lines)
createCanvas(windowWidth,windowHeight);
Makes the canvas fill the entire browser window so fireworks can launch from anywhere on screen.
cols=['#ff4b5c','#ffd93d','#4cd137','#00a8ff','#9b59b6'];
Defines five hex color strings that will be picked randomly for each firework's color.
background(3,5,15);
Paints the canvas a very dark navy/black once, creating the night sky before any fireworks appear.

draw()

draw() runs continuously at the browser's frame rate, forming the animation engine of the sketch. Because it loops through the fireworks array every single frame, everything you see - rockets rising, explosions bursting, particles fading - is the cumulative result of tiny per-frame updates to position, velocity, and life.

🔬 The 0.08 added to p.v.y each frame is the gravity pulling particles down. What happens if you change it to 0.3? What if you make it negative like -0.05?

      for(let j=f.parts.length-1;j>=0;j--){
        let p=f.parts[j];p.v.y+=0.08;p.p.add(p.v);p.life--;
        stroke(red(f.c),green(f.c),blue(f.c),p.life);strokeWeight(2);point(p.p.x,p.p.y);
        if(p.life<=0)f.parts.splice(j,1);
      }
function draw(){
  background(3,5,15,40);
  for(let i=fireworks.length-1;i>=0;i--){
    let f=fireworks[i];
    if(!f.exploded){
      f.p.add(f.v);
      stroke(255);strokeWeight(3);point(f.p.x,f.p.y);
      if(p5.Vector.dist(f.p,f.t)<10)explode(f);
    }else{
      for(let j=f.parts.length-1;j>=0;j--){
        let p=f.parts[j];p.v.y+=0.08;p.p.add(p.v);p.life--;
        stroke(red(f.c),green(f.c),blue(f.c),p.life);strokeWeight(2);point(p.p.x,p.p.y);
        if(p.life<=0)f.parts.splice(j,1);
      }
      if(!f.parts.length)fireworks.splice(i,1);
    }
  }
}
Line-by-line explanation (10 lines)

🔧 Subcomponents:

for-loop Fireworks Array Loop for(let i=fireworks.length-1;i>=0;i--){

Iterates backward through every active firework so items can be safely removed with splice() during the loop.

conditional Unexploded Rocket Check if(!f.exploded){

Handles movement and drawing of a rocket that is still flying up toward its target.

conditional Reached Target Check if(p5.Vector.dist(f.p,f.t)<10)explode(f);

Detects when the rocket is close enough to its click target and triggers the explosion.

for-loop Particle Update Loop for(let j=f.parts.length-1;j>=0;j--){

Updates position, gravity, and lifespan for every particle in an exploded firework, drawing each one.

conditional Remove Dead Particle if(p.life<=0)f.parts.splice(j,1);

Deletes a particle from the array once its life counter runs out.

conditional Remove Spent Firework if(!f.parts.length)fireworks.splice(i,1);

Removes the entire firework object once all of its particles have faded away.

background(3,5,15,40);
Draws a mostly-opaque dark rectangle over the whole canvas instead of clearing it completely, which lets previous frames partially show through and creates glowing trails.
for(let i=fireworks.length-1;i>=0;i--){
Loops through the fireworks array backward so removing items with splice() doesn't skip the next element.
let f=fireworks[i];
Grabs the current firework object to work with in this iteration.
f.p.add(f.v);
Moves the rocket's position by adding its velocity vector, using p5.Vector's add() method.
stroke(255);strokeWeight(3);point(f.p.x,f.p.y);
Draws the still-flying rocket as a thick white point at its current position.
if(p5.Vector.dist(f.p,f.t)<10)explode(f);
Checks the distance between the rocket and its target point; once it's within 10 pixels, the explode() function is called.
let p=f.parts[j];p.v.y+=0.08;p.p.add(p.v);p.life--;
Grabs a particle, nudges its vertical velocity downward to simulate gravity, moves it, and decreases its remaining life.
stroke(red(f.c),green(f.c),blue(f.c),p.life);strokeWeight(2);point(p.p.x,p.p.y);
Draws the particle using the firework's color but with alpha (transparency) equal to the particle's remaining life, so it fades out as life decreases.
if(p.life<=0)f.parts.splice(j,1);
Removes a particle from the array once its life has fully counted down to zero.
if(!f.parts.length)fireworks.splice(i,1);
Once a firework has no particles left, it's removed entirely from the fireworks array to keep the array small.

mousePressed()

mousePressed() is a p5.js event function that fires once every time the mouse button is clicked. Here it's used to spawn new data into the fireworks array, which is exactly the pattern used for click-to-spawn interactions in countless creative coding sketches.

🔬 This vector always starts from the bottom-center of the screen. What happens if you change width/2 to mouseX so rockets launch straight up from wherever you click instead?

  let dir=createVector(mouseX-width/2,mouseY-height);
  dir.setMag(8);
function mousePressed(){
  let dir=createVector(mouseX-width/2,mouseY-height);
  dir.setMag(8);
  fireworks.push({p:createVector(width/2,height),v:dir,t:createVector(mouseX,mouseY),exploded:false,parts:[],c:random(cols)});
}
Line-by-line explanation (3 lines)
let dir=createVector(mouseX-width/2,mouseY-height);
Creates a vector pointing from the bottom-center of the canvas toward the clicked location, giving the rocket its travel direction.
dir.setMag(8);
Resizes the direction vector so its length (speed) is exactly 8 pixels per frame, no matter how far away the click was.
fireworks.push({p:createVector(width/2,height),v:dir,t:createVector(mouseX,mouseY),exploded:false,parts:[],c:random(cols)});
Adds a new firework object to the array: p is its starting position (bottom-center), v is its velocity, t is its target (the click point), exploded starts false, parts will later hold explosion particles, and c is a randomly chosen color.

explode()

explode() is a helper function that converts one kind of object (a flying rocket) into another (a cloud of particles) by mutating the same firework object. This pattern - reusing one object with a state flag (exploded) instead of creating a brand new object - is a common lightweight approach in small particle systems.

🔬 spd=random(2,6) controls how far particles fly before slowing down. What happens if you widen that range to random(10,20)? What if you narrow it to a fixed value like 4?

  for(let i=0;i<n;i++){
    let ang=random(TWO_PI),spd=random(2,6);
    f.parts.push({p:f.p.copy(),v:createVector(cos(ang)*spd,sin(ang)*spd),life:255});
  }
function explode(f){
  f.exploded=true;f.c=color(f.c);
  let n=int(random(30,51));
  for(let i=0;i<n;i++){
    let ang=random(TWO_PI),spd=random(2,6);
    f.parts.push({p:f.p.copy(),v:createVector(cos(ang)*spd,sin(ang)*spd),life:255});
  }
}
Line-by-line explanation (5 lines)

🔧 Subcomponents:

for-loop Spawn Explosion Particles for(let i=0;i<n;i++){

Creates n particles, each with a random direction and speed, to build the burst effect.

f.exploded=true;f.c=color(f.c);
Marks the firework as exploded so draw() switches to particle mode, and converts the stored hex string into a real p5.Color object so red()/green()/blue() can be used on it later.
let n=int(random(30,51));
Picks a random whole number between 30 and 50 to decide how many particles this explosion will have.
for(let i=0;i<n;i++){
Repeats the particle-creation code n times, once per particle.
let ang=random(TWO_PI),spd=random(2,6);
Chooses a random angle (0 to full circle in radians) and a random speed between 2 and 6 for this particle.
f.parts.push({p:f.p.copy(),v:createVector(cos(ang)*spd,sin(ang)*spd),life:255});
Adds a new particle object starting at the explosion point, with velocity computed from the random angle and speed using cos/sin, and a starting life of 255 (used later as alpha).

windowResized()

windowResized() is a p5.js event function that automatically runs whenever the browser window changes size, letting you keep responsive full-window sketches without any extra setup.

function windowResized(){resizeCanvas(windowWidth,windowHeight);background(3,5,15);}
Line-by-line explanation (2 lines)
resizeCanvas(windowWidth,windowHeight);
Resizes the canvas to match the browser window whenever it's resized, keeping the sketch full-screen.
background(3,5,15);
Repaints the background solid dark color after resizing, since resizing can otherwise leave stale or blank pixels.

📦 Key Variables

fireworks array

Holds every active firework object (both still-flying rockets and exploded particle bursts) currently on screen.

let fireworks=[];
cols array

Stores the palette of hex color strings that get randomly assigned to each new firework.

let cols=['#ff4b5c','#ffd93d','#4cd137','#00a8ff','#9b59b6'];

🔧 Potential Improvements (5)

Here are some ways this code could be enhanced:

BUG draw() explosion trigger

The rocket only explodes when it comes within 10 pixels of its target (p5.Vector.dist(f.p,f.t)<10). If the rocket's speed is high enough, or the click is very close to the launch point, it can overshoot the target every frame and never get within 10 pixels, leaving it flying forever.

💡 Also explode when the rocket has passed its target vertically, e.g. add `|| f.p.y <= f.t.y` to the condition, so fast or nearby rockets always detonate.

BUG mousePressed()

If a user clicks exactly at width/2 and y equal to height, the direction vector (mouseX-width/2, mouseY-height) is (0,0), and calling setMag(8) on a zero-length vector can produce NaN, silently breaking that firework.

💡 Check dir.mag() > 0 before calling setMag, or add a tiny fallback vector like createVector(0,-8) when the computed direction is zero.

PERFORMANCE draw() particle loop

Each particle is drawn with individual stroke()/strokeWeight()/point() calls every frame, which is more state-switching overhead than necessary when hundreds of particles are on screen from multiple simultaneous fireworks.

💡 Batch particles by color, or use a p5.Graphics buffer / vertex-based drawing to reduce the number of state changes per frame.

STYLE whole sketch

Fireworks and particles are stored as loosely-typed object literals ({p, v, t, exploded, parts, c} and {p, v, life}), making the code compact but harder to extend or read as it grows.

💡 Refactor into a Firework class and a Particle class with their own update() and show() methods - this would make the draw() loop much shorter and easier to follow, e.g. `for (let fw of fireworks) fw.update(); fw.show();`.

FEATURE explode()

Every explosion currently expands as a uniform circular burst with no variation in shape.

💡 Add optional explosion 'types' (e.g. a ring, a heart shape, or a double-burst) by varying how ang and spd are generated, giving the show more visual variety.

🔄 Code Flow

Code flow showing setup, draw, mousepressed, explode, windowresized

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

graph TD start[Start] --> setup[setup] setup --> draw[draw loop] draw --> mainloop[Fireworks Array Loop] mainloop --> rocketflight[Unexploded Rocket Check] rocketflight --> explosiontrigger[Reached Target Check] explosiontrigger -->|If Exploded| explode[explode] explode --> particleloop[Particle Update Loop] particleloop --> particledeath[Remove Dead Particle] particledeath --> fireworkcleanup[Remove Spent Firework] fireworkcleanup --> draw draw -->|Continue Loop| mainloop click setup href "#fn-setup" click draw href "#fn-draw" click mainloop href "#sub-main-loop" click rocketflight href "#sub-rocket-flight" click explosiontrigger href "#sub-explosion-trigger" click explode href "#fn-explode" click particleloop href "#sub-particle-loop" click particledeath href "#sub-particle-death" click fireworkcleanup href "#sub-firework-cleanup" click mousepressed href "#fn-mousepressed" click windowresized href "#fn-windowresized"

❓ Frequently Asked Questions

What kind of visual effects does the AI Firework Show create?

The sketch visually simulates colorful fireworks that streak across the sky and explode into vibrant showers of particles, which gradually fade as they fall.

How can users launch fireworks in this interactive sketch?

Users can click anywhere on the canvas to launch fireworks, creating multiple explosions with each click for a lively celebration.

What creative coding techniques are showcased in this p5.js sketch?

This sketch demonstrates particle systems and vector mathematics to simulate the motion and explosion of fireworks in an engaging manner.

Preview

AI Firework Show - Click to Launch Explosions - p5.js creative coding sketch preview
Sketch Preview
Code flow diagram showing the structure of AI Firework Show - Click to Launch Explosions - Code flow showing setup, draw, mousepressed, explode, windowresized
Code Flow Diagram