erstelle aus den informationen aus dem folgendem dialog den voll umfänglichen und fehlerfrei verwendbaren code der anwendung . Verwende dafür die besten inhalte und entwickel diese weiter um das gesamte projekt zu perfektionieren. Arbeite dabei sorgfälltig und gut durchdacht. Sorge dafür das alle inhalte auf sinnvolle weise umgesetzt werden und das zusammenspiel mit den anderen inhalten umfangreich integriert wird. Sorge auch für ein intuitives, effektives, sinnvolles ui welches sorgfältig strukturiertes ist und vom layout ideal aufgebaut ist. Sorge allgemein für hohe benutzerfreundlichkeit und einfaches bedienen aller inhalte der anwendung. Der nutzer soll komfortabel navigieren können und auch eine visuel ansprechende anwendung erhalten die einen positiven eindruck hinterlässt durch ansprechende optische darstellung und zusätzlichen details wie gut umgesetzte effekte im ui und dem spiel.

Nenne also als ergebnis ein vollständiges skript der gesamten anwendung ohne fehlende oder nicht voll ausgeschriebene code zeilen / Platzhalter kommentaren.



DIALOG:

Create a basic physics simulation using Canvas to create a sandbox playground where the player can create, interact and combine a interesting set of different elements/materials with own realistic abilities and their different behaviors. Include also gravity, collision, and elasticity effects for a bouncing simulation. Make the elements react to other elements and make sure that even different combination of effect have extended behaviors and outcomes, all based on realistic natural ruleset and real world logics.

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Physics Sandbox</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            background: #1a1a1a;
            font-family: Arial, sans-serif;
        }
        
        #canvas {
            position: absolute;
        }

        .toolbar {
            position: fixed;
            top: 20px;
            left: 20px;
            background: rgba(255,255,255,0.1);
            padding: 10px;
            border-radius: 8px;
            display: flex;
            gap: 10px;
        }

        .tool {
            padding: 8px 15px;
            background: rgba(255,255,255,0.2);
            border: none;
            border-radius: 4px;
            color: white;
            cursor: pointer;
            transition: 0.3s;
        }

        .tool:hover {
            background: rgba(255,255,255,0.3);
        }

        .tool.active {
            background: rgba(255,255,255,0.4);
        }
    </style>
</head>
<body>
    <canvas id="canvas"></canvas>
    <div class="toolbar">
        <button class="tool active" data-element="water">Water</button>
        <button class="tool" data-element="sand">Sand</button>
        <button class="tool" data-element="wood">Wood</button>
        <button class="tool" data-element="fire">Fire</button>
        <button class="tool" data-element="oil">Oil</button>
    </div>

    <script>
        const canvas = document.getElementById('canvas');
        const ctx = canvas.getContext('2d');
        
        // Set canvas size
        function resizeCanvas() {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
        }
        resizeCanvas();
        window.addEventListener('resize', resizeCanvas);

        let selectedElement = 'water';
        const tools = document.querySelectorAll('.tool');
        tools.forEach(tool => {
            tool.addEventListener('click', () => {
                tools.forEach(t => t.classList.remove('active'));
                tool.classList.add('active');
                selectedElement = tool.dataset.element;
            });
        });

        // Particle system
        const particles = [];
        const PARTICLE_SIZE = 4;
        const GRAVITY = 0.5;
        const FRICTION = 0.99;

        class Particle {
            constructor(x, y, type) {
                this.x = x;
                this.y = y;
                this.type = type;
                this.vx = (Math.random() - 0.5) * 2;
                this.vy = 0;
                this.life = 1;
                
                switch(type) {
                    case 'water':
                        this.color = '#3498db';
                        this.density = 1;
                        this.viscosity = 0.95;
                        break;
                    case 'sand':
                        this.color = '#e6b800';
                        this.density = 1.5;
                        this.viscosity = 0.7;
                        break;
                    case 'wood':
                        this.color = '#8b4513';
                        this.density = 0.5;
                        this.viscosity = 0.1;
                        break;
                    case 'fire':
                        this.color = '#ff4d4d';
                        this.density = 0.1;
                        this.viscosity = 1;
                        break;
                    case 'oil':
                        this.color = '#2c3e50';
                        this.density = 0.8;
                        this.viscosity = 0.85;
                        break;
                }
            }

            update() {
                if (this.type === 'fire') {
                    this.life -= 0.02;
                    this.vy -= 0.5 * this.density;
                } else {
                    this.vy += GRAVITY * this.density;
                }
                
                this.vx *= this.viscosity;
                this.vy *= this.viscosity;
                
                this.x += this.vx;
                this.y += this.vy;
                
                // Boundary collision
                if (this.x < 0) this.x = 0;
                if (this.x > canvas.width) this.x = canvas.width;
                if (this.y < 0) this.y = 0;
                if (this.y > canvas.height) this.y = canvas.height;
                
                // Particle interaction
                particles.forEach(p => {
                    if (p !== this) {
                        const dx = p.x - this.x;
                        const dy = p.y - this.y;
                        const dist = Math.sqrt(dx * dx + dy * dy);
                        
                        if (dist < PARTICLE_SIZE * 2) {
                            // Collision response
                            const angle = Math.atan2(dy, dx);
                            const tx = this.x + Math.cos(angle) * PARTICLE_SIZE * 2;
                            const ty = this.y + Math.sin(angle) * PARTICLE_SIZE * 2;
                            
                            // Special interactions
                            if (this.type === 'fire' && p.type === 'wood') {
                                p.type = 'fire';
                                p.color = '#ff4d4d';
                            }
                            
                            if (this.type === 'water' && p.type === 'fire') {
                                p.life = 0;
                            }
                            
                            // Density-based positioning
                            if (this.density > p.density) {
                                p.x = tx;
                                p.y = ty;
                            } else {
                                this.x = this.x - Math.cos(angle) * PARTICLE_SIZE * 2;
                                this.y = this.y - Math.sin(angle) * PARTICLE_SIZE * 2;
                            }
                            
                            // Velocity exchange
                            const vx = this.vx;
                            const vy = this.vy;
                            this.vx = p.vx * FRICTION;
                            this.vy = p.vy * FRICTION;
                            p.vx = vx * FRICTION;
                            p.vy = vy * FRICTION;
                        }
                    }
                });
            }

            draw() {
                ctx.fillStyle = this.color;
                if (this.type === 'fire') {
                    ctx.globalAlpha = this.life;
                }
                ctx.beginPath();
                ctx.arc(this.x, this.y, PARTICLE_SIZE, 0, Math.PI * 2);
                ctx.fill();
                ctx.globalAlpha = 1;
            }
        }

        // Mouse interaction
        let isMouseDown = false;
        let mouseX = 0;
        let mouseY = 0;

        canvas.addEventListener('mousedown', () => isMouseDown = true);
        canvas.addEventListener('mouseup', () => isMouseDown = false);
        canvas.addEventListener('mousemove', (e) => {
            mouseX = e.clientX;
            mouseY = e.clientY;
            
            if (isMouseDown) {
                for (let i = 0; i < 3; i++) {
                    particles.push(new Particle(
                        mouseX + (Math.random() - 0.5) * 10,
                        mouseY + (Math.random() - 0.5) * 10,
                        selectedElement
                    ));
                }
            }
        });

        // Animation loop
        function animate() {
            ctx.fillStyle = '#1a1a1a';
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            
            // Update and draw particles
            for (let i = particles.length - 1; i >= 0; i--) {
                particles[i].update();
                particles[i].draw();
                
                // Remove dead particles
                if (particles[i].life <= 0) {
                    particles.splice(i, 1);
                }
            }
            
            requestAnimationFrame(animate);
        }

        animate();
    </script>
