oneshotlm
Compare all models on this prompt →

Fireworks · laguna-xs-2.1

Create a fireworks display on a full-screen canvas where clicks launch shells that explode into gravity-affected, fading particle bursts.

⛨ sandboxed Open in new tab ↗
transcript · 6 messages
user

Create a fireworks display on a full-screen canvas where clicks launch shells that explode into gravity-affected, fading particle bursts.

assistant
thinking
The user wants me to create a fireworks display web app with:
1. Full-screen canvas
2. Click to launch fireworks shells
3. Explosions that create gravity-affected, fading particle bursts

I need to create a self-contained index.html file with:
- CSS in a <style> tag
- JS in a <script> tag
- No external resources
- Full-screen canvas
- Click event handler to launch shells
- Particle physics with gravity
- Fading particles

Let me design this:
- Canvas fills the entire viewport
- On click, create a firework shell that travels from bottom to the click position
- At the target, explode into particles
- Particles should have:
  - Velocity (spread outward)
  - Gravity (fall down)
  - Fade out over time
  - Random colors
- Shell should have a trail

I'll write this all in one file.

I'll create a self-contained fireworks display web app with gravity-affected particles. Let me write the complete index.html file.

write /workspace/index.html (8983 bytes)
toolResult

Successfully wrote 8983 bytes to /workspace/index.html

