VFX SYSTEM + QUEST MANIFEST - Amnesia blur, Harvest sparkles, Water life, Cinematic transitions - 7 Main quests with ADHD dialogue - ROADMAP updated with VFX and Quest tracking

This commit is contained in:
2026-01-05 11:18:24 +01:00
parent 879b029f4c
commit 4fa69e35ea
3 changed files with 1027 additions and 0 deletions

539
docs/VFX_EFFECTS_SYSTEM.md Normal file
View File

@@ -0,0 +1,539 @@
# 🎬 VFX & INTERACTIVE EFFECTS SYSTEM
**Project:** Mrtva Dolina
**Purpose:** Visual feedback, emotional storytelling, player satisfaction
**Style:** ADHD-friendly, instant feedback, satisfying
---
## ✨ **1. AMNESIA EFFECT (Kai's Memory System)**
### **Concept:**
When Kai finds family heirlooms or Ana's belongings, trigger a **blur-to-clear memory flashback** with audio cues.
### **Visual Effect:**
**Stage 1: Discovery**
```javascript
// Player finds item (photo, Ana's necklace, family object)
onItemFound(familyItem) {
// Show blurred image overlay
showImage({
src: familyItem.memoryImage,
blur: 20, // Heavy gaussian blur
opacity: 0.8,
fadeIn: 500ms
});
// Play mysterious sound
playSound('memory_echo.mp3', volume: 0.5);
// Show prompt: "E - Remember" (simple text)
showPrompt("Pritisni E za spomin");
}
```
**Stage 2: Memory Restoration**
```javascript
// Player presses E to "remember"
onRememberPressed() {
// Blur clears gradually (2 seconds)
animateBlur({
from: 20,
to: 0,
duration: 2000ms,
easing: 'easeOut'
});
// Play Ana's voice (short clip)
playVoice('ana_flashback_01.mp3');
// Example: "Kai, pomnš tisti dan...?" (short, 2-3 sec)
// OR play emotional music sting
playMusic('flashback_theme.mp3', fadeIn: 500ms);
// Show caption (simple text)
showCaption({
text: "Spomin odklenjn...", // ADHD-friendly: simple, typo intentional for domestic feel
duration: 3000ms,
color: '#FFD700' // Gold
});
// Update quest log
questLog.add('family_memory_' + itemID);
}
```
**Stage 3: Reward**
```javascript
// After memory clears:
- Unlock new location on map (e.g., Capital City)
- Add clue to Ana's trail counter (X/50)
- Small stat boost (Hope +5%)
- Journal entry auto-saved
```
### **Audio Assets Needed:**
- `memory_echo.mp3` - Mysterious hum/echo
- `flashback_theme.mp3` - Short emotional music (10-15 sec)
- `ana_voice_01-10.mp3` - 10 short voice clips from Ana
### **Visual Assets Needed:**
- Family photo (blurred + clear versions)
- Ana's necklace (blurred + clear)
- Old diary page (blurred + clear)
- Kai's childhood toy (blurred + clear)
---
## 🌾 **2. HARVESTING VFX (Stardew Valley Style)**
### **Concept:**
When player harvests crops, items **bounce up with sparkles** and fly into inventory. **Instant satisfaction feedback.**
### **Animation Sequence:**
**Step 1: Harvest Action**
```javascript
onCropHarvested(cropTile) {
// 1. Crop disappears from tile
cropTile.sprite.fadeOut(200ms);
// 2. Item sprite bounces UP
let itemSprite = createSprite(crop.harvestedItem);
itemSprite.position = cropTile.position;
// Bounce animation (arc trajectory)
itemSprite.animate({
y: cropTile.y - 40, // Jump up 40px
duration: 300ms,
easing: 'easeOutQuad'
});
// 3. Sparkle particles
emitParticles({
position: cropTile.position,
count: 8,
sprite: 'sparkle_star.png',
color: '#FFD700', // Gold sparkles
velocity: random(-50, 50),
lifetime: 800ms,
fadeOut: true
});
// 4. Sound effect
playSound('harvest_pop.mp3', volume: 0.7);
// Happy "pop" or "ding" sound
// 5. Fly to inventory (UI corner)
itemSprite.animate({
x: inventoryIcon.x,
y: inventoryIcon.y,
duration: 600ms,
easing: 'easeInQuad',
onComplete: () => {
// Add to inventory
inventory.add(crop.harvestedItem);
itemSprite.destroy();
// Inventory icon pulse
inventoryIcon.pulse();
}
});
}
```
### **Optional: Quality Tier Effects**
Different sparkle colors for quality:
```javascript
qualityColors = {
basic: '#FFFFFF', // White sparkles
silver: '#C0C0C0', // Silver sparkles
gold: '#FFD700', // Gold sparkles
iridium: '#9D00FF' // Purple sparkles (legendary)
}
```
### **Audio Assets Needed:**
- `harvest_pop.mp3` - Satisfying "pop" sound
- `sparkle_ting.mp3` - Optional twinkle sound
### **Visual Assets Needed:**
- `sparkle_star.png` - 8x8px star particle
- `glow_particle.png` - 4x4px glow dot
---
## 🐟 **3. WATER LIFE (Fish Jump Animation)**
### **Concept:**
Fish occasionally **jump out of water** with splash effect. **Visual hint** for good fishing spots.
### **Animation Sequence:**
**Random Fish Jump:**
```javascript
// Every 5-15 seconds at fishing spots
setInterval(() => {
if (Math.random() < 0.3) { // 30% chance
spawnFishJump();
}
}, randomRange(5000, 15000));
function spawnFishJump() {
let waterTile = getRandomWaterTile();
// 1. Fish sprite jumps out
let fish = createSprite('fish_jump.png', waterTile.position);
fish.animate({
// Arc jump animation
keyframes: [
{ y: waterTile.y, time: 0 },
{ y: waterTile.y - 32, time: 300 }, // Peak of jump
{ y: waterTile.y, time: 600 } // Back to water
],
rotation: [0, 180, 360], // Flip in air
easing: 'easeInOutQuad'
});
// 2. Splash effect (start + end)
createSplash(waterTile.position, scale: 1.0);
setTimeout(() => {
createSplash(waterTile.position, scale: 1.2); // Bigger splash on landing
fish.destroy();
}, 600);
// 3. Sound effect
playSound('water_splash.mp3', volume: 0.6);
// 4. Ripple effect
createRipple(waterTile.position, {
radius: [0, 48],
duration: 1000ms,
opacity: [0.8, 0]
});
}
```
**Splash Particle Effect:**
```javascript
function createSplash(position, scale) {
emitParticles({
position: position,
count: 12,
sprite: 'water_drop.png',
color: '#4DB8FF', // Water blue
velocity: randomRange(-80, 80),
gravity: 200, // Drops fall down
lifetime: 500ms,
scale: scale,
rotation: random(0, 360)
});
}
```
### **Gameplay Integration:**
- **Fish jump frequency** indicates fish abundance
- More jumps = better fishing spot
- Rare fish have unique jump animations (golden sparkle)
### **Audio Assets Needed:**
- `water_splash.mp3` - Splash sound
- `fish_jump.mp3` - Optional fish "plop"
### **Visual Assets Needed:**
- `fish_jump.png` - 16x16px fish mid-jump (Style 32)
- `water_drop.png` - 4x4px water droplet particle
- `ripple.png` - 32x32px circular ripple ring
---
## 🎥 **4. DYNAMIC VISUALS (Cutscenes & Story Moments)**
### **Cross-Fade Transitions:**
```javascript
// Scene transitions (smooth, cinematic)
function transitionScene(fromScene, toScene) {
// Fade out current scene
fromScene.fadeOut({
duration: 1000ms,
color: '#000000' // Fade to black
});
// Wait for fade
setTimeout(() => {
// Switch scenes
game.scene.stop(fromScene);
game.scene.start(toScene);
// Fade in new scene
toScene.fadeIn({
duration: 1000ms
});
}, 1000);
}
```
### **Vignette Effect (Important Moments):**
```javascript
// Adds dark edge vignette for dramatic moments
function applyVignette(intensity = 0.5) {
let vignetteShader = {
type: 'radialGradient',
center: [screenWidth/2, screenHeight/2],
radius: screenWidth * 0.6,
colors: [
{ offset: 0, color: 'rgba(0,0,0,0)' },
{ offset: 1, color: `rgba(0,0,0,${intensity})` }
]
};
camera.applyPostFXShader(vignetteShader);
}
// Use during:
- Intro sequence (heavy vignette)
- Ana clue discoveries (medium vignette)
- Boss fights (light vignette)
- Emotional cutscenes (heavy vignette)
```
### **Blur Effect (Dream/Memory Sequences):**
```javascript
// Full-screen blur for dream states
function applyDreamBlur() {
camera.applyPostFXShader({
type: 'gaussianBlur',
strength: 8,
quality: 'medium'
});
// Desaturate colors slightly
camera.applyColorMatrix({
saturation: 0.5, // 50% saturation
brightness: 1.1 // Slightly brighter
});
}
```
### **Slow-Motion Effect (Epic Moments):**
```javascript
// Slow-motion for dramatic moments
function applySlowMotion(duration = 2000, speed = 0.3) {
game.time.timeScale = speed; // 30% speed
setTimeout(() => {
// Return to normal speed
tweenValue(game.time.timeScale, 1.0, {
duration: 500ms,
easing: 'easeOut'
});
}, duration);
// Optional: Add motion blur
camera.applyMotionBlur(strength: 0.5);
}
// Use during:
- Boss defeated moment
- Ana rescue cutscene
- Major discovery moments
```
---
## 🎨 **PARTICLE SYSTEM LIBRARY**
### **Reusable Particle Effects:**
```javascript
particlePresets = {
// Sparkle (harvest, treasure)
sparkle: {
sprite: 'sparkle_star.png',
count: 8,
color: '#FFD700',
velocity: random(-50, 50),
lifetime: 800ms,
fadeOut: true
},
// Smoke (campfire, forge)
smoke: {
sprite: 'smoke_puff.png',
count: 3,
color: '#888888',
velocity: { x: random(-10, 10), y: -30 },
lifetime: 2000ms,
fadeOut: true,
scaleUp: true
},
// Magic (enchanting, portals)
magic: {
sprite: 'glow_particle.png',
count: 20,
color: '#9D00FF', // Purple
velocity: spiral(radius: 40, speed: 2),
lifetime: 1500ms,
fadeOut: true,
glow: true
},
// Blood (combat - optional, can be green "zombie goo")
blood: {
sprite: 'blood_splat.png',
count: 6,
color: '#00FF00', // Green (zombie blood)
velocity: random(-60, 60),
gravity: 150,
lifetime: 800ms,
fadeOut: true
},
// Coins (quest rewards, sales)
coins: {
sprite: 'coin_spin.png',
count: 10,
color: '#FFD700',
velocity: { x: random(-40, 40), y: -80 },
gravity: 200,
lifetime: 1200ms,
rotation: true,
bounce: true
}
}
```
---
## 📊 **VFX IMPLEMENTATION PRIORITY**
| Effect | Priority | Complexity | Impact |
|--------|----------|------------|--------|
| **Harvest Sparkles** | ⭐⭐⭐⭐⭐ | Low | High satisfaction |
| **Amnesia Blur** | ⭐⭐⭐⭐⭐ | Medium | Emotional storytelling |
| **Fish Jump** | ⭐⭐⭐⭐ | Low | World feels alive |
| **Cross-Fade** | ⭐⭐⭐⭐ | Low | Professional polish |
| **Vignette** | ⭐⭐⭐ | Low | Dramatic moments |
| **Slow-Motion** | ⭐⭐ | Medium | Epic boss moments |
---
## 🎯 **PHASER 3 IMPLEMENTATION NOTES**
### **Particle Manager:**
```javascript
// src/systems/ParticleManager.js
class ParticleManager {
constructor(scene) {
this.scene = scene;
this.emitters = {};
}
emit(preset, position, customParams = {}) {
let params = { ...particlePresets[preset], ...customParams };
let emitter = this.scene.add.particles(position.x, position.y, params.sprite, params);
return emitter;
}
sparkle(position) {
return this.emit('sparkle', position);
}
smoke(position) {
return this.emit('smoke', position);
}
magic(position) {
return this.emit('magic', position);
}
}
```
### **Post-FX Pipeline:**
```javascript
// Phaser 3 built-in post-processing
scene.cameras.main.setPostPipeline('BlurPostFX');
scene.cameras.main.setPostPipeline('VignettePostFX');
```
---
## 🎬 **CUTSCENE SYSTEM**
### **Simple Dialogue + VFX:**
```javascript
// src/systems/CutsceneManager.js
class CutsceneManager {
playMemoryFlashback(memoryData) {
// 1. Freeze player
player.freeze();
// 2. Apply vignette
applyVignette(0.7);
// 3. Show blurred image
showBlurredImage(memoryData.image);
// 4. Play Ana's voice
playVoice(memoryData.audioClip);
// 5. Clear blur after 2 seconds
setTimeout(() => {
clearBlur(duration: 2000ms);
}, 2000);
// 6. Show dialogue
setTimeout(() => {
showDialogue({
text: memoryData.caption,
speaker: "Ana",
duration: 4000ms
});
}, 4000);
// 7. Resume game
setTimeout(() => {
removeVignette();
player.unfreeze();
}, 8000);
}
}
```
---
## 🚀 **ASSETS TO GENERATE**
### **Particle Sprites:**
- `sparkle_star.png` - 8x8px gold star
- `glow_particle.png` - 4x4px white glow
- `smoke_puff.png` - 16x16px gray smoke
- `water_drop.png` - 4x4px blue droplet
- `blood_splat.png` - 8x8px green splat (zombie blood)
- `coin_spin.png` - 8x8px gold coin
### **VFX Animations:**
- `fish_jump.png` - 16x16px fish sprite
- `ripple.png` - 32x32px water ripple ring
### **Audio:**
- `memory_echo.mp3`
- `flashback_theme.mp3`
- `ana_voice_01.mp3` through `ana_voice_10.mp3`
- `harvest_pop.mp3`
- `sparkle_ting.mp3`
- `water_splash.mp3`
---
**Status:** 🟢 **READY FOR IMPLEMENTATION**
**Estimated Time:** 6-8 hours coding + 2 hours audio/visual assets
**Emotional Impact:** 🚀 **MASSIVE** - Game feels alive and responsive!