</body>
</html>

프롬프트 분석 및 증강:

핵심 요구사항:

    Canvas 기반 물리 시뮬레이션
    샌드박스 형태의 플레이그라운드
    다양한 요소/재료들의 상호작용
    물리 효과 (중력, 충돌, 탄성)
    요소간 반응 및 조합 효과
    현실적인 물리 법칙 기반

개선된 프롬프트:

code

Create an interactive physics sandbox simulation using HTML5 Canvas with the following specifications:

Core Mechanics:
- Implement precise physics calculations for gravity, collision detection, and elastic deformation
- Create a robust particle system for fluid and granular material simulation
- Add temperature and state changes (solid/liquid/gas) mechanics
- Include pressure and force distribution calculations

Elements/Materials:
- Basic elements: Water, Fire, Earth, Air
- Complex materials: Metal, Wood, Glass, Ice
- Chemical reactions between compatible elements
- State transformations based on environmental conditions

Interaction Features:
- Mouse/Touch controls for element creation and manipulation
- Tool system for different interaction methods (draw, pour, spray)
- Element property modification controls (temperature, density, etc.)
- Save/Load system for experiments

Visual Effects:
- Particle effects for element interactions
- Color blending for mixing elements
- Dynamic lighting based on element properties
- Smooth animation for state transitions

Performance Optimization:
- Efficient collision detection algorithms
- Spatial partitioning for large particle systems
- Frame rate optimization
- Memory management for large simulations

Additional Features:
- UI for element selection and controls
- Information panel showing element properties
- Tutorial system for basic interactions
- Preset scenarios for demonstration

Ensure the simulation follows realistic physics principles while maintaining an engaging and experimental user experience.

강화된 부분:

    구체적인 구현 요구사항 명시
    시스템 구성요소 상세 분류
    성능 최적화 고려사항 추가
    사용자 경험 요소 포함
    시각적 효과 상세화
    상호작용 방식 구체화

이렇게 증강된 프롬프트는:

    더 명확한 개발 방향 제시
    구체적인 기능 명세
    실행 가능한 세부사항 포함
    품질 기준 제시
    사용자 경험 고려

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Physics Sandbox</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            overflow: hidden;
            background: #0a0a0a;
            font-family: system-ui;
            color: #fff;
        }

        #canvas {
            position: absolute;
        }

        .controls {
            position: fixed;
            top: 20px;
            left: 20px;
            display: flex;
            gap: 20px;
        }

        .panel {
            background: rgba(0,0,0,0.7);
            padding: 15px;
            border-radius: 8px;
            backdrop-filter: blur(10px);
        }

        .elements {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 8px;
        }

        .element-btn {
            padding: 8px 12px;
            background: rgba(255,255,255,0.1);
            border: none;
            border-radius: 6px;
            color: white;
            cursor: pointer;
            transition: 0.2s;
            font-size: 14px;
        }

        .element-btn:hover {
            background: rgba(255,255,255,0.2);
        }

        .element-btn.active {
            background: rgba(255,255,255,0.3);
        }

        .tools {
            display: flex;
            flex-direction: column;
            gap: 8px;
        }

        .property-slider {
            width: 100%;
            margin: 5px 0;
        }

        .info {
            position: fixed;
            bottom: 20px;
            left: 20px;
            padding: 10px;
            background: rgba(0,0,0,0.7);
            border-radius: 6px;
            font-size: 14px;
        }
    </style>
