Drawaria Liquid Bubble Canvas & Interactive Physics

Advanced liquid physics simulation with interactive bubbles, fluid dynamics, and collaborative drawing effects for drawaria.online!

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Drawaria Liquid Bubble Canvas & Interactive Physics
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Advanced liquid physics simulation with interactive bubbles, fluid dynamics, and collaborative drawing effects for drawaria.online!
// @author       YouTubeDrawaria
// @match        https://drawaria.online/*
// @grant        none
// @license      MIT
// @icon         https://www.google.com/s2/favicons?sz=64&domain=drawaria.online
// ==/UserScript==

(function() {
    'use strict';

    // Physics simulation state
    const physicsState = {
        bubbles: [],
        liquidDrops: [],
        gravityStrength: 0.1,
        viscosity: 0.99,
        tension: 0.1,
        interactionRadius: 80,
        maxBubbles: 50,
        liquidMode: true,
        magneticMode: false,
        antigravityMode: false,
        colorMixing: true,
        trailMode: false
    };

    // Advanced bubble with liquid physics
    class LiquidBubble {
        constructor(x, y, radius = null, color = null) {
            this.x = x || Math.random() * window.innerWidth;
            this.y = y || Math.random() * window.innerHeight;
            this.vx = (Math.random() - 0.5) * 4;
            this.vy = (Math.random() - 0.5) * 4;
            this.radius = radius || Math.random() * 30 + 15;
            this.originalRadius = this.radius;
            this.mass = this.radius * 0.1;
            this.color = color || this.generateColor();
            this.alpha = Math.random() * 0.6 + 0.4;
            this.life = 1.0;
            this.age = 0;
            this.elasticity = 0.8;
            this.temperature = Math.random() * 100 + 50;
            this.magneticCharge = Math.random() > 0.5 ? 1 : -1;
            this.trailPoints = [];
            this.maxTrailLength = 20;
            this.connections = [];
            this.vibrationPhase = Math.random() * Math.PI * 2;
        }

        generateColor() {
            const colors = [
                'rgba(64, 224, 255, 0.7)',   // Deep sky blue
                'rgba(255, 105, 180, 0.7)',  // Hot pink
                'rgba(50, 255, 126, 0.7)',   // Spring green
                'rgba(255, 215, 0, 0.7)',    // Gold
                'rgba(138, 43, 226, 0.7)',   // Blue violet
                'rgba(255, 69, 0, 0.7)'      // Red orange
            ];
            return colors[Math.floor(Math.random() * colors.length)];
        }

        update(bubbles, mouseX, mouseY) {
            this.age++;
            
            // Update trail
            if (physicsState.trailMode) {
                this.trailPoints.push({ x: this.x, y: this.y, alpha: 0.8 });
                if (this.trailPoints.length > this.maxTrailLength) {
                    this.trailPoints.shift();
                }
                // Fade trail points
                this.trailPoints.forEach((point, index) => {
                    point.alpha *= 0.95;
                });
            }

            // Mouse interaction
            if (mouseX !== undefined && mouseY !== undefined) {
                const dx = this.x - mouseX;
                const dy = this.y - mouseY;
                const distance = Math.sqrt(dx * dx + dy * dy);
                
                if (distance < physicsState.interactionRadius) {
                    const force = (physicsState.interactionRadius - distance) / physicsState.interactionRadius;
                    const angle = Math.atan2(dy, dx);
                    
                    if (physicsState.magneticMode) {
                        // Magnetic attraction/repulsion
                        const magneticForce = force * this.magneticCharge * 2;
                        this.vx += Math.cos(angle) * magneticForce;
                        this.vy += Math.sin(angle) * magneticForce;
                    } else {
                        // Normal repulsion
                        this.vx += Math.cos(angle) * force * 3;
                        this.vy += Math.sin(angle) * force * 3;
                    }
                    
                    // Change temperature based on interaction
                    this.temperature += force * 10;
                    this.radius = this.originalRadius + Math.sin(this.age * 0.1) * 5;
                }
            }

            // Gravity or anti-gravity
            if (physicsState.antigravityMode) {
                this.vy -= physicsState.gravityStrength;
            } else {
                this.vy += physicsState.gravityStrength;
            }

            // Bubble-to-bubble interactions
            this.connections = [];
            bubbles.forEach(other => {
                if (other !== this) {
                    const dx = other.x - this.x;
                    const dy = other.y - this.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    const minDistance = this.radius + other.radius;
                    
                    if (distance < minDistance + 30) {
                        // Surface tension effect
                        const overlap = minDistance - distance;
                        if (overlap > 0) {
                            const force = overlap * physicsState.tension;
                            const angle = Math.atan2(dy, dx);
                            
                            this.vx -= Math.cos(angle) * force * 0.5;
                            this.vy -= Math.sin(angle) * force * 0.5;
                            
                            // Color mixing on collision
                            if (physicsState.colorMixing && overlap > 10) {
                                this.mixColors(other);
                            }
                        }
                        
                        // Create connection for visual effect
                        if (distance < minDistance + 50) {
                            this.connections.push({
                                bubble: other,
                                distance: distance,
                                strength: 1 - (distance / (minDistance + 50))
                            });
                        }
                    }
                }
            });

            // Apply viscosity (liquid resistance)
            this.vx *= physicsState.viscosity;
            this.vy *= physicsState.viscosity;

            // Update position
            this.x += this.vx;
            this.y += this.vy;

            // Temperature cooling
            this.temperature *= 0.995;
            
            // Size pulsation based on temperature
            const tempFactor = (this.temperature - 50) / 100;
            this.radius = this.originalRadius + tempFactor * 10 + Math.sin(this.vibrationPhase + this.age * 0.1) * 2;
            this.vibrationPhase += 0.1;

            // Wall collision with liquid deformation
            if (this.x - this.radius < 0 || this.x + this.radius > window.innerWidth) {
                this.vx *= -this.elasticity;
                this.x = Math.max(this.radius, Math.min(window.innerWidth - this.radius, this.x));
                this.deform();
            }
            
            if (this.y - this.radius < 0 || this.y + this.radius > window.innerHeight) {
                this.vy *= -this.elasticity;
                this.y = Math.max(this.radius, Math.min(window.innerHeight - this.radius, this.y));
                this.deform();
            }

            // Life decay
            if (this.age > 2000) {
                this.life *= 0.999;
            }

            return this.life > 0.1;
        }

        mixColors(other) {
            // Simple color mixing algorithm
            const thisColor = this.parseColor(this.color);
            const otherColor = other.parseColor(other.color);
            
            if (thisColor && otherColor) {
                const newR = Math.floor((thisColor.r + otherColor.r) / 2);
                const newG = Math.floor((thisColor.g + otherColor.g) / 2);
                const newB = Math.floor((thisColor.b + otherColor.b) / 2);
                
                this.color = `rgba(${newR}, ${newG}, ${newB}, 0.7)`;
            }
        }

        parseColor(color) {
            const match = color.match(/rgba?$$(\d+),\s*(\d+),\s*(\d+)/);
            if (match) {
                return {
                    r: parseInt(match[1]),
                    g: parseInt(match[2]),
                    b: parseInt(match[3])
                };
            }
            return null;
        }

        deform() {
            // Temporary deformation effect
            this.radius *= 1.2;
            setTimeout(() => {
                this.radius = this.originalRadius;
            }, 100);
        }

        draw(ctx) {
            ctx.save();
            
            // Draw trail
            if (physicsState.trailMode && this.trailPoints.length > 1) {
                ctx.strokeStyle = this.color;
                ctx.lineWidth = 2;
                ctx.globalAlpha = 0.3;
                ctx.beginPath();
                ctx.moveTo(this.trailPoints.x, this.trailPoints.y);
                for (let i = 1; i < this.trailPoints.length; i++) {
                    ctx.lineTo(this.trailPoints[i].x, this.trailPoints[i].y);
                }
                ctx.stroke();
            }

            // Draw connections
            this.connections.forEach(conn => {
                ctx.globalAlpha = conn.strength * 0.3;
                ctx.strokeStyle = this.color;
                ctx.lineWidth = conn.strength * 3;
                ctx.beginPath();
                ctx.moveTo(this.x, this.y);
                ctx.lineTo(conn.bubble.x, conn.bubble.y);
                ctx.stroke();
            });

            // Main bubble
            ctx.globalAlpha = this.alpha * this.life;
            
            // Gradient fill for liquid effect
            const gradient = ctx.createRadialGradient(
                this.x - this.radius * 0.3, this.y - this.radius * 0.3, 0,
                this.x, this.y, this.radius
            );
            gradient.addColorStop(0, this.color.replace('0.7', '0.9'));
            gradient.addColorStop(0.7, this.color);
            gradient.addColorStop(1, this.color.replace('0.7', '0.3'));
            
            ctx.fillStyle = gradient;
            ctx.beginPath();
            ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
            ctx.fill();

            // Highlight for 3D effect
            ctx.globalAlpha = this.alpha * this.life * 0.6;
            ctx.fillStyle = 'rgba(255, 255, 255, 0.4)';
            ctx.beginPath();
            ctx.arc(this.x - this.radius * 0.3, this.y - this.radius * 0.3, this.radius * 0.3, 0, Math.PI * 2);
            ctx.fill();

            // Temperature indicator
            if (this.temperature > 80) {
                ctx.globalAlpha = (this.temperature - 80) / 100;
                ctx.strokeStyle = '#ff4444';
                ctx.lineWidth = 2;
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.radius + 3, 0, Math.PI * 2);
                ctx.stroke();
            }

            ctx.restore();
        }
    }

    // Liquid drop class for additional effects
    class LiquidDrop {
        constructor(x, y) {
            this.x = x;
            this.y = y;
            this.vx = (Math.random() - 0.5) * 6;
            this.vy = Math.random() * -8 - 2;
            this.size = Math.random() * 8 + 4;
            this.color = `hsl(${Math.random() * 360}, 70%, 60%)`;
            this.life = 1.0;
            this.gravity = 0.3;
        }

        update() {
            this.vy += this.gravity;
            this.x += this.vx;
            this.y += this.vy;
            this.life -= 0.02;
            this.size *= 0.98;

            return this.y < window.innerHeight && this.life > 0;
        }

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

    // Control panel creation
    function createPhysicsPanel() {
        const panel = document.createElement('div');
        panel.innerHTML = `
            <div id="physics-panel" style="
                position: fixed;
                top: 20px;
                right: 20px;
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                border-radius: 20px;
                padding: 25px;
                box-shadow: 0 20px 40px rgba(0,0,0,0.4);
                color: white;
                font-family: 'Segoe UI', sans-serif;
                z-index: 10000;
                min-width: 320px;
                max-height: 80vh;
                overflow-y: auto;
                backdrop-filter: blur(15px);
                border: 1px solid rgba(255,255,255,0.2);
            ">
                <h2 style="margin: 0 0 25px 0; text-align: center;">🫧 Liquid Physics Lab</h2>
                
                <!-- Physics Controls -->
                <div class="physics-section" style="
                    background: rgba(255,255,255,0.1);
                    padding: 15px;
                    border-radius: 12px;
                    margin-bottom: 20px;
                ">
                    <h3 style="margin: 0 0 15px 0; color: #e0e6ff; font-size: 14px;">⚡ PHYSICS ENGINE</h3>
                    
                    <div style="margin: 10px 0;">
                        <label>Gravity: <span id="gravity-display">0.1</span></label>
                        <input type="range" id="gravity-strength" min="0" max="0.5" step="0.01" value="0.1" style="width: 100%;">
                    </div>
                    
                    <div style="margin: 10px 0;">
                        <label>Viscosity: <span id="viscosity-display">0.99</span></label>
                        <input type="range" id="viscosity" min="0.9" max="1" step="0.001" value="0.99" style="width: 100%;">
                    </div>
                    
                    <div style="margin: 10px 0;">
                        <label>Surface Tension: <span id="tension-display">0.1</span></label>
                        <input type="range" id="surface-tension" min="0" max="0.5" step="0.01" value="0.1" style="width: 100%;">
                    </div>
                    
                    <div style="margin: 10px 0;">
                        <label>Interaction Radius: <span id="radius-display">80</span></label>
                        <input type="range" id="interaction-radius" min="30" max="150" value="80" style="width: 100%;">
                    </div>
                </div>

                <!-- Bubble Controls -->
                <div class="physics-section" style="
                    background: rgba(255,255,255,0.1);
                    padding: 15px;
                    border-radius: 12px;
                    margin-bottom: 20px;
                ">
                    <h3 style="margin: 0 0 15px 0; color: #e0e6ff; font-size: 14px;">🫧 BUBBLE SYSTEM</h3>
                    
                    <div style="margin: 10px 0;">
                        <label>Max Bubbles: <span id="bubbles-display">50</span></label>
                        <input type="range" id="max-bubbles" min="10" max="100" value="50" style="width: 100%;">
                    </div>
                    
                    <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 15px 0;">
                        <button id="add-bubble" style="padding: 8px; font-size: 12px;">➕ Add Bubble</button>
                        <button id="clear-bubbles" style="padding: 8px; font-size: 12px;">🗑️ Clear All</button>
                        <button id="bubble-explosion" style="padding: 8px; font-size: 12px;">💥 Explosion</button>
                        <button id="rainbow-mode" style="padding: 8px; font-size: 12px;">🌈 Rainbow</button>
                    </div>
                </div>

                <!-- Special Modes -->
                <div class="physics-section" style="
                    background: rgba(255,255,255,0.1);
                    padding: 15px;
                    border-radius: 12px;
                    margin-bottom: 20px;
                ">
                    <h3 style="margin: 0 0 15px 0; color: #e0e6ff; font-size: 14px;">🔬 SPECIAL MODES</h3>
                    
                    <div style="display: grid; grid-template-columns: 1fr; gap: 8px;">
                        <button id="magnetic-mode" style="padding: 10px;">🧲 Magnetic Field</button>
                        <button id="antigravity-mode" style="padding: 10px;">🚀 Anti-Gravity</button>
                        <button id="color-mixing" style="padding: 10px;">🎨 Color Mixing</button>
                        <button id="trail-mode" style="padding: 10px;">✨ Particle Trails</button>
                    </div>
                </div>

                <!-- Environmental Presets -->
                <div class="physics-section" style="
                    background: rgba(255,255,255,0.1);
                    padding: 15px;
                    border-radius: 12px;
                ">
                    <h3 style="margin: 0 0 15px 0; color: #e0e6ff; font-size: 14px;">🌍 ENVIRONMENTS</h3>
                    
                    <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px;">
                        <button class="env-preset" data-env="water">🌊 Water</button>
                        <button class="env-preset" data-env="space">🌌 Space</button>
                        <button class="env-preset" data-env="lava">🌋 Lava</button>
                        <button class="env-preset" data-env="ice">🧊 Ice</button>
                    </div>
                </div>

                <!-- Real-time Stats -->
                <div style="
                    background: rgba(0,0,0,0.2);
                    padding: 10px;
                    border-radius: 8px;
                    margin-top: 20px;
                    font-size: 12px;
                ">
                    <div>Active Bubbles: <span id="bubble-count">0</span></div>
                    <div>Liquid Drops: <span id="drops-count">0</span></div>
                    <div>Total Interactions: <span id="interactions-count">0</span></div>
                </div>
            </div>
        `;

        // Add styles
        const style = document.createElement('style');
        style.textContent = `
            #physics-panel button {
                background: rgba(255, 255, 255, 0.15);
                border: 1px solid rgba(255, 255, 255, 0.3);
                color: white;
                border-radius: 8px;
                cursor: pointer;
                transition: all 0.3s ease;
            }
            #physics-panel button:hover {
                background: rgba(255, 255, 255, 0.25);
                transform: translateY(-2px);
                box-shadow: 0 5px 15px rgba(0,0,0,0.2);
            }
            #physics-panel button.active {
                background: rgba(46, 213, 115, 0.4);
                border-color: #2ed573;
            }
            .env-preset {
                padding: 8px 4px !important;
                font-size: 11px !important;
            }
            #physics-panel input[type="range"] {
                background: rgba(255, 255, 255, 0.2);
                height: 6px;
                border-radius: 3px;
                margin: 5px 0;
            }
        `;
        document.head.appendChild(style);
        document.body.appendChild(panel);
        return panel;
    }

    // Main physics engine
    class LiquidPhysicsEngine {
        constructor() {
            this.canvas = this.createCanvas();
            this.ctx = this.canvas.getContext('2d');
            this.mouseX = 0;
            this.mouseY = 0;
            this.isMousePressed = false;
            this.lastBubbleSpawn = 0;
            this.interactionCount = 0;
            
            this.setupEventListeners();
            this.initializeBubbles();
            this.animate();
        }

        createCanvas() {
            const canvas = document.createElement('canvas');
            canvas.style.cssText = `
                position: fixed;
                top: 0;
                left: 0;
                width: 100vw;
                height: 100vh;
                pointer-events: none;
                z-index: 9999;
                background: transparent;
            `;
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
            document.body.appendChild(canvas);
            return canvas;
        }

        setupEventListeners() {
            document.addEventListener('mousemove', (e) => {
                this.mouseX = e.clientX;
                this.mouseY = e.clientY;
            });

            document.addEventListener('mousedown', () => {
                this.isMousePressed = true;
            });

            document.addEventListener('mouseup', () => {
                this.isMousePressed = false;
            });

            document.addEventListener('click', (e) => {
                // Spawn liquid drops on click
                for (let i = 0; i < 8; i++) {
                    physicsState.liquidDrops.push(new LiquidDrop(e.clientX, e.clientY));
                }
            });

            window.addEventListener('resize', () => {
                this.canvas.width = window.innerWidth;
                this.canvas.height = window.innerHeight;
            });
        }

        initializeBubbles() {
            physicsState.bubbles = [];
            for (let i = 0; i < 20; i++) {
                physicsState.bubbles.push(new LiquidBubble());
            }
        }

        spawnBubble(x, y, radius, color) {
            if (physicsState.bubbles.length < physicsState.maxBubbles) {
                physicsState.bubbles.push(new LiquidBubble(x, y, radius, color));
            }
        }

        createExplosion(x, y) {
            for (let i = 0; i < 15; i++) {
                const angle = (i / 15) * Math.PI * 2;
                const radius = Math.random() * 20 + 10;
                const bubbleX = x + Math.cos(angle) * (Math.random() * 100 + 50);
                const bubbleY = y + Math.sin(angle) * (Math.random() * 100 + 50);
                this.spawnBubble(bubbleX, bubbleY, radius);
            }
        }

        applyEnvironment(env) {
            switch(env) {
                case 'water':
                    physicsState.gravityStrength = 0.05;
                    physicsState.viscosity = 0.98;
                    physicsState.tension = 0.2;
                    break;
                case 'space':
                    physicsState.gravityStrength = 0;
                    physicsState.viscosity = 1;
                    physicsState.tension = 0.05;
                    break;
                case 'lava':
                    physicsState.gravityStrength = 0.15;
                    physicsState.viscosity = 0.95;
                    physicsState.tension = 0.3;
                    break;
                case 'ice':
                    physicsState.gravityStrength = 0.2;
                    physicsState.viscosity = 0.99;
                    physicsState.tension = 0.1;
                    break;
            }
            this.updateUIValues();
        }

        updateUIValues() {
            document.getElementById('gravity-display').textContent = physicsState.gravityStrength;
            document.getElementById('viscosity-display').textContent = physicsState.viscosity;
            document.getElementById('tension-display').textContent = physicsState.tension;
            document.getElementById('gravity-strength').value = physicsState.gravityStrength;
            document.getElementById('viscosity').value = physicsState.viscosity;
            document.getElementById('surface-tension').value = physicsState.tension;
        }

        updateStats() {
            document.getElementById('bubble-count').textContent = physicsState.bubbles.length;
            document.getElementById('drops-count').textContent = physicsState.liquidDrops.length;
            document.getElementById('interactions-count').textContent = this.interactionCount;
        }

        animate() {
            // Clear canvas with fade effect
            this.ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
            this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);

            // Update and count interactions
            this.interactionCount = 0;

            // Update bubbles
            physicsState.bubbles = physicsState.bubbles.filter(bubble => {
                const alive = bubble.update(physicsState.bubbles, this.mouseX, this.mouseY);
                if (alive) {
                    bubble.draw(this.ctx);
                    this.interactionCount += bubble.connections.length;
                }
                return alive;
            });

            // Update liquid drops
            physicsState.liquidDrops = physicsState.liquidDrops.filter(drop => {
                const alive = drop.update();
                if (alive) drop.draw(this.ctx);
                return alive;
            });

            // Spawn bubbles during mouse press
            if (this.isMousePressed && Date.now() - this.lastBubbleSpawn > 200) {
                this.spawnBubble(this.mouseX, this.mouseY, Math.random() * 25 + 15);
                this.lastBubbleSpawn = Date.now();
            }

            // Update stats
            this.updateStats();

            requestAnimationFrame(() => this.animate());
        }
    }

    // Initialize the system
    function init() {
        const panel = createPhysicsPanel();
        const engine = new LiquidPhysicsEngine();

        // Physics control event listeners
        document.getElementById('gravity-strength').oninput = (e) => {
            physicsState.gravityStrength = parseFloat(e.target.value);
            document.getElementById('gravity-display').textContent = e.target.value;
        };

        document.getElementById('viscosity').oninput = (e) => {
            physicsState.viscosity = parseFloat(e.target.value);
            document.getElementById('viscosity-display').textContent = e.target.value;
        };

        document.getElementById('surface-tension').oninput = (e) => {
            physicsState.tension = parseFloat(e.target.value);
            document.getElementById('tension-display').textContent = e.target.value;
        };

        document.getElementById('interaction-radius').oninput = (e) => {
            physicsState.interactionRadius = parseInt(e.target.value);
            document.getElementById('radius-display').textContent = e.target.value;
        };

        document.getElementById('max-bubbles').oninput = (e) => {
            physicsState.maxBubbles = parseInt(e.target.value);
            document.getElementById('bubbles-display').textContent = e.target.value;
        };

        // Bubble controls
        document.getElementById('add-bubble').onclick = () => {
            engine.spawnBubble(Math.random() * window.innerWidth, Math.random() * window.innerHeight);
        };

        document.getElementById('clear-bubbles').onclick = () => {
            physicsState.bubbles = [];
            physicsState.liquidDrops = [];
        };

        document.getElementById('bubble-explosion').onclick = () => {
            engine.createExplosion(window.innerWidth / 2, window.innerHeight / 2);
        };

        document.getElementById('rainbow-mode').onclick = () => {
            physicsState.bubbles.forEach(bubble => {
                bubble.color = `hsl(${Math.random() * 360}, 70%, 60%)`;
            });
        };

        // Special modes
        const toggleMode = (buttonId, stateKey) => {
            const button = document.getElementById(buttonId);
            button.onclick = () => {
                physicsState[stateKey] = !physicsState[stateKey];
                button.classList.toggle('active', physicsState[stateKey]);
            };
        };

        toggleMode('magnetic-mode', 'magneticMode');
        toggleMode('antigravity-mode', 'antigravityMode');
        toggleMode('color-mixing', 'colorMixing');
        toggleMode('trail-mode', 'trailMode');

        // Environment presets
        document.querySelectorAll('.env-preset').forEach(button => {
            button.onclick = () => {
                engine.applyEnvironment(button.dataset.env);
                document.querySelectorAll('.env-preset').forEach(b => b.classList.remove('active'));
                button.classList.add('active');
            };
        });

        // Welcome message
        setTimeout(() => {
            const welcome = document.createElement('div');
            welcome.innerHTML = `
                <div style="
                    position: fixed;
                    top: 50%;
                    left: 50%;
                    transform: translate(-50%, -50%);
                    background: linear-gradient(135deg, #667eea, #764ba2);
                    color: white;
                    padding: 30px;
                    border-radius: 20px;
                    text-align: center;
                    z-index: 10001;
                    box-shadow: 0 25px 50px rgba(0,0,0,0.4);
                    animation: liquidWelcome 6s ease-in-out forwards;
                ">
                    <h2>🫧 Liquid Physics Lab Activated! 🫧</h2>
                    <p>🖱️ Click and drag to create bubbles!</p>
                    <p>🧲 Try magnetic mode for crazy interactions!</p>
                    <p>🌊 Experiment with different environments!</p>
                    <p>💥 Create bubble explosions and watch them mix!</p>
                </div>
            `;

            const welcomeStyle = document.createElement('style');
            welcomeStyle.textContent = `
                @keyframes liquidWelcome {
                    0% { opacity: 0; transform: translate(-50%, -50%) scale(0.3) rotate(10deg); }
                    15% { opacity: 1; transform: translate(-50%, -50%) scale(1.05) rotate(-2deg); }
                    25% { transform: translate(-50%, -50%) scale(0.95) rotate(1deg); }
                    35% { transform: translate(-50%, -50%) scale(1.02) rotate(-0.5deg); }
                    45% { transform: translate(-50%, -50%) scale(1) rotate(0deg); }
                    80% { opacity: 1; transform: translate(-50%, -50%) scale(1) rotate(0deg); }
                    100% { opacity: 0; transform: translate(-50%, -50%) scale(0.7) rotate(5deg); }
                }
            `;
            document.head.appendChild(welcomeStyle);
            document.body.appendChild(welcome);

            setTimeout(() => welcome.remove(), 6000);
        }, 2000);

        console.log('🫧 Liquid Physics Lab initialized!');
    }

    // Start the liquid physics system
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();