assistant
thinking
I've created the fireworks display web app. Let me verify the file was written correctly by reading it.
read {"path":"/workspace/index.html"}
toolResult

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Fireworks Display</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { overflow: hidden; background: linear-gradient(135deg, #0a0a2a 0%, #1a0a2a 50%, #0a1a2a 100%); height: 100vh; cursor: pointer; } canvas { display: block; width: 100vw; height: 100vh; } .info { position: fixed; top: 20px; left: 20px; color: white; font-family: Arial, sans-serif; font-size: 14px; background: rgba(0, 0, 0, 0.3); padding: 10px 15px; border-radius: 5px; pointer-events: none; } </style> </head> <body> <canvas id="fireworks"></canvas> <div class="info">Click anywhere to launch fireworks</div> <script> const canvas = document.getElementById('fireworks'); const ctx = canvas.getContext('2d'); // Set canvas size canvas.width = window.innerWidth; canvas.height = window.innerHeight; // Resize handler window.addEventListener('resize', () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }); // Fireworks arrays const shells = []; const particles = []; const trails = []; // Colors for fireworks const colors = [ '#ff5252', '#ffca28', '#69f0ae', '#536dfe', '#ff80ab', '#ff8000', '#d500f9', '#00e5ff', '#ff6400', '#76ff03', '#2979ff', '#ff4081' ]; // Utility functions function random(min, max) { return Math.random() * (max - min) + min; } function randomInt(min, max) { return Math.floor(random(min, max)); } // Firework shell class class FireworkShell { constructor(x, y, targetX, targetY) { this.x = x; this.y = y; this.targetX = targetX; this.targetY = targetY; this.speed = random(4, 8); this.color = colors[randomInt(0, colors.length)]; this.size = random(3, 6); this.exploded = false; this.angle = Math.atan2(targetY - y, targetX - x); } update() { const dx = this.targetX - this.x; const dy = this.targetY - this.y; const dist = Math.sqrt(dx * dx + dy * dy); if (dist < this.speed) { this.exploded = true; this.explode(); } else { this.x += Math.cos(this.angle) * this.speed; this.y += Math.sin(this.angle) * this.speed; // Create trail trails.push({ x: this.x, y: this.y, color: this.color, size: this.size * 0.5, alpha: 0.5, life: 20 }); } } explode() { const particleCount = randomInt(50, 100); for (let i = 0; i < particleCount; i++) { particles.push(new Particle(this.x, this.y, this.color)); } } draw() { if (!this.exploded) { ctx.fillStyle = this.color; ctx.beginPath(); ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2); ctx.fill(); } } } // Particle class class Particle { constructor(x, y, color) { this.x = x; this.y = y; this.color = color; this.size = random(2, 5); this.speed = random(2, 6); this.angle = random(0, Math.PI * 2); this.vx = Math.cos(this.angle) * this.speed; this.vy = Math.sin(this.angle) * this.speed; this.alpha = 1; this.gravity = 0.15; this.friction = 0.99; this.life = random(40, 80); } update() { this.vy += this.gravity; this.vx *= this.friction; this.vy *= this.friction; this.x += this.vx; this.y += this.vy; this.alpha -= 1 / this.life; this.life--; } draw() { ctx.fillStyle = this.color; ctx.globalAlpha = this.alpha; ctx.beginPath(); ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2); ctx.fill(); ctx.globalAlpha = 1; } isDead() { return this.alpha <= 0 || this.life <= 0; } } // Trail class class Trail { constructor(x, y, color) { this.x = x; this.y = y; this.color = color; this.size = random(2, 4); this.alpha = 0.5; this.life = 20; } update() { this.alpha -= 0.05; this.life--; } draw() { ctx.fillStyle = this.color; ctx.globalAlpha = this.alpha; ctx.beginPath(); ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2); ctx.fill(); ctx.globalAlpha = 1; } isDead() { return this.life <= 0; } } // Handle click canvas.addEventListener('click', (e) => { const rect = canvas.getBoundingClientRect(); const x = e.clientX; const y = e.clientY; const startX = randomInt(canvas.width * 0.3, canvas.width * 0.7); const startY = canvas.height + 20; shells.push(new FireworkShell(startX, startY, x, y)); }); // Animation loop function animate() { // Semi-transparent background for trail effect ctx.fillStyle = 'rgba(10, 10, 42, 0.2)'; ctx.fillRect(0, 0, canvas.width, canvas.height); // Update and draw shells for (let i = shells.length - 1; i >= 0; i--) { const shell = shells[i]; shell.update(); shell.draw(); if (shell.exploded) { shells.splice(i, 1); } } // Update and draw particles for (let i = particles.length - 1; i >= 0; i--) { const particle = particles[i]; particle.update(); particle.draw(); if (particle.isDead()) { particles.splice(i, 1); } } // Update and draw trails for (let i = trails.length - 1; i >= 0; i--) { const trail = trails[i]; trail.life--; trail.alpha = trail.life / 20; ctx.fillStyle = trail.color; ctx.globalAlpha = trail.alpha; ctx.beginPath(); ctx.arc(trail.x, trail.y, trail.size, 0, Math.PI * 2); ctx.fill(); ctx.globalAlpha = 1; if (trail.life <= 0) { trails.splice(i, 1); } } requestAnimationFrame(animate); } // Start animation animate(); // Add some initial fireworks for effect setTimeout(() => { for (let i = 0; i < 3; i++) { setTimeout(() => { const x = randomInt(canvas.width * 0.3, canvas.width * 0.7); const y = randomInt(canvas.height * 0.3, canvas.height * 0.7); shells.push(new FireworkShell( randomInt(canvas.width * 0.3, canvas.width * 0.7), canvas.height + 20, x, y )); }, i * 500); } }, 1000); </script> </body> </html>

assistant
thinking
The file has been created successfully. The fireworks display web app includes:

1. Full-screen canvas with a dark gradient background
2. Click anywhere to launch fireworks - shells travel from bottom to the click position
3. Explosions create 50-100 gravity-affected particles with:
   - Random velocities in all directions
   - Gravity pulling them down
   - Friction slowing them over time
   - Fading alpha for the fade-out effect
4. Colored particles with 12 vibrant colors
5. Trail effects behind the ascending shells
6. Semi-transparent background clear for persistent trails
7. Responsive to window resize
8. Initial demo fireworks at startup

The file is now complete at /workspace/index.html

Created `/workspace/index.html` - a complete fireworks display web app with: **Features:** - **Full-screen canvas** with dark gradient background - **Click to launch** - shells travel from bottom to your click position - **Gravity-affected particles** - each explosion creates 50-100 particles with realistic physics - **Fading effect** - particles gradually fade as they expire - **Trail effects** - colored trails follow each ascending shell - **Vibrant colors** - 12 different firework colors - **Responsive** - adapts to window resize - **Demo fireworks** - 3 initial fireworks at startup **Physics:** - Particles have gravity (`vy += 0.15` per frame) - Friction (`0.99`) slows them down over time - Alpha decreases for fade-out effect - Particles are removed when alpha <= 0 or life expires

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

modellaguna-xs-2.1
vendorPoolside
harnesspi-agent
generated2026-07-22

EVALUATION

3/5 working

Clicking and scrolling launch fireworks that explode into fading particle bursts, but display is sparse and dim.

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.

idle motion0.0%
on click0.1%
on drag0.0%
on wheel1.2%
on enter + space0.0%
on arrow keys0.0%
on w/a/s/d0.0%
frame spread7.9 / 255
console errors0
js errors none

METRICS

runtime22.5s
tokens in5.1k
tokens out3.0k
cached7.2k
cost / run$0.0147