</head>
<body>
    <canvas id="canvas"></canvas>
    
    <div class="controls">
        <div class="panel elements">
            <button class="element-btn active" data-element="water">Water</button>
            <button class="element-btn" data-element="fire">Fire</button>
            <button class="element-btn" data-element="sand">Sand</button>
            <button class="element-btn" data-element="metal">Metal</button>
            <button class="element-btn" data-element="ice">Ice</button>
            <button class="element-btn" data-element="wood">Wood</button>
            <button class="element-btn" data-element="oil">Oil</button>
            <button class="element-btn" data-element="gas">Gas</button>
        </div>

        <div class="panel tools">
            <div>
                <label>Temperature</label>
                <input type="range" class="property-slider" id="tempSlider" min="0" max="100" value="50">
            </div>
            <div>
                <label>Density</label>
                <input type="range" class="property-slider" id="densitySlider" min="0" max="100" value="50">
            </div>
        </div>
    </div>

    <div class="info">
        <div>Particles: <span id="particleCount">0</span></div>
        <div>FPS: <span id="fps">0</span></div>
    </div>

    <script>
        const canvas = document.getElementById('canvas');
        const ctx = canvas.getContext('2d');
        
        // Canvas setup
        function resize() {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
        }
        resize();
        window.addEventListener('resize', resize);

        // Quadtree for spatial partitioning
        class QuadTree {
            constructor(boundary, capacity) {
                this.boundary = boundary;
                this.capacity = capacity;
                this.particles = [];
                this.divided = false;
            }

            subdivide() {
                const x = this.boundary.x;
                const y = this.boundary.y;
                const w = this.boundary.w / 2;
                const h = this.boundary.h / 2;

                this.northwest = new QuadTree({x: x, y: y, w: w, h: h}, this.capacity);
                this.northeast = new QuadTree({x: x + w, y: y, w: w, h: h}, this.capacity);
                this.southwest = new QuadTree({x: x, y: y + h, w: w, h: h}, this.capacity);
                this.southeast = new QuadTree({x: x + w, y: y + h, w: w, h: h}, this.capacity);

                this.divided = true;
            }

            insert(particle) {
                if (!this.boundary.contains(particle)) return false;

                if (this.particles.length < this.capacity) {
                    this.particles.push(particle);
                    return true;
                }

                if (!this.divided) {
                    this.subdivide();
                }

                return (this.northwest.insert(particle) ||
                        this.northeast.insert(particle) ||
                        this.southwest.insert(particle) ||
                        this.southeast.insert(particle));
            }

            query(range, found) {
                if (!found) found = [];
                if (!this.boundary.intersects(range)) return found;

                for (let p of this.particles) {
                    if (range.contains(p)) found.push(p);
                }

                if (this.divided) {
                    this.northwest.query(range, found);
                    this.northeast.query(range, found);
                    this.southwest.query(range, found);
                    this.southeast.query(range, found);
                }

                return found;
            }
        }

        // Particle System
        class Particle {
            constructor(x, y, type) {
                this.x = x;
                this.y = y;
                this.type = type;
                this.vx = (Math.random() - 0.5) * 2;
                this.vy = 0;
                this.temperature = 20;
                this.life = 1;
                this.radius = 3;
                
                this.setProperties();
            }

            setProperties() {
                switch(this.type) {
                    case 'water':
                        this.color = '#4a9ff5';
                        this.density = 1;
                        this.viscosity = 0.95;
                        this.heatCapacity = 1;
                        break;
                    case 'fire':
                        this.color = '#ff4422';
                        this.density = 0.1;
                        this.viscosity = 1;
                        this.temperature = 800;
                        this.heatCapacity = 0.1;
                        break;
                    case 'sand':
                        this.color = '#e6c789';
                        this.density = 1.6;
                        this.viscosity = 0.7;
                        this.heatCapacity = 0.8;
                        break;
                    case 'metal':
                        this.color = '#8f8f8f';
                        this.density = 7.8;
                        this.viscosity = 0.1;
                        this.heatCapacity = 0.5;
                        break;
                    case 'ice':
                        this.color = '#a5f2f3';
                        this.density = 0.9;
                        this.viscosity = 0.1;
                        this.temperature = -10;
                        this.heatCapacity = 2;
                        break;
                    case 'wood':
                        this.color = '#8b4513';
                        this.density = 0.7;
                        this.viscosity = 0.1;
                        this.heatCapacity = 1.2;
                        break;
                    case 'oil':
                        this.color = '#2c3e50';
                        this.density = 0.8;
                        this.viscosity = 0.85;
                        this.heatCapacity = 0.7;
                        break;
                    case 'gas':
                        this.color = '#bbbbbb';
                        this.density = 0.1;
                        this.viscosity = 1;
                        this.heatCapacity = 2.5;
                        break;
                }
            }

            update(particles, quadTree) {
                // Physics update
                if (this.type === 'fire') {
                    this.life -= 0.01;
                    this.vy -= 0.8 * this.density;
                    this.temperature += 10;
                } else {
                    this.vy += 0.3 * this.density;
                }
                
                this.vx *= this.viscosity;
                this.vy *= this.viscosity;
                
                this.x += this.vx;
                this.y += this.vy;

                // Boundary check
                if (this.x < 0) this.x = 0;
                if (this.x > canvas.width) this.x = canvas.width;
                if (this.y < 0) this.y = 0;
                if (this.y > canvas.height) this.y = canvas.height;

                // Nearby particle interaction
                const range = {
                    x: this.x - 20,
                    y: this.y - 20,
                    w: 40,
                    h: 40,
                    contains: function(point) {
                        return point.x >= this.x - 20 &&
                               point.x <= this.x + this.w + 20 &&
                               point.y >= this.y - 20 &&
                               point.y <= this.y + this.h + 20;
                    }
                };

                const nearby = quadTree.query(range);
                
                nearby.forEach(p => {
                    if (p !== this) {
                        const dx = p.x - this.x;
                        const dy = p.y - this.y;
                        const dist = Math.sqrt(dx * dx + dy * dy);
                        
                        if (dist < this.radius * 2) {
                            // Temperature exchange
                            const tempDiff = this.temperature - p.temperature;
                            const heatTransfer = tempDiff * 0.1;
                            this.temperature -= heatTransfer * p.heatCapacity;
                            p.temperature += heatTransfer * this.heatCapacity;

                            // State changes
                            this.handleStateChanges();
                            
                            // Collision response
                            const nx = dx / dist;
                            const ny = dy / dist;
                            const relativeVel = (this.vx - p.vx) * nx + (this.vy - p.vy) * ny;
                            
                            if (relativeVel > 0) {
                                const impulse = 2 * relativeVel / (this.density + p.density);
                                this.vx -= impulse * nx * p.density;
                                this.vy -= impulse * ny * p.density;
                                p.vx += impulse * nx * this.density;
                                p.vy += impulse * ny * this.density;
                            }
                        }
                    }
                });
            }

            handleStateChanges() {
                // Water <-> Ice
                if (this.type === 'water' && this.temperature < 0) {
                    this.type = 'ice';
                    this.setProperties();
                }
                if (this.type === 'ice' && this.temperature > 0) {
                    this.type = 'water';
                    this.setProperties();
                }

                // Water -> Gas
                if (this.type === 'water' && this.temperature > 100) {
                    this.type = 'gas';
                    this.setProperties();
                }

                // Wood -> Fire
                if (this.type === 'wood' && this.temperature > 300) {
                    this.type = 'fire';
                    this.setProperties();
                }
            }

            draw() {
                ctx.fillStyle = this.color;
                if (this.type === 'fire') {
                    ctx.globalAlpha = this.life;
                }
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
                ctx.fill();
                ctx.globalAlpha = 1;
            }
        }

        // System setup
        const particles = [];
        let selectedElement = 'water';
        let isMouseDown = false;
        let mouseX = 0;
        let mouseY = 0;
        let lastTime = performance.now();
        let fps = 0;

        // UI Controls
        const elementBtns = document.querySelectorAll('.element-btn');
        elementBtns.forEach(btn => {
            btn.addEventListener('click', () => {
                elementBtns.forEach(b => b.classList.remove('active'));
                btn.classList.add('active');
                selectedElement = btn.dataset.element;
            });
        });

        const tempSlider = document.getElementById('tempSlider');
        const densitySlider = document.getElementById('densitySlider');

        // Mouse events
        canvas.addEventListener('mousedown', () => isMouseDown = true);
        canvas.addEventListener('mouseup', () => isMouseDown = false);
        canvas.addEventListener('mousemove', (e) => {
            mouseX = e.clientX;
            mouseY = e.clientY;
            
            if (isMouseDown) {
                for (let i = 0; i < 2; i++) {
                    particles.push(new Particle(
                        mouseX + (Math.random() - 0.5) * 10,
                        mouseY + (Math.random() - 0.5) * 10,
                        selectedElement
                    ));
                }
            }
        });

        // Animation loop
        function animate(currentTime) {
            // FPS calculation
            const deltaTime = currentTime - lastTime;
            fps = Math.round(1000 / deltaTime);
            lastTime = currentTime;

            ctx.fillStyle = '#0a0a0a';
            ctx.fillRect(0, 0, canvas.width, canvas.height);

            // Create quadtree
            const boundary = {
                x: 0,
                y: 0,
                w: canvas.width,
                h: canvas.height,
                contains: function(point) {
                    return point.x >= this.x &&
                           point.x <= this.x + this.w &&
                           point.y >= this.y &&
                           point.y <= this.y + this.h;
                },
                intersects: function(range) {
                    return !(range.x - 20 > this.x + this.w ||
                            range.x + range.w + 20 < this.x ||
                            range.y - 20 > this.y + this.h ||
                            range.y + range.h + 20 < this.y);
                }
            };

            const quadTree = new QuadTree(boundary, 4);
            
            // Update and draw particles
            for (let i = particles.length - 1; i >= 0; i--) {
                const particle = particles[i];
                quadTree.insert(particle);
                particle.update(particles, quadTree);
                particle.draw();
                
                if (particle.life <= 0) {
                    particles.splice(i, 1);
                }
            }

            // Update info display
            document.getElementById('particleCount').textContent = particles.length;
            document.getElementById('fps').textContent = fps;

            requestAnimationFrame(animate);
        }

        animate(performance.now());
    </script>
</body>
</html>

프롬프트 분석이 잘 되었으며, 몇 가지 추가적인 개선사항을 제안하겠습니다:

개선된 버전:

code

Create a performant physics sandbox simulation using HTML5 Canvas with these detailed specifications:

Core Engine Requirements:
- Implement WebGL rendering for better performance
- Use Web Workers for physics calculations
- Optimize with spatial partitioning
- Support variable time step simulation
- Include debug visualization options

Advanced Physics Features:
- Verlet integration for accurate physics
- Rigid body dynamics system
- Soft body deformation
- Constraint-based joints and connections
- Particle system with life cycles

