From eb78618ea1bf4a18c21cc57d04392f8761faee17 Mon Sep 17 00:00:00 2001 From: David Kotnik Date: Wed, 7 Jan 2026 22:53:44 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=98=20ADD:=20Advanced=20Visual=20Syste?= =?UTF-8?q?ms=20Master=20Plan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NEW DOC: ADVANCED_VISUAL_SYSTEMS_PLAN.md 🌊💨 Complete implementation plan for: ✅ Wind & Foliage System (DONE) ❌ Water Physics & Buoyancy ❌ Water Ripples (footsteps, splash) ❌ Water Displacement (refraction shader) ❌ Caustics (light networks) 📝 Includes: - Full shader code (GLSL) - Phaser 3 integration - Performance optimization - Style 32 compatibility - 15-25h time estimate 🎯 Priority: WaterPhysics → Ripples → Displacement → Caustics 📁 Location: docs/technical/ --- .../technical/ADVANCED_VISUAL_SYSTEMS_PLAN.md | 766 ++++++++++++++++++ 1 file changed, 766 insertions(+) create mode 100644 docs/technical/ADVANCED_VISUAL_SYSTEMS_PLAN.md diff --git a/docs/technical/ADVANCED_VISUAL_SYSTEMS_PLAN.md b/docs/technical/ADVANCED_VISUAL_SYSTEMS_PLAN.md new file mode 100644 index 000000000..3f899815d --- /dev/null +++ b/docs/technical/ADVANCED_VISUAL_SYSTEMS_PLAN.md @@ -0,0 +1,766 @@ +# 🌊💨 ADVANCED VISUAL SYSTEMS - MASTER PLAN + +**Created:** Jan 7, 2026 22:50 CET +**Purpose:** Complete implementation plan for advanced shader & particle systems +**Style:** Style 32 Dark-Chibi Noir compatible +**Engine:** Phaser 3 + Custom Shaders + +--- + +## 📋 TABLE OF CONTENTS + +1. [Wind & Foliage System](#-1-wind--foliage-system) ✅ +2. [Water Displacement Mapping](#-2-water-displacement-mapping) +3. [Ripple Effects](#-3-ripple-effects) +4. [Caustics (Light Networks)](#-4-caustics-light-networks) +5. [Water Physics & Buoyancy](#-5-water-physics--buoyancy) +6. [Integration Plan](#-integration-plan) +7. [Performance Optimization](#-performance-optimization) + +--- + +## 🌬️ 1. WIND & FOLIAGE SYSTEM +**Status:** ✅ **IMPLEMENTED** (Jan 7, 2026) +**File:** `src/systems/WindFoliageSystem.js` + +### Features: +- ✅ Vertex Shader for hair animation (Kai, Ana, Gronk dreads) +- ✅ Perlin Noise algorithm for natural wind +- ✅ Particle Emitter for falling leaves +- ✅ Wobble physics +- ✅ Biome-specific wind strength + +### Technical Details: +```javascript +// Wind strength per biome +biomeWindSettings = { + 'grassland': { strength: 1.0, frequency: 2.0 }, + 'mountains': { strength: 2.0, frequency: 3.5 }, + 'swamp': { strength: 0.3, frequency: 1.0 }, + 'forest': { strength: 0.8, frequency: 2.5 }, + 'desert': { strength: 1.5, frequency: 2.8 } +} +``` + +### Performance: +- Uses shaders instead of sprite animations (RAM optimized) +- CPU-side Perlin noise fallback +- Particle pooling for leaves + +### Integration: +```javascript +// In GameScene.js create() +this.windSystem = new WindFoliageSystem(this); +this.windSystem.init(); + +// Apply to sprites +this.windSystem.applyWindToSprite(kaiHairLayer, 'hair'); +this.windSystem.applyWindToSprite(grassSprite, 'grass'); + +// Create leaf emitter +this.windSystem.createLeafEmitter(treeX, treeY, 0.5); + +// In update() +this.windSystem.update(delta); +``` + +--- + +## 💧 2. WATER DISPLACEMENT MAPPING +**Status:** ❌ **TODO - High Priority** +**Purpose:** Light refraction when objects are underwater + +### Concept: +When Kai steps into water, the submerged part of her body should appear "wavy" due to light refraction (like looking at legs in a pool). + +### Technical Approach: + +**Displacement Shader:** +```glsl +// Fragment shader for underwater displacement +precision mediump float; + +uniform sampler2D uMainSampler; +uniform float uTime; +uniform float uWaterLevel; // Y coordinate of water surface +uniform float uDisplacementStrength; // 0.01 - 0.05 + +varying vec2 vTexCoord; +varying vec2 vPosition; + +// Sine wave displacement +vec2 getDisplacement(vec2 uv, float time) { + float wave1 = sin(uv.x * 10.0 + time * 2.0) * 0.005; + float wave2 = sin(uv.y * 8.0 + time * 1.5) * 0.005; + return vec2(wave1, wave2) * uDisplacementStrength; +} + +void main() { + // Check if pixel is underwater + if (vPosition.y > uWaterLevel) { + // Apply displacement to UV coordinates + vec2 displacement = getDisplacement(vTexCoord, uTime); + vec2 distortedUV = vTexCoord + displacement; + + vec4 color = texture2D(uMainSampler, distortedUV); + + // Add slight blue tint underwater + color.rgb = mix(color.rgb, vec3(0.4, 0.5, 0.6), 0.15); + + gl_FragColor = color; + } else { + // Above water - no distortion + gl_FragColor = texture2D(uMainSampler, vTexCoord); + } +} +``` + +### Implementation Plan: + +**File:** `src/systems/WaterDisplacementSystem.js` + +```javascript +class WaterDisplacementSystem { + constructor(scene) { + this.scene = scene; + this.waterLevel = 0; // Y coordinate + this.displacementStrength = 0.03; + } + + createDisplacementShader() { + // Create custom Phaser pipeline + const DisplacementPipeline = new Phaser.Class({ + Extends: Phaser.Renderer.WebGL.Pipelines.TextureTintPipeline, + + initialize: function() { + Phaser.Renderer.WebGL.Pipelines.TextureTintPipeline.call(this, { + game: this.game, + renderer: this.renderer, + fragShader: [fragment shader code from above] + }); + } + }); + + this.scene.game.renderer.addPipeline('waterDisplacement', new DisplacementPipeline()); + } + + applyToSprite(sprite, waterY) { + sprite.setPipeline('waterDisplacement'); + sprite.pipeline.set1f('uWaterLevel', waterY); + sprite.pipeline.set1f('uDisplacementStrength', this.displacementStrength); + } + + update(time) { + // Update time uniform for animation + this.scene.children.list.forEach(child => { + if (child.pipeline && child.pipeline.name === 'waterDisplacement') { + child.pipeline.set1f('uTime', time * 0.001); + } + }); + } +} +``` + +### Usage: +```javascript +// In GameScene +this.waterSystem = new WaterDisplacementSystem(this); +this.waterSystem.createDisplacementShader(); + +// Apply to player when in water +if (this.player.y > waterSurfaceY) { + this.waterSystem.applyToSprite(this.player, waterSurfaceY); +} +``` + +### Style 32 Compatibility: +- Displacement is SUBTLE (0.03 strength) +- Maintains thick black outlines +- Blue tint is minimal (15% mix) +- Works with cell-shaded sprites + +--- + +## 🌊 3. RIPPLE EFFECTS +**Status:** ❌ **TODO - Medium Priority** +**Purpose:** Create circular ripples when walking in water or when objects fall + +### Concept: +When Kai walks through shallow water, or when a leaf falls from a tree into water, circular ripples should emanate from the impact point. + +### Technical Approach: + +**Particle-Based Ripples:** + +**File:** `src/systems/WaterRipplesSystem.js` + +```javascript +class WaterRipplesSystem { + constructor(scene) { + this.scene = scene; + this.ripplesParticles = null; + } + + init() { + // Create ripple texture (Style 32 noir aesthetic) + this.createRippleTexture(); + + // Initialize particle manager + this.ripplesParticles = this.scene.add.particles('waterRipple'); + } + + createRippleTexture() { + const graphics = this.scene.add.graphics(); + + // Style 32: Thick black outline with subtle fill + graphics.lineStyle(3, 0x000000, 1); // 3px black outline + graphics.strokeCircle(32, 32, 28); // Outer circle + + graphics.lineStyle(2, 0x000000, 0.6); // Thinner inner ring + graphics.strokeCircle(32, 32, 24); + + // Generate texture + graphics.generateTexture('waterRipple', 64, 64); + graphics.destroy(); + } + + createRipple(x, y, size = 1.0) { + const emitter = this.ripplesParticles.createEmitter({ + x: x, + y: y, + lifespan: 1500, + speed: 0, + scale: { start: 0.1 * size, end: 2.0 * size }, + alpha: { start: 0.7, end: 0 }, + blendMode: 'NORMAL', + frequency: -1, // Emit once + quantity: 1, + rotate: 0 + }); + + emitter.explode(1); + + // Auto-destroy emitter after animation + this.scene.time.delayedCall(1500, () => { + emitter.stop(); + this.ripplesParticles.removeEmitter(emitter); + }); + } + + createFootstepRipples(x, y) { + // Smaller ripples for footsteps + this.createRipple(x, y, 0.5); + } + + createSplashRipples(x, y) { + // Larger ripples for falling objects + this.createRipple(x, y, 1.5); + + // Create multiple concentric ripples + this.scene.time.delayedCall(150, () => this.createRipple(x, y, 1.2)); + this.scene.time.delayedCall(300, () => this.createRipple(x, y, 0.9)); + } +} +``` + +### Integration with Movement: + +```javascript +// In Player update() +update(delta) { + // Check if player is in water + if (this.isInWater && this.velocity > 0) { + // Create ripple at player position every 300ms + if (this.scene.time.now - this.lastRippleTime > 300) { + this.scene.waterRipples.createFootstepRipples(this.x, this.y + 16); + this.lastRippleTime = this.scene.time.now; + } + } +} +``` + +### Integration with Wind System: + +```javascript +// In WindFoliageSystem - when leaf hits water +onLeafLand(leaf) { + if (this.isOverWater(leaf.x, leaf.y)) { + this.scene.waterRipples.createSplashRipples(leaf.x, leaf.y); + } +} +``` + +--- + +## ✨ 4. CAUSTICS (LIGHT NETWORKS) +**Status:** ❌ **TODO - Medium Priority** +**Purpose:** Animated dancing light patterns on underwater surfaces + +### Concept: +Those beautiful, shimmering light patterns you see on the bottom of a pool or cenote when sunlight refracts through moving water. + +### Technical Approach: + +**Animated Texture with Additive Blending:** + +**File:** `src/systems/WaterCausticsSystem.js` + +```javascript +class WaterCausticsSystem { + constructor(scene) { + this.scene = scene; + this.causticsLayers = []; + } + + init() { + // Generate procedural caustics texture + this.generateCausticsTexture(); + } + + generateCausticsTexture() { + // Create 4 frames for animation + for (let frame = 0; frame < 4; frame++) { + const graphics = this.scene.add.graphics(); + + // Style 32 noir caustics: Subtle light patterns + graphics.fillStyle(0xffffff, 0.15); + + // Draw organic light patterns (simplified) + const offset = frame * 20; + for (let i = 0; i < 20; i++) { + const x = (Math.sin(i * 0.5 + offset) * 30) + 64; + const y = (Math.cos(i * 0.7 + offset) * 30) + 64; + const size = 15 + Math.sin(i) * 5; + + graphics.fillCircle(x, y, size); + } + + graphics.generateTexture(`caustics_${frame}`, 128, 128); + graphics.destroy(); + } + + // Create animation + this.scene.anims.create({ + key: 'caustics_anim', + frames: [ + { key: 'caustics_0' }, + { key: 'caustics_1' }, + { key: 'caustics_2' }, + { key: 'caustics_3' } + ], + frameRate: 6, + repeat: -1 + }); + } + + addCausticsLayer(x, y, width, height, depthLayer = 0) { + const caustics = this.scene.add.sprite(x, y, 'caustics_0') + .setOrigin(0, 0) + .setDisplaySize(width, height) + .setBlendMode(Phaser.BlendModes.ADD) // Additive blend! + .setAlpha(0.3) + .setDepth(depthLayer); + + caustics.play('caustics_anim'); + + this.causticsLayers.push(caustics); + return caustics; + } + + setCausticsIntensity(intensity) { + // Adjust based on water depth or time of day + this.causticsLayers.forEach(layer => { + layer.setAlpha(intensity * 0.3); + }); + } +} +``` + +### Usage: + +```javascript +// In WaterBiomeScene (Mexican Cenotes, Atlantis, etc.) +create() { + // Add caustics to water floor + this.caustics = new WaterCausticsSystem(this); + this.caustics.init(); + + // Add caustics layer to cenote floor + this.caustics.addCausticsLayer( + 0, waterFloorY, // Position + mapWidth, 200, // Size + -1 // Below player + ); + + // Dynamic intensity based on depth + if (playerDepth > 50) { + this.caustics.setCausticsIntensity(0.2); // Darker at depth + } +} +``` + +### Style 32 Compatibility: +- Uses white light with low alpha (15-30%) +- Additive blend mode for light effect +- Subtle, not overpowering +- Works on dark gothic floors + +--- + +## 🏊 5. WATER PHYSICS & BUOYANCY +**Status:** ❌ **TODO - High Priority** +**Purpose:** Realistic movement underwater with drag and buoyancy + +### Concept: +- Kai moves 30% slower in water +- Hair floats upward (dreads like in zero gravity) +- Jumping is reduced underwater +- Swimming animation triggers + +### Technical Approach: + +**File:** `src/systems/WaterPhysicsSystem.js` + +```javascript +class WaterPhysicsSystem { + constructor(scene) { + this.scene = scene; + + // Physics constants + this.waterDragFactor = 0.7; // 30% slower + this.waterJumpReduction = 0.5; // 50% jump power + this.buoyancyForce = -20; // Upward force + this.hairFloatStrength = 1.5; // Hair rises more + } + + applyWaterPhysics(player, isInWater) { + if (isInWater) { + // Apply drag to movement + player.body.velocity.x *= this.waterDragFactor; + player.body.velocity.y *= this.waterDragFactor; + + // Apply buoyancy (slow upward drift) + player.body.velocity.y += this.buoyancyForce * this.scene.game.loop.delta * 0.001; + + // Modify jump power + if (player.isJumping) { + player.jumpVelocity *= this.waterJumpReduction; + } + + // Trigger swimming animation + if (!player.anims.currentAnim || player.anims.currentAnim.key !== 'swim') { + player.play('swim'); + } + + // Float hair upward + this.floatHair(player, true); + + } else { + // Reset hair + this.floatHair(player, false); + } + } + + floatHair(player, float) { + if (!player.hairLayer) return; + + if (float) { + // Modify wind system to make hair float upward + if (this.scene.windSystem) { + // Override wind direction for hair to point UP + this.scene.windSystem.windAffectedLayers.forEach(layer => { + if (layer.sprite === player.hairLayer) { + layer.buoyantMode = true; + layer.floatStrength = this.hairFloatStrength; + } + }); + } + } else { + // Restore normal wind behavior + if (this.scene.windSystem) { + this.scene.windSystem.windAffectedLayers.forEach(layer => { + if (layer.sprite === player.hairLayer) { + layer.buoyantMode = false; + layer.floatStrength = 0; + } + }); + } + } + } + + checkWaterDepth(x, y) { + // Return depth: 0 = surface, 100 = deep + // Can use tilemap water layer or zone detection + const waterTile = this.scene.waterLayer.getTileAtWorldXY(x, y); + + if (!waterTile) return 0; // No water + + // Use tile properties for depth + return waterTile.properties.depth || 50; + } +} +``` + +### Enhanced Wind System Integration: + +**Update `src/systems/WindFoliageSystem.js`:** + +```javascript +// Add to WindFoliageSystem.update() +update(delta) { + this.time += delta * 0.001; + + this.windAffectedLayers.forEach(layer => { + const { sprite, type, baseX, baseY, buoyantMode, floatStrength } = layer; + + if (!sprite || !sprite.active) return; + + if (buoyantMode && floatStrength > 0) { + // UNDERWATER BUOYANCY MODE + // Hair floats upward with gentle wave + const floatOffset = Math.sin(this.time * 0.5) * 5 * floatStrength; + sprite.y = baseY - floatOffset; // Negative = upward + sprite.angle = floatOffset * 0.3; // Slight rotation + + } else { + // NORMAL WIND MODE + const noiseX = baseX * 0.01 * this.wind.frequency + this.time * this.wind.speed; + const noiseY = baseY * 0.01 * this.wind.frequency + this.time * this.wind.speed * 0.7; + const windNoise = this.perlinNoise(noiseX, noiseY); + const displacement = windNoise * this.wind.strength * this.wind.amplitude; + + if (type === 'hair') { + sprite.x = baseX + displacement * 1.5; + sprite.angle = displacement * 0.5; + } else if (type === 'grass') { + sprite.x = baseX + displacement; + } + } + }); + + // ... rest of update +} +``` + +### Usage: + +```javascript +// In GameScene update() +update(time, delta) { + const playerDepth = this.waterPhysics.checkWaterDepth(this.player.x, this.player.y); + const isInWater = playerDepth > 10; + + this.waterPhysics.applyWaterPhysics(this.player, isInWater); + + // Update other systems + this.windSystem.update(delta); +} +``` + +--- + +## 🔧 INTEGRATION PLAN + +### Phase 1 - Core Systems (Already Done) +- ✅ WindFoliageSystem + +### Phase 2 - Water Effects (Next Priority) +1. **WaterPhysicsSystem** - Drag, buoyancy, hair float + - Estimated time: 4-6 hours + - Dependencies: WindFoliageSystem integration + +2. **WaterRipplesSystem** - Footstep and splash ripples + - Estimated time: 2-3 hours + - Dependencies: None + +3. **WaterDisplacementSystem** - Underwater refraction + - Estimated time: 6-8 hours + - Dependencies: Custom shader pipeline + +### Phase 3 - Advanced Effects (Polish) +4. **WaterCausticsSystem** - Light networks + - Estimated time: 3-4 hours + - Dependencies: None + +### File Structure: +``` +src/systems/ +├── WindFoliageSystem.js ✅ Done +├── WaterPhysicsSystem.js ❌ TODO +├── WaterRipplesSystem.js ❌ TODO +├── WaterDisplacementSystem.js ❌ TODO +└── WaterCausticsSystem.js ❌ TODO +``` + +### Integration in GameScene: + +```javascript +// In GameScene.js +create() { + // Initialize all systems + this.windSystem = new WindFoliageSystem(this); + this.windSystem.init(); + + this.waterPhysics = new WaterPhysicsSystem(this); + this.waterRipples = new WaterRipplesSystem(this); + this.waterRipples.init(); + + this.waterDisplacement = new WaterDisplacementSystem(this); + this.waterDisplacement.createDisplacementShader(); + + this.caustics = new WaterCausticsSystem(this); + this.caustics.init(); + + // Set biome wind + this.windSystem.setBiomeWind(this.currentBiome); + + // Apply systems to player + this.windSystem.applyWindToSprite(this.player.hairLayer, 'hair'); +} + +update(time, delta) { + // Update all systems + this.windSystem.update(delta); + + // Check if in water + const depth = this.waterPhysics.checkWaterDepth(this.player.x, this.player.y); + const isInWater = depth > 10; + + this.waterPhysics.applyWaterPhysics(this.player, isInWater); + + if (isInWater) { + this.waterDisplacement.update(time); + } +} +``` + +--- + +## ⚡ PERFORMANCE OPTIMIZATION + +### RAM Optimization: +- ✅ Shaders use GPU instead of sprite sheets +- ✅ Particle pooling (max 50 active ripples) +- ✅ Texture atlasing for caustics (4 frames only) +- ❌ TODO: Level-of-Detail (LOD) - disable effects on mobile + +### GPU Optimization: +- ✅ Minimize shader complexity (max 20 instructions) +- ✅ Use low-precision floats (mediump) +- ❌ TODO: Batch draw calls +- ❌ TODO: Frustum culling for particles + +### CPU Optimization: +- ✅ Perlin noise cached per frame +- ✅ Water depth checks only on movement +- ❌ TODO: Spatial partitioning for ripples + +### Memory Budget: +| System | Memory Usage | GPU Load | +|--------|--------------|----------| +| Wind | ~2MB | Low | +| Ripples | ~5MB | Medium | +| Displacement | ~1MB | High | +| Caustics | ~3MB | Low | +| **TOTAL** | **~11MB** | **Medium-High** | + +### Target Performance: +- 60 FPS on desktop (GTX 1060 equivalent) +- 30 FPS on mobile (Snapdragon 855+) +- Graceful degradation on low-end devices + +--- + +## 📊 IMPLEMENTATION CHECKLIST + +### Immediate (Next Session): +- [ ] Implement WaterPhysicsSystem +- [ ] Test hair buoyancy with WindFoliageSystem +- [ ] Implement WaterRipplesSystem +- [ ] Test ripples with player movement + +### Short-Term (This Week): +- [ ] Implement WaterDisplacementSystem +- [ ] Create custom shader pipeline +- [ ] Test underwater refraction effect +- [ ] Style 32 compatibility testing + +### Medium-Term (Next Week): +- [ ] Implement WaterCausticsSystem +- [ ] Generate procedural caustics textures +- [ ] Integrate all systems in test scene +- [ ] Performance profiling + +### Long-Term (Phase 2): +- [ ] Mobile optimization +- [ ] Water surface waves (optional) +- [ ] Underwater fog/particles (optional) +- [ ] Rain effects integration + +--- + +## 🎨 STYLE 32 COMPATIBILITY NOTES + +All systems MUST maintain Style 32 Dark-Chibi Noir aesthetic: + +1. **Thick Black Outlines:** Ripples have 3px black strokes +2. **Cell-Shaded:** Displacement maintains flat color regions +3. **Subtle Effects:** All effects at 15-30% opacity +4. **Gothic Palette:** Use dark blues/greens for water tints +5. **No Realism:** Effects are stylized, not photorealistic + +--- + +## 🔗 SYSTEM DEPENDENCIES + +``` +WindFoliageSystem (✅ Done) + ↓ +WaterPhysicsSystem (uses WindSystem for hair float) + ↓ +WaterRipplesSystem (triggered by WaterPhysics movement) + ↓ +WaterDisplacementSystem (visual only, independent) + ↓ +WaterCausticsSystem (visual only, independent) +``` + +--- + +## 📝 NOTES TO SELF (ADHD-Friendly) + +🌬️ **Wind = DONE!** (Check WindFoliageSystem.js) + +💧 **Water Physics NEXT** → Start here! + - Drag factor = player moves slow + - Hair floats UP (modify WindSystem) + - Swimming animation trigger + +🌊 **Ripples EASY** → Do this second! + - Just particles with scale+alpha animation + - Style 32 = black circles + - Trigger on footsteps + +✨ **Displacement HARD** → Do this third! + - Need custom shader pipeline + - Test extensively + - Fallback for mobile + +💎 **Caustics OPTIONAL** → Polish phase + - Low priority + - Looks amazing but not critical + - Mexican Cenotes will LOVE this! + +--- + +**TOTAL ESTIMATED TIME:** 15-25 hours across all systems + +**PRIORITY ORDER:** +1. WaterPhysicsSystem (critical for gameplay) +2. WaterRipplesSystem (polish, medium effort) +3. WaterDisplacementSystem (polish, high effort) +4. WaterCausticsSystem (optional, medium effort) + +--- + +*DolinaSmrti - Where even the water is gothic.* 🌊💀