Ai Fireworks Code

This was made in Google Gemini app, within the Canvas using Gemini Pro

<!DOCTYPE html>
<div id="fireworks-container" style="width: 100%; height: 600px; background-color: transparent; overflow: hidden; position: relative;">
    <canvas id="fireworks-canvas-block"></canvas>

    <script>
        // Use a self-executing function to keep variables local and avoid conflicts
        (function() {
            const container = document.getElementById('fireworks-container');
            const canvas = document.getElementById('fireworks-canvas-block');
            const ctx = canvas.getContext('2d');
            
            // Define core variables, scoped locally
            const rockets = [];
            const particles = [];
            const stars = []; 
            const GRAVITY = 0.05;
            const FRICTION = 0.985;

            let width, height;

            /** Utility function to get a random number within a range. */
            function randomRange(min, max) {
                return Math.random() * (max - min) + min;
            }

            /** Utility function to generate a vibrant HSL color string. */
            function randomColor() {
                const h = randomRange(0, 360);
                return `hsl(${h}, 95%, 70%)`;
            }

            // --- Star Class for Twinkling Background ---
            class Star {
                constructor(x, y, radius) {
                    this.x = x;
                    this.y = y;
                    this.radius = radius;
                    this.alpha = randomRange(0.2, 0.7);
                    this.oscillationSpeed = randomRange(0.005, 0.015);
                    this.oscillationOffset = Math.random() * Math.PI * 2;
                }

                update() {
                    // Subtle twinkling effect by oscillating alpha
                    // Using Date.now() for simple time-based oscillation without a global counter
                    this.alpha = randomRange(0.2, 0.7) + Math.sin(Date.now() * this.oscillationSpeed + this.oscillationOffset) * 0.2;
                }

                draw() {
                    ctx.save();
                    ctx.fillStyle = `rgba(255, 255, 255, ${this.alpha})`;
                    ctx.beginPath();
                    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
                    ctx.fill();
                    ctx.restore();
                }
            }

            // --- Particle Class for Explosion Debris ---
            class Particle {
                constructor(x, y, color, angle, speed, friction, gravity, sizeMultiplier = 1) {
                    this.x = x;
                    this.y = y;
                    this.color = color;
                    this.friction = friction;
                    this.gravity = gravity;
                    this.alpha = 1;
                    this.decay = randomRange(0.015, 0.035);
                    this.size = randomRange(1, 3) * sizeMultiplier; 
                    this.windX = randomRange(-0.01, 0.01);

                    this.velX = Math.cos(angle) * speed;
                    this.velY = Math.sin(angle) * speed;
                }

                update() {
                    this.velX = this.velX * this.friction + this.windX;
                    this.velY *= this.friction;

                    this.velY += this.gravity;

                    this.x += this.velX;
                    this.y += this.velY;

                    this.alpha -= this.decay;
                }

                draw() {
                    ctx.save();
                    ctx.globalAlpha = this.alpha;
                    ctx.fillStyle = this.color;
                    ctx.beginPath();
                    ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
                    ctx.fill();
                    ctx.restore();
                }
            }

            // --- Rocket Class for Launching Firework ---
            class Rocket {
                constructor(startX, startY, targetX, targetY) {
                    this.x = startX;
                    this.y = startY;
                    this.targetX = targetX;
                    this.targetY = targetY;
                    this.color = randomColor();

                    const dx = targetX - startX;
                    const dy = targetY - startY;
                    const distance = Math.sqrt(dx * dx + dy * dy);

                    const speed = distance / randomRange(45, 70);

                    this.velX = dx / distance * speed;
                    this.velY = dy / distance * speed;

                    this.exploded = false;
                    this.trail = [];
                    
                    // Determine a size multiplier for the resulting explosion (0.5 to 1.5)
                    this.sizeMultiplier = randomRange(0.5, 1.5);
                }

                update() {
                    if (this.exploded) return;

                    // Check for explosion condition
                    if (this.y < this.targetY || this.velY > 0) {
                        this.explode();
                        return;
                    }

                    this.velY += GRAVITY * 0.5;

                    this.x += this.velX;
                    this.y += this.velY;

                    // Add current position to trail
                    this.trail.push({ x: this.x, y: this.y, color: this.color });
                    if (this.trail.length > 8) {
                        this.trail.shift();
                    }
                }

                draw() {
                    if (this.exploded) return;

                    // Draw the trail
                    ctx.strokeStyle = this.color;
                    ctx.lineWidth = randomRange(1, 3) * Math.min(this.sizeMultiplier, 1); 
                    ctx.beginPath();
                    if (this.trail.length > 1) {
                        ctx.moveTo(this.trail[0].x, this.trail[0].y);
                        for (let i = this.trail.length - 1; i >= 0; i--) {
                            ctx.globalAlpha = 0.1 + (i / this.trail.length) * 0.9;
                            ctx.lineTo(this.trail[i].x, this.trail[i].y);
                        }
                    }
                    ctx.stroke();
                    ctx.globalAlpha = 1;

                    // Draw the head of the rocket (brighter point with glow)
                    ctx.fillStyle = this.color;
                    ctx.shadowBlur = 15;
                    ctx.shadowColor = this.color;
                    ctx.beginPath();
                    ctx.arc(this.x, this.y, 3, 0, Math.PI * 2);
                    ctx.fill();
                    
                    ctx.shadowBlur = 0;
                    ctx.shadowColor = 'transparent';
                }

                explode() {
                    this.exploded = true;
                    
                    const particleCount = Math.floor(randomRange(100, 200) * this.sizeMultiplier);
                    const color = this.color;

                    for (let i = 0; i < particleCount; i++) {
                        const angle = randomRange(0, Math.PI * 2);
                        const speed = randomRange(2, 12) * this.sizeMultiplier; 

                        particles.push(new Particle(
                            this.x,
                            this.y,
                            color,
                            angle,
                            speed,
                            FRICTION,
                            GRAVITY,
                            this.sizeMultiplier 
                        ));
                    }
                }
            }

            // --- Star Generation ---
            function createStars(count) {
                for (let i = 0; i < count; i++) {
                    stars.push(new Star(
                        randomRange(0, width),
                        randomRange(0, height * 0.7), 
                        randomRange(0.5, 1.5)
                    ));
                }
            }

            function drawStars() {
                for (let i = 0; i < stars.length; i++) {
                    stars[i].update();
                    stars[i].draw();
                }
            }

            // --- Main Functions ---

            function resizeCanvas() {
                // Resize based on the container size, not the window
                width = canvas.width = container.clientWidth;
                height = canvas.height = container.clientHeight;

                // Clear and recreate stars on resize
                stars.length = 0; 
                createStars(200); 
            }

            function draw() {
                // Completely clear the canvas for transparency
                ctx.clearRect(0, 0, width, height);
                
                // Draw Stars (will stay static relative to the canvas)
                drawStars();

                // Update and Draw Rockets
                for (let i = rockets.length - 1; i >= 0; i--) {
                    const rocket = rockets[i];
                    rocket.update();
                    rocket.draw();

                    if (rocket.exploded) {
                        rockets.splice(i, 1);
                    }
                }

                // Update and Draw Particles
                ctx.shadowBlur = 10;
                ctx.shadowColor = 'white';

                for (let i = particles.length - 1; i >= 0; i--) {
                    const particle = particles[i];
                    particle.update();
                    particle.draw();

                    if (particle.alpha <= particle.decay) {
                        particles.splice(i, 1);
                    }
                }
                
                ctx.shadowBlur = 0;
                ctx.shadowColor = 'transparent';
            }

            function animate() {
                draw();
                requestAnimationFrame(animate);
            }

            function launchFirework(x, y) {
                
                const targetY = Math.min(y, height * 0.8);
                
                rockets.push(new Rocket(
                    width / 2,
                    height,
                    x,
                    targetY
                ));
            }

            function autoLaunchFirework() {
                // Random X coordinate (across the whole width)
                const randomX = randomRange(width * 0.1, width * 0.9);
                // Random Y coordinate (in the top half of the screen for explosion height)
                const randomY = randomRange(height * 0.1, height * 0.5); 
                
                launchFirework(randomX, randomY);
            }

            /**
             * Starts the animation loop and automatic launches.
             */
            function startGame() {
                // Start the automatic firework show loop
                setInterval(autoLaunchFirework, randomRange(500, 1500));

                // Start the animation loop
                animate();
            }

            // --- Event Listeners and Initialization ---
            
            // Observer to handle container resizing (e.g., if the user changes the column width in WP)
            const resizeObserver = new ResizeObserver(entries => {
                for (let entry of entries) {
                    if (entry.target === container) {
                        resizeCanvas();
                    }
                }
            });

            resizeObserver.observe(container);

            window.addEventListener('load', function() {
                resizeCanvas(); // Initial setup
                startGame(); 
            });
        })(); // End of self-executing function

    </script>
</div>

Leave a Reply

Your email address will not be published. Required fields are marked *