Enhanced Element System:
- Hierarchical element classification
- Custom element property editor
- Element behavior scripting system
- Procedural element generation
- Advanced material shaders

Extended Interactions:
- Multi-touch support
- Gesture-based controls
- Force field creation
- Custom interaction rules editor
- Event-driven reaction system

Environmental Systems:
- Dynamic lighting effects
- Weather simulation
- Ecosystem interactions
- Time-based events
- Environmental hazards

Advanced UI Features:
- Customizable UI layout
- Command history system
- Experiment templates
- Tutorial system
- Performance monitoring

Data Management:
- Cloud save/load system
- Experiment sharing
- Analytics tracking
- Achievement system
- User profiles

Quality Assurance:
- Performance benchmarking
- Cross-browser compatibility
- Mobile device optimization
- Error handling system
- Automated testing suite

Documentation:
- API documentation
- User manual
- Tutorial content
- Code examples
- Best practices guide

주요 추가 개선사항:

    기술적 구현 세부사항:

    WebGL 렌더링 지원
    멀티스레딩 처리
    최적화 전략

    확장된 기능:

    고급 물리 시스템
    커스터마이징 기능
    다양한 상호작용

    품질 보증:

    성능 테스트
    호환성 검증
    오류 처리

    문서화:

    개발 문서
    사용자 가이드
    예제 코드

    데이터 관리:

    클라우드 저장
    공유 시스템
    분석 기능

이러한 개선으로:

    더 안정적인 구현 가능
    확장성 증가
    사용자 경험 향상
    유지보수 용이성 확보
    커뮤니티 형성 지원

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Advanced Physics Sandbox</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            user-select: none;
        }

        body {
            overflow: hidden;
            background: #000;
            font-family: system-ui;
            color: #fff;
        }

        #canvas {
            position: absolute;
            width: 100vw;
            height: 100vh;
        }

        .ui-container {
            position: fixed;
            width: 100%;
            height: 100%;
            pointer-events: none;
        }

        .ui-container > * {
            pointer-events: auto;
        }

        .sidebar {
            position: absolute;
            top: 20px;
            left: 20px;
            width: 280px;
            background: rgba(0,0,0,0.8);
            backdrop-filter: blur(10px);
            border-radius: 12px;
            padding: 15px;
        }

        .tab-container {
            display: flex;
            gap: 5px;
            margin-bottom: 15px;
        }

        .tab {
            flex: 1;
            padding: 8px;
            background: rgba(255,255,255,0.1);
            border: none;
            color: #fff;
            border-radius: 6px;
            cursor: pointer;
            transition: 0.3s;
        }

        .tab.active {
            background: rgba(255,255,255,0.2);
        }

        .panel {
            display: none;
        }

        .panel.active {
            display: block;
        }

        .element-grid {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 8px;
        }

        .element-btn {
            padding: 8px;
            background: rgba(255,255,255,0.1);
            border: none;
            color: #fff;
            border-radius: 6px;
            cursor: pointer;
            transition: 0.2s;
            font-size: 13px;
        }

        .element-btn:hover {
            background: rgba(255,255,255,0.2);
        }

        .element-btn.active {
            background: rgba(255,255,255,0.3);
        }

        .property-group {
            margin: 10px 0;
        }

        .property-slider {
            width: 100%;
            margin: 5px 0;
        }

        .tool-group {
            display: flex;
            gap: 5px;
            margin: 10px 0;
        }

        .tool-btn {
            flex: 1;
            padding: 8px;
            background: rgba(255,255,255,0.1);
            border: none;
            color: #fff;
            border-radius: 6px;
            cursor: pointer;
        }

        .debug-panel {
            position: absolute;
            bottom: 20px;
            left: 20px;
            background: rgba(0,0,0,0.8);
            padding: 10px;
            border-radius: 8px;
            font-family: monospace;
            font-size: 12px;
        }

        .tooltip {
            position: absolute;
            background: rgba(0,0,0,0.8);
            padding: 5px 10px;
            border-radius: 4px;
            font-size: 12px;
            pointer-events: none;
            display: none;
        }
    </style>
