📘 ADD: Advanced Visual Systems Master Plan
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/
This commit is contained in:
766
docs/technical/ADVANCED_VISUAL_SYSTEMS_PLAN.md
Normal file
766
docs/technical/ADVANCED_VISUAL_SYSTEMS_PLAN.md
Normal file
@@ -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.* 🌊💀
|
||||
Reference in New Issue
Block a user