Fireworks · grok-4.20
Create a fireworks display on a full-screen canvas where clicks launch shells that explode into gravity-affected, fading particle bursts.
transcript · 4 messages
Create a fireworks display on a full-screen canvas where clicks launch shells that explode into gravity-affected, fading particle bursts.
thinking
The task is: "Create a fireworks display on a full-screen canvas where clicks launch shells that explode into gravity-affected, fading particle bursts." I must build a single-page web app in one self-...The task is to create a fireworks display on a full-screen canvas where clicks launch shells that explode into gravity-affected, fading particle bursts. It needs to be a single self-contained index.html file with CSS in <style> and JS in <script>. No external resources.
I need to build this in one HTML file.
- Canvas full screen
- Dark background
- Click to launch fireworks
- Shells go up, explode into particles
- Particles with gravity, fade
- Animation loop with requestAnimationFrame
I'll use classes for Firework and Particle.
For launch: on click, launch from bottom center 0 to random x? But to make interactive, launch from bottom at random x, direction towards click point.
Simple: launch from bottom center upwards, but click determines explosion height or something. But prompt says "clicks launch shells", so probably click position is where shell goes to or launch point.
Common: click anywhere launches a shell from bottom center to that x at some height.
Let's decide: on click at (x,y), launch shell from (random bottom x, height) to (x,y) or something. To simplify, launch from bottom center (width/2,0) to (clickx, clicky) but 0 is top? No, y=0 bottom.
Set y=0 at bottom.
Shell starts at y=height, x=random or fixed, moves to target.
But for simplicity, let's make launch from bottom center, direction based on click x, straight up if no x.
To make it good, random launch x at bottom, random direction or fixed up, but to use click, launch to click position.
Let's code it.
First, the structure.
I need to write the full code.
Confidence high if I can get it right.
Let me sketch the code in mind.
HTML:
<!DOCTYPE html>
<html lang="en ">
<head>
<meta charset="UTF-8">
<title>Fireworks Display</title>
<style>
body { margin: 0; overflow: hidden; background: #000; }
canvas { display: block; }
</style>
</head>
<body>
<canvas id="c"></canvas>
<script>
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');
let w, h;
function resize() {
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;
}
window.addEventListener('resize', resize);
resize();
let fireworks = [];
let particles = [];
class Firework {
constructor(sx, sy, tx, ty) {
this.x = sx;
this.y = sy;
this.tx = tx;
this.ty = ty;
this.hue = Math.random()*360;
this.trail = [];
this.exploded = false;
}
update() {
if (this .exploded) return;
this.x += (this.tx - this.x) * 0.05; // smooth towards
this.y += (this.ty - this.y) * 0.05;
this.trail.push({x: this.x, y: this.y});
if (this.trail.length > 10) this.trail.shift();
if (Math.hypot(this.tx - this.x, this.ty - this.y) < 2) {
this.explode();
}
}
explode() {
this.exploded = true;
const count = 100;
for (let i = 0; i < count; i++) {
const angle = Math.random() * Math.PI * 2;
const speed = 2 + Math.random() * 6;
particles.push(new Particle(this.x, this.y, Math.cos(angle) * speed, Math.sin(angle) * speed, this.hue));
}
}
draw() {
if (this.expl oded) return;
ctx.save();
ctx.shadowBlur = 10;
ctx.shadowColor = `hsl(${this.hue}, 100%, 50%)`;
ctx.fillStyle = `hsl(${this.hue}, 100%, 70%)`;
for (let p of this.trail) {
const alpha = 1 - this.trail.indexOf(p) / this.trail.length;
ctx.globalAlpha = alpha;
ctx.fillRect(p.x - 1, p.y - 1, 2, 2);
}
ctx.globalAlpha = 1;
ctx.beginPath();
ctx.arc(this.x, this.y, 3 , 0, Math.PI*2);
ctx.fill();
ctx.restore();
}
}
class Particle {
constructor(x, y, vx, vy, hue) {
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.hue = hue + (Math.random()* 40 -20);
this.alpha = 1;
this.size = 2 + Math.random() * 2;
this.gravity = 0.1;
this.friction = 0.95;
this.life = 1;
}
update() {
this.vy += this.gravity;
this.vx *= this .friction;
this.vy *= this.friction;
this.x += this.vx;
this.y += this.vy;
this.alpha -= 0.01;
this.life -= 0.02;
if (this.life <0) this.alpha =0;
}
draw() {
if (this.alpha <=0 ) return;
ctx.save();
ctx.shadowBlur = 10;
ctx.shadowColor = `hsl(${this.hue}, 100%, 50%)`;
ctx.fillStyle = `hsl(${this.hue}, 100%, 70%, ${this.alpha})`;
ctx.beginPath();
ctx.arc(this.x, this.y , this.size, 0, Math.PI*2);
ctx.fill();
ctx.restore();
}
}
function launchFirework(tx, ty) {
const sx = w / 2;
const sy = h;
fireworks.push(new Firework(sx, sy, tx, ty));
}
canvas.addEventListener('click ', (e) => {
const tx = e.clientX;
const ty = e.clientY;
launchFirework(tx, ty);
});
function animate() {
ctx.fillStyle = 'rgba(0,0,0,0.1)';
ctx.index.html (15952 bytes)Successfully wrote 15952 bytes to index.html
thinking
The task is complete. I've created a single self-contained index.html file with a full-screen fireworks display. It includes:
The fireworks display has been built as a self-contained `index.html`. Open it in a browser for a full-screen interactive experience (click/tap to launch shells, spacebar for bursts, etc.).
TAKE IT TO CODE
A single self-contained HTML file — copy it and open in any browser, or reuse the prompt with your own pi-agent run.
RUN
EVALUATION
Animated fireworks display with shells launching automatically and exploding into colorful fading particle bursts with gravity.
Vision grade · anthropic/claude-sonnet-5
MEASUREMENTS
Raw readings from the capture, not a verdict — the grade above is the only judgement. Percentages are how much of the screen changed; the measure under-reports sparse motion on a dark background.