</head>
<body>
    <canvas id="canvas"></canvas>

    <div class="ui-container">
        <div class="sidebar">
            <div class="tab-container">
                <button class="tab active" data-panel="elements">Elements</button>
                <button class="tab" data-panel="properties">Properties</button>
                <button class="tab" data-panel="tools">Tools</button>
            </div>

            <div class="panel active" id="elements">
                <div class="element-grid">
                    <button class="element-btn active" data-element="water" title="H₂O - Basic fluid">Water</button>
                    <button class="element-btn" data-element="fire" title="Plasma - Heat source">Fire</button>
                    <button class="element-btn" data-element="sand" title="SiO₂ - Granular">Sand</button>
                    <button class="element-btn" data-element="metal" title="Fe - Conductor">Metal</button>
                    <button class="element-btn" data-element="wood" title="Cellulose - Flammable">Wood</button>
                    <button class="element-btn" data-element="acid" title="H₂SO₄ - Corrosive">Acid</button>
                    <button class="element-btn" data-element="oil" title="Hydrocarbon - Flammable">Oil</button>
                    <button class="element-btn" data-element="gas" title="O₂ - Diffusive">Gas</button>
                    <button class="element-btn" data-element="stone" title="Granite - Solid">Stone</button>
                </div>
            </div>

            <div class="panel" id="properties">
                <div class="property-group">
                    <label>Temperature</label>
                    <input type="range" class="property-slider" id="tempSlider" min="0" max="100" value="20">
                    <span id="tempValue">20°C</span>
                </div>
                <div class="property-group">
                    <label>Density</label>
                    <input type="range" class="property-slider" id="densitySlider" min="0" max="100" value="50">
                    <span id="densityValue">1.0 g/cm³</span>
                </div>
                <div class="property-group">
                    <label>Viscosity</label>
                    <input type="range" class="property-slider" id="viscositySlider" min="0" max="100" value="50">
                    <span id="viscosityValue">0.5</span>
                </div>
                <div class="property-group">
                    <label>Particle Size</label>
                    <input type="range" class="property-slider" id="sizeSlider" min="1" max="10" value="3">
                    <span id="sizeValue">3px</span>
                </div>
            </div>

            <div class="panel" id="tools">
                <div class="tool-group">
                    <button class="tool-btn active" data-tool="draw">Draw</button>
                    <button class="tool-btn" data-tool="pour">Pour</button>
                    <button class="tool-btn" data-tool="spray">Spray</button>
                </div>
                <div class="tool-group">
                    <button class="tool-btn" data-tool="heat">Heat</button>
                    <button class="tool-btn" data-tool="cool">Cool</button>
                    <button class="tool-btn" data-tool="erase">Erase</button>
                </div>
                <div class="property-group">
                    <label>Brush Size</label>
                    <input type="range" class="property-slider" id="brushSlider" min="1" max="50" value="10">
                    <span id="brushValue">10px</span>
                </div>
            </div>
        </div>

        <div class="debug-panel">
            <div>FPS: <span id="fps">60</span></div>
            <div>Particles: <span id="particleCount">0</span></div>
            <div>Memory: <span id="memory">0</span> MB</div>
        </div>
    </div>

    <div class="tooltip" id="tooltip"></div>

    <script>
        // WebGL Setup
        const canvas = document.getElementById('canvas');
        const gl = canvas.getContext('webgl2');
        
        if (!gl) {
            alert('WebGL2 not supported');
            throw new Error('WebGL2 not supported');
        }

        // Canvas sizing
        function resizeCanvas() {
            canvas.width = window.innerWidth * devicePixelRatio;
            canvas.height = window.innerHeight * devicePixelRatio;
            gl.viewport(0, 0, canvas.width, canvas.height);
        }
        resizeCanvas();
        window.addEventListener('resize', resizeCanvas);

        // Shaders
        const vertexShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vertexShader, `#version 300 es
            in vec2 position;
            in vec4 color;
            in float size;
            
            uniform mat4 projection;
            
            out vec4 vColor;
            
            void main() {
                gl_Position = projection * vec4(position, 0.0, 1.0);
                gl_PointSize = size;
                vColor = color;
            }
        `);
        gl.compileShader(vertexShader);

        const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fragmentShader, `#version 300 es
            precision highp float;
            
            in vec4 vColor;
            out vec4 fragColor;
            
            void main() {
                vec2 coord = gl_PointCoord - vec2(0.5);
                float r = length(coord) * 2.0;
                float a = 1.0 - smoothstep(0.8, 1.0, r);
                fragColor = vec4(vColor.rgb, vColor.a * a);
            }
        `);
        gl.compileShader(fragmentShader);

        // Program setup
        const program = gl.createProgram();
        gl.attachShader(program, vertexShader);
        gl.attachShader(program, fragmentShader);
        gl.linkProgram(program);
        gl.useProgram(program);

        // Attributes and uniforms
        const positionLoc = gl.getAttribLocation(program, 'position');
        const colorLoc = gl.getAttribLocation(program, 'color');
        const sizeLoc = gl.getAttribLocation(program, 'size');
        const projectionLoc = gl.getUniformLocation(program, 'projection');

        // Buffers
        const positionBuffer = gl.createBuffer();
        const colorBuffer = gl.createBuffer();
        const sizeBuffer = gl.createBuffer();

        // Particle system initialization
        const MAX_PARTICLES = 100000;
        const positions = new Float32Array(MAX_PARTICLES * 2);
        const colors = new Float32Array(MAX_PARTICLES * 4);
        const sizes = new Float32Array(MAX_PARTICLES);
        let particleCount = 0;

        // Physics worker
        const physicsWorker = new Worker(URL.createObjectURL(new Blob([`
            let particles = [];
            let width, height;

            self.onmessage = function(e) {
                const {type, data} = e.data;
                
                switch(type) {
                    case 'init':
                        width = data.width;
                        height = data.height;
                        break;
                        
                    case 'update':
                        particles = data.particles;
                        updatePhysics();
                        self.postMessage({
                            type: 'update',
                            particles: particles
                        });
                        break;
                }
            };

            function updatePhysics() {
                // Physics calculations
                const GRAVITY = 0.5;
                const DAMPING = 0.99;

                for(let i = 0; i < particles.length; i++) {
                    let p = particles[i];
                    
                    // Apply forces
                    p.vy += GRAVITY * p.density;
                    p.vx *= DAMPING;
                    p.vy *= DAMPING;
                    
                    // Update position
                    p.x += p.vx;
                    p.y += p.vy;
                    
                    // Boundary collision
                    if(p.x < 0) {
                        p.x = 0;
                        p.vx *= -0.5;
                    }
                    if(p.x > width) {
                        p.x = width;
                        p.vx *= -0.5;
                    }
                    if(p.y < 0) {
                        p.y = 0;
                        p.vy *= -0.5;
                    }
                    if(p.y > height) {
                        p.y = height;
                        p.vy *= -0.5;
                    }
                }
            }
        `], {type: 'text/javascript'})));

        // UI Events
        let selectedElement = 'water';
        let selectedTool = 'draw';
        let isMouseDown = false;
        let mouseX = 0;
        let mouseY = 0;

        // Tab system
        document.querySelectorAll('.tab').forEach(tab => {
            tab.addEventListener('click', () => {
                document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
                document.querySelectorAll('.panel').forEach(p => p.classList.remove('active'));
                tab.classList.add('active');
                document.getElementById(tab.dataset.panel).classList.add('active');
            });
        });

        // Element selection
        document.querySelectorAll('.element-btn').forEach(btn => {
            btn.addEventListener('click', () => {
                document.querySelectorAll('.element-btn').forEach(b => b.classList.remove('active'));
                btn.classList.add('active');
                selectedElement = btn.dataset.element;
            });

            // Tooltips
            btn.addEventListener('mouseenter', (e) => {
                const tooltip = document.getElementById('tooltip');
                tooltip.textContent = btn.title;
                tooltip.style.display = 'block';
                tooltip.style.left = e.pageX + 10 + 'px';
                tooltip.style.top = e.pageY + 10 + 'px';
            });

            btn.addEventListener('mouseleave', () => {
                document.getElementById('tooltip').style.display = 'none';
            });
        });

        // Tool selection
        document.querySelectorAll('.tool-btn').forEach(btn => {
            btn.addEventListener('click', () => {
                document.querySelectorAll('.tool-btn').forEach(b => b.classList.remove('active'));
                btn.classList.add('active');
                selectedTool = btn.dataset.tool;
            });
        });

        // Mouse events
        canvas.addEventListener('mousedown', () => isMouseDown = true);
        canvas.addEventListener('mouseup', () => isMouseDown = false);
        canvas.addEventListener('mousemove', (e) => {
            mouseX = e.clientX * devicePixelRatio;
            mouseY = e.clientY * devicePixelRatio;
        });

        // Animation loop
        let lastTime = performance.now();
        let fps = 60;

        function animate(currentTime) {
            // FPS calculation
            const deltaTime = currentTime - lastTime;
            fps = Math.round(1000 / deltaTime);
            lastTime = currentTime;

            // Clear canvas
            gl.clear(gl.COLOR_BUFFER_BIT);

            // Update particles via worker
            physicsWorker.postMessage({
                type: 'update',
                particles: Array.from({length: particleCount}, (_, i) => ({
                    x: positions[i * 2],
                    y: positions[i * 2 + 1],
                    vx: 0,
                    vy: 0,
                    density: 1
                }))
            });

            // Update debug info
            document.getElementById('fps').textContent = fps;
            document.getElementById('particleCount').textContent = particleCount;
            document.getElementById('memory').textContent = 
                Math.round(performance.memory?.usedJSHeapSize / 1024 / 1024 || 0);

            requestAnimationFrame(animate);
        }

        // Initialize
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.enable(gl.BLEND);
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

        physicsWorker.postMessage({
            type: 'init',
            data: {
                width: canvas.width,
                height: canvas.height
            }
        });

        animate(performance.now());
    </script>
</body>
</html>

프롬프트 분석이 잘 되었으며, 몇 가지 추가적인 개선사항을 제안하겠습니다:

개선된 버전:

code

Create a performant physics sandbox simulation using HTML5 Canvas with these detailed specifications:

Core Engine Requirements:
- Implement WebGL rendering for better performance
- Use Web Workers for physics calculations
- Optimize with spatial partitioning
- Support variable time step simulation
- Include debug visualization options

Advanced Physics Features:
- Verlet integration for accurate physics
- Rigid body dynamics system
- Soft body deformation
- Constraint-based joints and connections
- Particle system with life cycles

Enhanced Element System:
- Hierarchical element classification
- Custom element property editor
- Element behavior scripting system
- Procedural element generation
- Advanced material shaders

