class Firework {
constructor(targetX, targetY) {
this.pos = createVector(random(width), height);
this.target = createVector(targetX, targetY);
this.vel = p5.Vector.sub(this.target, this.pos);
this.vel.setMag(random(8, 12));
this.acc = createVector(0, 0);
this.exploded = false;
this.particles = [];
this.hu = random(255);
}
done() {
if (this.exploded) {
return this.particles.length === 0;
} else {
return false;
}
}
update() {
if (!this.exploded) {
this.vel.add(this.acc);
this.pos.add(this.vel);
this.acc.mult(0);
let d = p5.Vector.dist(this.pos, this.target);
if (d < 10) {
this.explode();
this.exploded = true;
}
} else {
for (let i = this.particles.length - 1; i >= 0; i--) {
let particle = this.particles[i];
particle.update();
if (particle.done()) {
this.particles.splice(i, 1);
}
}
}
}
show() {
if (!this.exploded) {
stroke(this.hu, 255, 255);
point(this.pos.x, this.pos.y);
} else {
for (let particle of this.particles) {
particle.show();
}
}
}
explode() {
for (let i = 0; i < random(50, 100); i++) {
this.particles.push(new Particle(this.pos.x, this.pos.y, this.hu));
}
}
}
๐ง Subcomponents:
calculation
Firework Constructor
constructor(targetX, targetY) { ... }
Initializes a new firework with starting position at bottom of canvas, target position at click location, and calculated velocity to reach the target
conditional
Done Method
done() { ... }
Checks if the firework has completely finished by verifying all particles have faded out
conditional
Update Method
update() { ... }
Moves the firework toward its target before explosion, or updates all particles after explosion
conditional
Show Method
show() { ... }
Draws the firework as a bright point before explosion, or draws all particles after explosion
for-loop
Explode Method
explode() { ... }
Creates 50-100 particles at the explosion point, spreading them outward with random velocities
Line by Line:
this.pos = createVector(random(width), height)
- Sets the starting position at the bottom of the canvas (height) with a random X coordinate, so fireworks launch from different positions
this.target = createVector(targetX, targetY)
- Stores the target position where the user clicked, which the firework will travel toward
this.vel = p5.Vector.sub(this.target, this.pos)
- Calculates the velocity vector by subtracting the starting position from the target, creating a vector pointing toward the target
this.vel.setMag(random(8, 12))
- Sets the speed of the firework's ascent to a random value between 8 and 12 pixels per frame, making each firework travel at a slightly different speed
this.exploded = false
- Flag that tracks whether the firework has exploded yet. Used to determine whether to update position or update particles
this.particles = []
- Empty array that will hold all particle objects created when the firework explodes
this.hu = random(255)
- Assigns a random hue value (0-255) to this firework, which will be inherited by all its particles for consistent coloring
if (this.exploded) { return this.particles.length === 0 }
- If exploded, the firework is done only when all particles have faded out (array is empty)
this.vel.add(this.acc)
- Applies acceleration to velocity (currently 0 for fireworks, but structure allows for future modifications)
this.pos.add(this.vel)
- Updates the firework's position by adding its velocity, moving it one step closer to the target
this.acc.mult(0)
- Resets acceleration to zero for the next frame, following the physics simulation pattern
let d = p5.Vector.dist(this.pos, this.target)
- Calculates the distance between the firework's current position and its target using vector distance
if (d < 10)
- Checks if the firework is close enough to the target (within 10 pixels) to trigger explosion
particle.update()
- Updates each particle's position and applies gravity to it
if (particle.done())
- Checks if a particle has completely faded out (lifespan < 0)
this.particles.splice(i, 1)
- Removes the faded particle from the array to free memory
stroke(this.hu, 255, 255)
- Sets the stroke color to the firework's hue with full saturation and brightness, creating a bright colored point
point(this.pos.x, this.pos.y)
- Draws a single point at the firework's current position before explosion
for (let particle of this.particles)
- Loops through all particles after explosion and calls their show() method to draw them
for (let i = 0; i < random(50, 100); i++)
- Creates a random number of particles between 50 and 100, adding variety to each explosion
this.particles.push(new Particle(this.pos.x, this.pos.y, this.hu))
- Creates a new Particle at the explosion position with the firework's hue, and adds it to the particles array
class Particle {
constructor(x, y, hu) {
this.pos = createVector(x, y);
this.vel = p5.Vector.random2D();
this.vel.mult(random(1, 8));
this.acc = createVector(0, 0);
this.lifespan = 255;
this.hu = hu;
}
done() {
return this.lifespan < 0;
}
update() {
this.acc.add(gravity);
this.vel.add(this.acc);
this.pos.add(this.vel);
this.acc.mult(0);
this.lifespan -= 5;
}
show() {
stroke(this.hu, 255, 255, this.lifespan);
strokeWeight(2);
point(this.pos.x, this.pos.y);
}
}
๐ง Subcomponents:
calculation
Particle Constructor
constructor(x, y, hu) { ... }
Initializes a particle at the explosion point with random velocity spreading outward and inherited hue from the firework
conditional
Done Method
done() { return this.lifespan < 0 }
Checks if the particle has completely faded out
calculation
Update Method
update() { ... }
Applies gravity, updates velocity and position, and decreases lifespan to fade the particle
calculation
Show Method
show() { ... }
Draws the particle as a point with alpha based on remaining lifespan, creating the fade effect
Line by Line:
this.pos = createVector(x, y)
- Sets the particle's starting position at the explosion point (center of the firework)
this.vel = p5.Vector.random2D()
- Creates a random 2D vector with magnitude 1, pointing in a random direction for spreading particles outward
this.vel.mult(random(1, 8))
- Multiplies the velocity by a random value between 1 and 8, giving particles different speeds so they spread at varying rates
this.acc = createVector(0, 0)
- Initializes acceleration to zero, ready to receive gravity in the update method
this.lifespan = 255
- Sets the particle's lifespan to 255 (fully opaque in HSB mode). This decreases each frame to create the fade effect
this.hu = hu
- Stores the hue inherited from the parent firework, ensuring all particles in an explosion share the same color
return this.lifespan < 0
- Returns true when lifespan becomes negative, indicating the particle is completely faded and should be removed
this.acc.add(gravity)
- Adds the global gravity vector to the particle's acceleration, making it fall downward each frame
this.vel.add(this.acc)
- Applies acceleration to velocity, increasing downward velocity due to gravity
this.pos.add(this.vel)
- Updates the particle's position by adding velocity, moving it one step in its current direction
this.acc.mult(0)
- Resets acceleration to zero for the next frame, following standard physics simulation practice
this.lifespan -= 5
- Decreases lifespan by 5 each frame, causing the particle to fade out over approximately 51 frames (255 / 5)
stroke(this.hu, 255, 255, this.lifespan)
- Sets the stroke color using the particle's hue with full saturation and brightness, but with alpha equal to lifespan so it fades as lifespan decreases
strokeWeight(2)
- Sets stroke weight to 2 pixels, making particles slightly thinner than the initial firework point
point(this.pos.x, this.pos.y)
- Draws a single point at the particle's current position