Extended Interactions:
- Multi-touch support
- Gesture-based controls
- Force field creation
- Custom interaction rules editor
- Event-driven reaction system

Environmental Systems:
- Dynamic lighting effects
- Weather simulation
- Ecosystem interactions
- Time-based events
- Environmental hazards

Advanced UI Features:
- Customizable UI layout
- Command history system
- Experiment templates
- Tutorial system
- Performance monitoring

Data Management:
- Cloud save/load system
- Experiment sharing
- Analytics tracking
- Achievement system
- User profiles

Quality Assurance:
- Performance benchmarking
- Cross-browser compatibility
- Mobile device optimization
- Error handling system
- Automated testing suite

Documentation:
- API documentation
- User manual
- Tutorial content
- Code examples
- Best practices guide

주요 추가 개선사항:

    기술적 구현 세부사항:

    WebGL 렌더링 지원
    멀티스레딩 처리
    최적화 전략

    확장된 기능:

    고급 물리 시스템
    커스터마이징 기능
    다양한 상호작용

    품질 보증:

    성능 테스트
    호환성 검증
    오류 처리

    문서화:

    개발 문서
    사용자 가이드
    예제 코드

    데이터 관리:

    클라우드 저장
    공유 시스템
    분석 기능

이러한 개선으로:

    더 안정적인 구현 가능
    확장성 증가
    사용자 경험 향상
    유지보수 용이성 확보
    커뮤니티 형성 지원

Uses following code as basis and expand/edit it to create a fully functional and error free application:
Advanced Physics Sandbox * { margin: 0; padding: 0; box-sizing: border-box; user-select: none; } body { overflow: hidden; background: #000; font-family: system-ui; color: #fff; } #canvas { position: absolute; width: 100vw; height: 100vh; } .ui-container { position: fixed; width: 100%; height: 100%; pointer-events: none; } .ui-container > * { pointer-events: auto; } .sidebar { position: absolute; top: 20px; left: 20px; width: 280px; background: rgba(0,0,0,0.8); backdrop-filter: blur(10px); border-radius: 12px; padding: 15px; } .tab-container { display: flex; gap: 5px; margin-bottom: 15px; } .tab { flex: 1; padding: 8px; background: rgba(255,255,255,0.1); border: none; color: #fff; border-radius: 6px; cursor: pointer; transition: 0.3s; } .tab.active { background: rgba(255,255,255,0.2); } .panel { display: none; } .panel.active { display: block; } .element-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; } .element-btn { padding: 8px; background: rgba(255,255,255,0.1); border: none; color: #fff; border-radius: 6px; cursor: pointer; transition: 0.2s; font-size: 13px; } .element-btn:hover { background: rgba(255,255,255,0.2); } .element-btn.active { background: rgba(255,255,255,0.3); } .property-group { margin: 10px 0; } .property-slider { width: 100%; margin: 5px 0; } .tool-group { display: flex; gap: 5px; margin: 10px 0; } .tool-btn { flex: 1; padding: 8px; background: rgba(255,255,255,0.1); border: none; color: #fff; border-radius: 6px; cursor: pointer; } .debug-panel { position: absolute; bottom: 20px; left: 20px; background: rgba(0,0,0,0.8); padding: 10px; border-radius: 8px; font-family: monospace; font-size: 12px; } .tooltip { position: absolute; background: rgba(0,0,0,0.8); padding: 5px 10px; border-radius: 4px; font-size: 12px; pointer-events: none; display: none; } </style>

code

<div class="ui-container">
    <div class="sidebar">
        <div class="tab-container">
            <button class="tab active" data-panel="elements">Elements</button>
            <button class="tab" data-panel="properties">Properties</button>
            <button class="tab" data-panel="tools">Tools</button>
        </div>

        <div class="panel active" id="elements">
            <div class="element-grid">
                <button class="element-btn active" data-element="water" title="H₂O - Basic fluid">Water</button>
                <button class="element-btn" data-element="fire" title="Plasma - Heat source">Fire</button>
                <button class="element-btn" data-element="sand" title="SiO₂ - Granular">Sand</button>
                <button class="element-btn" data-element="metal" title="Fe - Conductor">Metal</button>
                <button class="element-btn" data-element="wood" title="Cellulose - Flammable">Wood</button>
                <button class="element-btn" data-element="acid" title="H₂SO₄ - Corrosive">Acid</button>
                <button class="element-btn" data-element="oil" title="Hydrocarbon - Flammable">Oil</button>
                <button class="element-btn" data-element="gas" title="O₂ - Diffusive">Gas</button>
                <button class="element-btn" data-element="stone" title="Granite - Solid">Stone</button>
            </div>
        </div>

        <div class="panel" id="properties">
            <div class="property-group">
                <label>Temperature</label>
                <input type="range" class="property-slider" id="tempSlider" min="0" max="100" value="20">
                <span id="tempValue">20°C</span>
            </div>
            <div class="property-group">
                <label>Density</label>
                <input type="range" class="property-slider" id="densitySlider" min="0" max="100" value="50">
                <span id="densityValue">1.0 g/cm³</span>
            </div>
            <div class="property-group">
                <label>Viscosity</label>
                <input type="range" class="property-slider" id="viscositySlider" min="0" max="100" value="50">
                <span id="viscosityValue">0.5</span>
            </div>
            <div class="property-group">
                <label>Particle Size</label>
                <input type="range" class="property-slider" id="sizeSlider" min="1" max="10" value="3">
                <span id="sizeValue">3px</span>
            </div>
        </div>

        <div class="panel" id="tools">
            <div class="tool-group">
                <button class="tool-btn active" data-tool="draw">Draw</button>
                <button class="tool-btn" data-tool="pour">Pour</button>
                <button class="tool-btn" data-tool="spray">Spray</button>
            </div>
            <div class="tool-group">
                <button class="tool-btn" data-tool="heat">Heat</button>
                <button class="tool-btn" data-tool="cool">Cool</button>
                <button class="tool-btn" data-tool="erase">Erase</button>
            </div>
            <div class="property-group">
                <label>Brush Size</label>
                <input type="range" class="property-slider" id="brushSlider" min="1" max="50" value="10">
                <span id="brushValue">10px</span>
            </div>
        </div>
    </div>

    <div class="debug-panel">
        <div>FPS: <span id="fps">60</span></div>
        <div>Particles: <span id="particleCount">0</span></div>
        <div>Memory: <span id="memory">0</span> MB</div>
    </div>
</div>

<div class="tooltip" id="tooltip"></div>

<script>
    // WebGL Setup
    const canvas = document.getElementById('canvas');
    const gl = canvas.getContext('webgl2');
    
    if (!gl) {
        alert('WebGL2 not supported');
        throw new Error('WebGL2 not supported');
    }

    // Canvas sizing
    function resizeCanvas() {
        canvas.width = window.innerWidth * devicePixelRatio;
        canvas.height = window.innerHeight * devicePixelRatio;
        gl.viewport(0, 0, canvas.width, canvas.height);
    }
    resizeCanvas();
    window.addEventListener('resize', resizeCanvas);

    // Shaders
    const vertexShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertexShader, `#version 300 es
        in vec2 position;
        in vec4 color;
        in float size;
        
        uniform mat4 projection;
        
        out vec4 vColor;
        
        void main() {
            gl_Position = projection * vec4(position, 0.0, 1.0);
            gl_PointSize = size;
            vColor = color;
        }
    `);
    gl.compileShader(vertexShader);

    const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragmentShader, `#version 300 es
        precision highp float;
        
        in vec4 vColor;
        out vec4 fragColor;
        
        void main() {
            vec2 coord = gl_PointCoord - vec2(0.5);
            float r = length(coord) * 2.0;
            float a = 1.0 - smoothstep(0.8, 1.0, r);
            fragColor = vec4(vColor.rgb, vColor.a * a);
        }
    `);
    gl.compileShader(fragmentShader);

    // Program setup
    const program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    gl.useProgram(program);

    // Attributes and uniforms
    const positionLoc = gl.getAttribLocation(program, 'position');
    const colorLoc = gl.getAttribLocation(program, 'color');
    const sizeLoc = gl.getAttribLocation(program, 'size');
    const projectionLoc = gl.getUniformLocation(program, 'projection');

    // Buffers
    const positionBuffer = gl.createBuffer();
    const colorBuffer = gl.createBuffer();
    const sizeBuffer = gl.createBuffer();

    // Particle system initialization
    const MAX_PARTICLES = 100000;
    const positions = new Float32Array(MAX_PARTICLES * 2);
    const colors = new Float32Array(MAX_PARTICLES * 4);
    const sizes = new Float32Array(MAX_PARTICLES);
    let particleCount = 0;

    // Physics worker
    const physicsWorker = new Worker(URL.createObjectURL(new Blob([`
        let particles = [];
        let width, height;

        self.onmessage = function(e) {
            const {type, data} = e.data;
            
            switch(type) {
                case 'init':
                    width = data.width;
                    height = data.height;
                    break;
                    
                case 'update':
                    particles = data.particles;
                    updatePhysics();
                    self.postMessage({
                        type: 'update',
                        particles: particles
                    });
                    break;
            }
        };

        function updatePhysics() {
            // Physics calculations
            const GRAVITY = 0.5;
            const DAMPING = 0.99;

            for(let i = 0; i < particles.length; i++) {
                let p = particles[i];
                
                // Apply forces
                p.vy += GRAVITY * p.density;
                p.vx *= DAMPING;
                p.vy *= DAMPING;
                
                // Update position
                p.x += p.vx;
                p.y += p.vy;
                
                // Boundary collision
                if(p.x < 0) {
                    p.x = 0;
                    p.vx *= -0.5;
                }
                if(p.x > width) {
                    p.x = width;
                    p.vx *= -0.5;
                }
                if(p.y < 0) {
                    p.y = 0;
                    p.vy *= -0.5;
                }
                if(p.y > height) {
                    p.y = height;
                    p.vy *= -0.5;
                }
            }
        }
    `], {type: 'text/javascript'})));

    // UI Events
    let selectedElement = 'water';
    let selectedTool = 'draw';
    let isMouseDown = false;
    let mouseX = 0;
    let mouseY = 0;

    // Tab system
    document.querySelectorAll('.tab').forEach(tab => {
        tab.addEventListener('click', () => {
            document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
            document.querySelectorAll('.panel').forEach(p => p.classList.remove('active'));
            tab.classList.add('active');
            document.getElementById(tab.dataset.panel).classList.add('active');
        });
    });

    // Element selection
    document.querySelectorAll('.element-btn').forEach(btn => {
        btn.addEventListener('click', () => {
            document.querySelectorAll('.element-btn').forEach(b => b.classList.remove('active'));
            btn.classList.add('active');
            selectedElement = btn.dataset.element;
        });

        // Tooltips
        btn.addEventListener('mouseenter', (e) => {
            const tooltip = document.getElementById('tooltip');
            tooltip.textContent = btn.title;
            tooltip.style.display = 'block';
            tooltip.style.left = e.pageX + 10 + 'px';
            tooltip.style.top = e.pageY + 10 + 'px';
        });

        btn.addEventListener('mouseleave', () => {
            document.getElementById('tooltip').style.display = 'none';
        });
    });

    // Tool selection
    document.querySelectorAll('.tool-btn').forEach(btn => {
        btn.addEventListener('click', () => {
            document.querySelectorAll('.tool-btn').forEach(b => b.classList.remove('active'));
            btn.classList.add('active');
            selectedTool = btn.dataset.tool;
        });
    });

    // Mouse events
    canvas.addEventListener('mousedown', () => isMouseDown = true);
    canvas.addEventListener('mouseup', () => isMouseDown = false);
    canvas.addEventListener('mousemove', (e) => {
        mouseX = e.clientX * devicePixelRatio;
        mouseY = e.clientY * devicePixelRatio;
    });

    // Animation loop
    let lastTime = performance.now();
    let fps = 60;

    function animate(currentTime) {
        // FPS calculation
        const deltaTime = currentTime - lastTime;
        fps = Math.round(1000 / deltaTime);
        lastTime = currentTime;

        // Clear canvas
        gl.clear(gl.COLOR_BUFFER_BIT);

        // Update particles via worker
        physicsWorker.postMessage({
            type: 'update',
            particles: Array.from({length: particleCount}, (_, i) => ({
                x: positions[i * 2],
                y: positions[i * 2 + 1],
                vx: 0,
                vy: 0,
                density: 1
            }))
        });

        // Update debug info
        document.getElementById('fps').textContent = fps;
        document.getElementById('particleCount').textContent = particleCount;
        document.getElementById('memory').textContent = 
            Math.round(performance.memory?.usedJSHeapSize / 1024 / 1024 || 0);

        requestAnimationFrame(animate);
    }

    // Initialize
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

    physicsWorker.postMessage({
        type: 'init',
        data: {
            width: canvas.width,
            height: canvas.height
        }
    });

    animate(performance.now());
</script>

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Physics Sandbox Pro</title>
    <style>
        /* Base styles */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            user-select: none;
        }

        body {
            overflow: hidden;
            background: #000;
            font-family: system-ui;
            color: #fff;
        }

        canvas {
            position: absolute;
            width: 100vw; 
            height: 100vh;
            touch-action: none;
        }

        .ui-container {
            position: fixed;
            width: 100%;
            height: 100%;
            pointer-events: none;
        }

        .ui-container > * {
            pointer-events: auto;
        }

        /* UI Components */
        .sidebar {
            position: absolute;
            top: 20px;
            left: 20px;
            width: 280px;
            background: rgba(0,0,0,0.8);
            backdrop-filter: blur(10px);
            border-radius: 12px;
            padding: 15px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.3);
        }

        .panel {
            display: none;
            transition: 0.3s;
        }

        .panel.active {
            display: block;
        }

        /* Tabs */
        .tab-container {
            display: flex;
            gap: 5px;
            margin-bottom: 15px;
        }

        .tab {
            flex: 1;
            padding: 8px;
            background: rgba(255,255,255,0.1);
            border: none;
            color: #fff;
            border-radius: 6px;
            cursor: pointer;
            transition: 0.3s;
            font-weight: 500;
        }

        .tab:hover {
            background: rgba(255,255,255,0.2);
        }

        .tab.active {
            background: rgba(255,255,255,0.25);
            box-shadow: 0 0 0 2px rgba(255,255,255,0.1);
        }

        /* Elements Grid */
        .element-grid {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 8px;
        }

        .element-btn {
            padding: 8px;
            background: rgba(255,255,255,0.1);
            border: none;
            color: #fff;
            border-radius: 6px;
            cursor: pointer;
            transition: 0.2s;
            font-size: 13px;
        }

        .element-btn:hover {
            background: rgba(255,255,255,0.2);
            transform: translateY(-1px);
        }

        .element-btn.active {
            background: rgba(255,255,255,0.3);
            box-shadow: 0 0 0 2px rgba(255,255,255,0.2);
        }

        /* Property Controls */
        .property-group {
            margin: 15px 0;
        }

        .property-group label {
            display: block;
            margin-bottom: 5px;
            font-weight: 500;
            color: #aaa;
        }

        .property-slider {
            -webkit-appearance: none;
            width: 100%;
            height: 6px;
            border-radius: 3px;
            background: rgba(255,255,255,0.1);
            outline: none;
            margin: 10px 0;
        }

        .property-slider::-webkit-slider-thumb {
            -webkit-appearance: none;
            width: 16px;
            height: 16px;
            border-radius: 50%;
            background: #fff;
            cursor: pointer;
            transition: 0.2s;
        }

        .property-slider::-webkit-slider-thumb:hover {
            transform: scale(1.2);
        }

        /* Tools */
        .tool-group {
            display: flex;
            gap: 5px;
            margin: 10px 0;
        }

        .tool-btn {
            flex: 1;
            padding: 8px;
            background: rgba(255,255,255,0.1);
            border: none;
            color: #fff;
            border-radius: 6px;
            cursor: pointer;
            transition: 0.2s;
        }

        .tool-btn:hover {
            background: rgba(255,255,255,0.2);
        }

        .tool-btn.active {
            background: rgba(255,255,255,0.3);
            box-shadow: 0 0 0 2px rgba(255,255,255,0.2);
        }

        /* Debug Panel */
        .debug-panel {
            position: absolute;
            bottom: 20px;
            left: 20px;
            background: rgba(0,0,0,0.8);
            padding: 12px;
            border-radius: 8px;
            font-family: monospace;
            font-size: 12px;
            backdrop-filter: blur(10px);
        }

        .debug-panel div {
            margin: 3px 0;
        }

        /* Tooltip */
        .tooltip {
            position: absolute;
            background: rgba(0,0,0,0.9);
            color: #fff;
            padding: 8px 12px;
            border-radius: 6px;
            font-size: 12px;
            pointer-events: none;
            display: none;
            z-index: 1000;
            box-shadow: 0 2px 8px rgba(0,0,0,0.2);
            backdrop-filter: blur(4px);
        }

        /* Loading Screen */
        .loading-screen {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: #000;
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 1000;
            transition: 0.5s;
        }

        .loading-screen.hidden {
            opacity: 0;
            pointer-events: none;
        }

        .loading-spinner {
            width: 50px;
            height: 50px;
            border: 5px solid rgba(255,255,255,0.1);
            border-top-color: #fff;
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }

        @keyframes spin {
            to { transform: rotate(360deg); }
        }

        /* Error Message */
        .error-message {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(255,0,0,0.9);
            color: white;
            padding: 20px;
            border-radius: 10px;
            text-align: center;
            display: none;
        }

        /* Responsive Design */
        @media (max-width: 768px) {
            .sidebar {
                width: 100%;
                top: auto;
                bottom: 0;
                left: 0;
                border-radius: 12px 12px 0 0;
            }

            .debug-panel {
                display: none;
            }
        }
    </style>
</head>
<body>
    <div class="loading-screen">
        <div class="loading-spinner"></div>
    </div>

    <div class="error-message" id="errorMessage">
        WebGL2 is not supported in your browser. Please try a different browser.
    </div>

    <canvas id="canvas"></canvas>

    <!-- UI Components -->
    <!-- [Previous UI HTML remains the same] -->

    <script>
        // Error Handling
        window.onerror = function(msg, url, lineNo, columnNo, error) {
            console.error('Error: ', msg, 'URL: ', url, 'Line: ', lineNo, 'Column: ', columnNo, 'Error object: ', error);
            showError('An error occurred. Please refresh the page.');
            return false;
        };

        function showError(message) {
            const errorElement = document.getElementById('errorMessage');
            errorElement.textContent = message;
            errorElement.style.display = 'block';
        }

        // WebGL Context Creation with Error Handling
        let gl;
        try {
            const canvas = document.getElementById('canvas');
            gl = canvas.getContext('webgl2', {
                alpha: false,
                antialias: false,
                depth: false,
                stencil: false,
                preserveDrawingBuffer: false
            });
            
            if (!gl) throw new Error('WebGL2 not supported');
        } catch (error) {
            showError('WebGL2 initialization failed: ' + error.message);
            throw error;
        }

        // Performance Monitoring
        const performanceMonitor = {
            fpsHistory: [],
            particleHistory: [],
            memoryHistory: [],
            
            update(fps, particleCount, memoryUsage) {
                this.fpsHistory.push(fps);
                this.particleHistory.push(particleCount);
                this.memoryHistory.push(memoryUsage);
                
                if (this.fpsHistory.length > 60) {
                    this.fpsHistory.shift();
                    this.particleHistory.shift();
                    this.memoryHistory.shift();
                }

                // Performance warnings
                if (fps < 30) console.warn('Low FPS detected');
                if (memoryUsage > 500) console.warn('High memory usage');
            }
        };

        // Optimized Particle System
        class ParticleSystem {
            constructor(maxParticles) {
                this.maxParticles = maxParticles;
                this.particles = new Float32Array(maxParticles * 4); // x, y, vx, vy
                this.attributes = new Float32Array(maxParticles * 4); // temp, density, size, type
                this.count = 0;
            }

            addParticle(x, y, type) {
                if (this.count >= this.maxParticles) return false;
                
                const i = this.count * 4;
                this.particles[i] = x;
                this.particles[i + 1] = y;
                this.particles[i + 2] = 0; // vx
                this.particles[i + 3] = 0; // vy
                
                // Set attributes based on type
                this.setParticleAttributes(this.count, type);
                
                this.count++;
                return true;
            }

            setParticleAttributes(index, type) {
                const i = index * 4;
                const elementProperties = ELEMENT_PROPERTIES[type];
                
                this.attributes[i] = elementProperties.temperature;
                this.attributes[i + 1] = elementProperties.density;
                this.attributes[i + 2] = elementProperties.size;
                this.attributes[i + 3] = elementProperties.typeId;
            }
        }

        // Element Properties Configuration
        const ELEMENT_PROPERTIES = {
            water: {
                typeId: 1,
                temperature: 20,
                density: 1.0,
                size: 3,
                color: [0.29, 0.62, 0.96, 1.0],
                viscosity: 0.95,
                heatCapacity: 1
            },
            fire: {
                typeId: 2,
                temperature: 800,
                density: 0.1,
                size: 4,
                color: [1.0, 0.27, 0.13, 0.8],
                viscosity: 1.0,
                heatCapacity: 0.1
            },
            // [Add more element properties...]
        };

        // [Rest of the previous JavaScript code with optimization improvements...]
    </script>
</body>
</html>

This improved version includes:

    Robust error handling
    Performance monitoring system
    Memory optimization
    Improved particle system architecture
    Proper WebGL context creation
    Loading screen
    Responsive design improvements
    Enhanced visual styling

To complete the implementation, you would need to:

    Add the remaining element properties
    Implement the WebGL render pipeline
    Add the physics worker code
    Complete the interaction systems
    Add the save/load functionality