🎬🔥 60-SECOND EPIC INTRO - COMPLETE IMPLEMENTATION!

 COMPLETE 60-SECOND CINEMATIC:
- ALL 20 intro shots integrated
- 4 emotional phases (Childhood→Virus→Amnesia→Awakening)
- Perfect timing (3s per shot)
- Smooth transitions with glitch effects

 FULL VOICE INTEGRATION:
- 12 Kai voices (complete narrative arc)
- 8 Ana voices (emotional journey)
- 1 Gronk voice (wake-up call)
- playVoice() function for audio triggers
- Synchronized with shot timing

 4 PHASES BREAKDOWN:
**Phase 1 (0-15s): HAPPY CHILDHOOD**
- 5 shots: Family, Father, Dreads, Barbershop, Birthday
- Kai + Ana voices: 'Bili smo... celi.'
- Warm colors, nostalgic

**Phase 2 (15-30s): THE VIRUS**
- 5 shots: Virus, Chaos, Zombies, Parents, Ana Taken
- Dramatic voices: 'KAI! NE POZABI ME!'
- Red/green toxic, glitch, camera shake

**Phase 3 (30-45s): THE AMNESIA**
- 5 shots: Alone, Young, Adult, Elder, Memory
- Aging timeline: 'Leta so minila...'
- Dark, mysterious

**Phase 4 (45-60s): THE AWAKENING**
- 5 shots: Bedroom, Gronk, Memory, Twins, Fade
- Final resolve: '...tudi če mi vzame celo življenje.'
- Fade to GameScene

🎨 VISUAL EFFECTS:
- Polaroid frames (65% size, floating)
- VHS scanlines + noise
- Chromatic aberration (RGB flash)
- Warm/red/toxic color tints
- Camera shake + strobe
- Glitch transitions

🎵 AUDIO SYSTEM:
- Ambient noir music (loop)
- Voice auto-stop on new voice
- Skip stops all audio
- Volume balanced (ambient 0.2, voices 0.8)

⏱️  TOTAL DURATION: 60 seconds exactly
🎯 SKIP: Available after 5s (X or SPACE)
🔄 TRANSITIONS: Fade to GameScene at 60s

READY FOR EPIC TEST! 🎆
This commit is contained in:
2026-01-10 13:59:39 +01:00
parent d383483d96
commit d9f40d016d

View File

@@ -1,7 +1,8 @@
// 🎬 INTRO SEQUENCE - VERSION B (30-45 seconds Fast-Cut) // 🎬 INTRO SEQUENCE - 60-SECOND EPIC CINEMATIC
// "From Colors to Darkness" - Kai's Amnesia Awakening // "From Colors to Darkness" - Complete Story
// Created: January 10, 2026 // Created: January 10, 2026
// Style: Style 32 Dark-Chibi Noir with ADHD energy // Style: Style 32 Dark-Chibi Noir + Polaroid + VHS
// Voices: Kai (Rok) + Ana (Petra) + Gronk (Rok deep)
class IntroScene extends Phaser.Scene { class IntroScene extends Phaser.Scene {
constructor() { constructor() {
@@ -9,64 +10,86 @@ class IntroScene extends Phaser.Scene {
this.skipEnabled = false; this.skipEnabled = false;
this.currentPhase = 0; this.currentPhase = 0;
this.skipPrompt = null; this.skipPrompt = null;
this.currentShot = null;
this.currentPolaroid = null; this.currentPolaroid = null;
this.currentText = null; this.currentText = null;
this.vhsNoise = null; this.vhsNoise = null;
this.scanlines = null; this.scanlines = null;
this.ambientAudio = null; this.ambientAudio = null;
this.projectorAudio = null; this.currentVoice = null;
} }
preload() { preload() {
console.log('🎬 IntroScene: Loading assets...'); console.log('🎬 IntroScene: Loading EPIC 60s assets...');
// Base path for intro shots // Base path for intro shots
const introPath = 'assets/references/intro_shots/'; const introPath = 'assets/references/intro_shots/';
// PHASE 1: HAPPY FAMILY (5 shots) // ALL 20 INTRO SHOTS
this.load.image('intro_otac_longboard', introPath + 'otac_longboard_pier.png');
this.load.image('intro_ana_barbershop', introPath + 'ana_barbershop_dreads.png');
this.load.image('intro_twins_childhood', introPath + 'kai_ana_twins_childhood.png');
this.load.image('intro_birthday_cake', introPath + 'birthday_cake_rd.png');
this.load.image('intro_family_portrait', introPath + 'family_portrait_punk_complete.png'); this.load.image('intro_family_portrait', introPath + 'family_portrait_punk_complete.png');
this.load.image('intro_otac_longboard', introPath + 'otac_longboard_pier.png');
// PHASE 2: THE COLLAPSE (4 shots) this.load.image('intro_kai_dreads', introPath + 'kai_first_dreads_family.png');
this.load.image('intro_ana_barbershop', introPath + 'ana_barbershop_dreads.png');
this.load.image('intro_birthday_cake', introPath + 'birthday_cake_rd.png');
this.load.image('intro_virus', introPath + 'virus_xnoir_microscope.png'); this.load.image('intro_virus', introPath + 'virus_xnoir_microscope.png');
this.load.image('intro_zombies', introPath + 'zombie_silhouettes_panic.png');
this.load.image('intro_chaos', introPath + 'chaos_streets_apocalypse.png'); this.load.image('intro_chaos', introPath + 'chaos_streets_apocalypse.png');
this.load.image('intro_zombies', introPath + 'zombie_silhouettes_panic.png');
this.load.image('intro_parents_ghosts', introPath + 'parents_transparent_ghosts.png');
this.load.image('intro_ana_taken', introPath + 'ana_taken_military.png'); this.load.image('intro_ana_taken', introPath + 'ana_taken_military.png');
this.load.image('intro_kai_alone', introPath + 'kai_alone_basement.png');
// PHASE 3: AMNESIA WAKE-UP (4 shots) this.load.image('intro_kai_young', introPath + 'kai_young_timelapse.png');
this.load.image('intro_bedroom', introPath + 'kai_bedroom_wakeup.png'); this.load.image('intro_kai_adult', introPath + 'kai_adult_35_timelapse.png');
this.load.image('intro_kai_elder', introPath + 'kai_elder_50_timelapse.png');
this.load.image('intro_ana_memory', introPath + 'ana_memory_flash_purple.png'); this.load.image('intro_ana_memory', introPath + 'ana_memory_flash_purple.png');
this.load.image('intro_bedroom', introPath + 'kai_bedroom_wakeup.png');
this.load.image('intro_gronk', introPath + 'gronk_doorway_silhouette.png'); this.load.image('intro_gronk', introPath + 'gronk_doorway_silhouette.png');
this.load.image('intro_twins_childhood', introPath + 'kai_ana_twins_childhood.png');
// 🎵 AUDIO (Optional - with safe loading) // 🎵 AMBIENT MUSIC
this.loadAudioSafe('noir_ambience', 'assets/audio/ambient/noir_ambience.mp3'); this.loadAudioSafe('noir_ambience', 'assets/audio/ambient/noir_ambience.mp3');
this.loadAudioSafe('projector_loop', 'assets/audio/ambient/projector_loop.mp3');
// Voice triggers (placeholders) // 🎤 KAI VOICES (12 total)
this.loadAudioSafe('audio_kai_memory_01', 'assets/audio/voiceover/kai_memory_01.mp3'); this.loadAudioSafe('kai_01', 'assets/audio/voiceover/kai_01_beginning.mp3');
this.loadAudioSafe('audio_kai_memory_02', 'assets/audio/voiceover/kai_memory_02.mp3'); this.loadAudioSafe('kai_02', 'assets/audio/voiceover/kai_02_father.mp3');
this.loadAudioSafe('audio_kai_memory_03', 'assets/audio/voiceover/kai_memory_03.mp3'); this.loadAudioSafe('kai_03', 'assets/audio/voiceover/kai_03_whole.mp3');
this.loadAudioSafe('kai_04', 'assets/audio/voiceover/kai_04_virus.mp3');
this.loadAudioSafe('kai_05', 'assets/audio/voiceover/kai_05_zombies.mp3');
this.loadAudioSafe('kai_06', 'assets/audio/voiceover/kai_06_alone.mp3');
this.loadAudioSafe('kai_07', 'assets/audio/voiceover/kai_07_years.mp3');
this.loadAudioSafe('kai_08', 'assets/audio/voiceover/kai_08_memory.mp3');
this.loadAudioSafe('kai_09', 'assets/audio/voiceover/kai_09_fog.mp3');
this.loadAudioSafe('kai_10', 'assets/audio/voiceover/kai_10_wake.mp3');
this.loadAudioSafe('kai_11', 'assets/audio/voiceover/kai_11_find.mp3');
this.loadAudioSafe('kai_12', 'assets/audio/voiceover/kai_12_lifetime.mp3');
// 🎤 ANA VOICES (8 total)
this.loadAudioSafe('ana_01', 'assets/audio/voiceover/ana_01_ride.mp3');
this.loadAudioSafe('ana_02', 'assets/audio/voiceover/ana_02_immortal.mp3');
this.loadAudioSafe('ana_03', 'assets/audio/voiceover/ana_03_whole.mp3');
this.loadAudioSafe('ana_04', 'assets/audio/voiceover/ana_04_changed.mp3');
this.loadAudioSafe('ana_05', 'assets/audio/voiceover/ana_05_parents.mp3');
this.loadAudioSafe('ana_06', 'assets/audio/voiceover/ana_06_scream.mp3');
this.loadAudioSafe('ana_07', 'assets/audio/voiceover/ana_07_truth.mp3');
this.loadAudioSafe('ana_08', 'assets/audio/voiceover/ana_08_two.mp3');
// 🎤 GRONK VOICE
this.loadAudioSafe('gronk_01', 'assets/audio/voiceover/gronk_01_wake.mp3');
} }
loadAudioSafe(key, path) { loadAudioSafe(key, path) {
try { try {
this.load.audio(key, path); this.load.audio(key, path);
} catch (error) { } catch (error) {
console.warn(`⚠️ Audio skipped: ${key} (file not found)`); console.warn(`⚠️ Audio skipped: ${key}`);
} }
} }
create() { create() {
console.log('🎬 IntroScene: Starting intro sequence...'); console.log('🎬 IntroScene: Starting 60-SECOND EPIC...');
// Black background // Black background
this.cameras.main.setBackgroundColor('#000000'); this.cameras.main.setBackgroundColor('#000000');
// 🎵 Start ambient audio (if available) // 🎵 Start ambient audio
this.startAmbientAudio(); this.startAmbientAudio();
// 📺 Create VHS overlay effects // 📺 Create VHS overlay effects
@@ -82,49 +105,28 @@ class IntroScene extends Phaser.Scene {
}); });
// Start Phase 1 // Start Phase 1
this.playPhase1HappyFamily(); this.playPhase1HappyChildhood();
}
setupSkipControls() {
// Keyboard skip (X key or SPACE)
this.input.keyboard.on('keydown-X', () => this.skipIntro());
this.input.keyboard.on('keydown-SPACE', () => this.skipIntro());
// Mouse/touch skip (click anywhere)
this.input.on('pointerdown', () => {
if (this.skipEnabled) {
this.skipIntro();
}
});
} }
startAmbientAudio() { startAmbientAudio() {
// Noir ambience (constant low drone)
try { try {
if (this.cache.audio.exists('noir_ambience')) { if (this.cache.audio.exists('noir_ambience')) {
this.ambientAudio = this.sound.add('noir_ambience', { volume: 0.15, loop: true }); this.ambientAudio = this.sound.add('noir_ambience', {
volume: 0.2,
loop: true
});
this.ambientAudio.play(); this.ambientAudio.play();
} }
} catch (e) { } catch (e) {
console.warn('⚠️ Ambient audio not available'); console.warn('⚠️ Ambient audio not available');
} }
// Projector sound (old film aesthetic)
try {
if (this.cache.audio.exists('projector_loop')) {
this.projectorAudio = this.sound.add('projector_loop', { volume: 0.2, loop: true });
this.projectorAudio.play();
}
} catch (e) {
console.warn('⚠️ Projector audio not available');
}
} }
createVHSEffects() { createVHSEffects() {
const width = this.cameras.main.width; const width = this.cameras.main.width;
const height = this.cameras.main.height; const height = this.cameras.main.height;
// VHS Scanlines (horizontal lines) // VHS Scanlines
this.scanlines = this.add.graphics(); this.scanlines = this.add.graphics();
this.scanlines.setDepth(900); this.scanlines.setDepth(900);
@@ -133,7 +135,7 @@ class IntroScene extends Phaser.Scene {
this.scanlines.fillRect(0, y, width, 2); this.scanlines.fillRect(0, y, width, 2);
} }
// VHS Noise overlay (subtle static) // VHS Noise overlay
this.vhsNoise = this.add.rectangle( this.vhsNoise = this.add.rectangle(
width / 2, width / 2,
height / 2, height / 2,
@@ -144,7 +146,7 @@ class IntroScene extends Phaser.Scene {
); );
this.vhsNoise.setDepth(901); this.vhsNoise.setDepth(901);
// Animate noise (flicker) // Animate noise
this.tweens.add({ this.tweens.add({
targets: this.vhsNoise, targets: this.vhsNoise,
alpha: { from: 0.01, to: 0.05 }, alpha: { from: 0.01, to: 0.05 },
@@ -154,8 +156,19 @@ class IntroScene extends Phaser.Scene {
}); });
} }
setupSkipControls() {
this.input.keyboard.on('keydown-X', () => this.skipIntro());
this.input.keyboard.on('keydown-SPACE', () => this.skipIntro());
this.input.on('pointerdown', () => {
if (this.skipEnabled) {
this.skipIntro();
}
});
}
showSkipPrompt() { showSkipPrompt() {
if (this.skipPrompt) return; // Already showing if (this.skipPrompt) return;
const width = this.cameras.main.width; const width = this.cameras.main.width;
const height = this.cameras.main.height; const height = this.cameras.main.height;
@@ -176,7 +189,6 @@ class IntroScene extends Phaser.Scene {
this.skipPrompt.setAlpha(0.7); this.skipPrompt.setAlpha(0.7);
this.skipPrompt.setDepth(1000); this.skipPrompt.setDepth(1000);
// Pulse animation
this.tweens.add({ this.tweens.add({
targets: this.skipPrompt, targets: this.skipPrompt,
alpha: { from: 0.7, to: 1.0 }, alpha: { from: 0.7, to: 1.0 },
@@ -191,7 +203,9 @@ class IntroScene extends Phaser.Scene {
console.log('⏭️ IntroScene: Skipped by user'); console.log('⏭️ IntroScene: Skipped by user');
// Stop all tweens and timers // Stop all
if (this.ambientAudio) this.ambientAudio.stop();
if (this.currentVoice) this.currentVoice.stop();
this.tweens.killAll(); this.tweens.killAll();
this.time.removeAllEvents(); this.time.removeAllEvents();
@@ -202,277 +216,162 @@ class IntroScene extends Phaser.Scene {
}); });
} }
playPhase1HappyFamily() { playVoice(key) {
// PHASE 1: HAPPY FAMILY MEMORIES (0-15s) try {
console.log('🎬 Phase 1: Happy Family'); if (this.cache.audio.exists(key)) {
if (this.currentVoice) this.currentVoice.stop();
this.currentVoice = this.sound.add(key, { volume: 0.8 });
this.currentVoice.play();
}
} catch (e) {
console.warn(`⚠️ Voice ${key} not available`);
}
}
// ═══════════════════════════════════════════════════════════
// PHASE 1: HAPPY CHILDHOOD (0-15s)
// ═══════════════════════════════════════════════════════════
playPhase1HappyChildhood() {
console.log('🎬 Phase 1: Happy Childhood (0-15s)');
this.currentPhase = 1; this.currentPhase = 1;
const width = this.cameras.main.width; // Shot 1 (0-3s): Family Portrait + Kai voice
const height = this.cameras.main.height; this.showShot('intro_family_portrait', 0, 3000, { warm: true });
this.time.delayedCall(200, () => this.playVoice('kai_01')); // "Vse se je začelo..."
// Text overlay // Shot 2 (3-6s): Otac Longboard + Kai voice
const text1 = this.add.text( this.showShot('intro_otac_longboard', 3000, 6000, { warm: true });
width / 2, this.time.delayedCall(3200, () => this.playVoice('kai_02')); // "Oče me je učil..."
height - 80,
'Nekoč smo imeli barve...',
{
fontFamily: 'Courier New',
fontSize: '24px',
fill: '#ffffff',
stroke: '#00ffff',
strokeThickness: 1,
shadow: {
offsetX: 2,
offsetY: 2,
color: '#ff00ff',
blur: 5,
stroke: false,
fill: true
}
}
);
text1.setOrigin(0.5);
text1.setAlpha(0);
text1.setDepth(100);
this.tweens.add({ // Shot 3 (6-9s): Kai Dreads + Ana voice
targets: text1, this.showShot('intro_kai_dreads', 6000, 9000, { warm: true });
alpha: 1, this.time.delayedCall(6200, () => this.playVoice('ana_01')); // "...ampak divja vožnja..."
duration: 1000,
delay: 500
});
// Shots sequence - fast cuts (~3s each) // Shot 4 (9-12s): Ana Barbershop + Ana voice
this.showShot('intro_otac_longboard', 0, 3000, { warm: true }); this.showShot('intro_ana_barbershop', 9000, 12000, { warm: true });
this.showShot('intro_ana_barbershop', 3000, 6000, { warm: true }); this.time.delayedCall(9200, () => this.playVoice('ana_02')); // "Bili smo neustavljivi..."
this.showShot('intro_twins_childhood', 6000, 9000, { warm: true, clear: true }); // CLEAREST
this.showShot('intro_birthday_cake', 9000, 12000, { warm: true }); // Shot 5 (12-15s): Birthday Cake + Both voices
this.showShot('intro_family_portrait', 12000, 15000, { warm: true, freeze: true }); this.showShot('intro_birthday_cake', 12000, 15000, { warm: true });
this.time.delayedCall(12200, () => this.playVoice('kai_03')); // "Bili smo... celi."
// Transition to Phase 2 // Transition to Phase 2
this.time.delayedCall(14500, () => { this.time.delayedCall(15000, () => this.playPhase2TheVirus());
this.tweens.add({
targets: text1,
alpha: 0,
duration: 500
});
});
this.time.delayedCall(15000, () => {
text1.destroy();
this.playPhase2TheCollapse();
});
} }
playPhase2TheCollapse() { // ═══════════════════════════════════════════════════════════
// PHASE 2: THE COLLAPSE (15-30s) // PHASE 2: THE VIRUS (15-30s)
console.log('🎬 Phase 2: The Collapse'); // ═══════════════════════════════════════════════════════════
playPhase2TheVirus() {
console.log('🎬 Phase 2: The Virus (15-30s)');
this.currentPhase = 2; this.currentPhase = 2;
const width = this.cameras.main.width; // Shot 6 (15-18s): Virus + Kai voice
const height = this.cameras.main.height; this.showShot('intro_virus', 15000, 18000, { toxic: true, glitch: true });
this.time.delayedCall(15200, () => this.playVoice('kai_04')); // "Potem je prišel X-Noir..."
// Text overlay // Shot 7 (18-21s): Chaos + Ana voice
const text2 = this.add.text( this.showShot('intro_chaos', 18000, 21000, { red: true, glitch: true });
width / 2, this.time.delayedCall(18200, () => this.playVoice('ana_04')); // "Vsi so se spremenili..."
height - 80, this.cameras.main.shake(3000, 0.005);
'Potem je prišla tema...',
{
fontFamily: 'Courier New',
fontSize: '24px',
fill: '#ff0000',
stroke: '#00ff00',
strokeThickness: 2,
shadow: {
offsetX: 3,
offsetY: 3,
color: '#000000',
blur: 10,
stroke: true,
fill: true
}
}
);
text2.setOrigin(0.5);
text2.setAlpha(0);
text2.setDepth(100);
this.tweens.add({ // Shot 8 (21-24s): Zombies + Kai voice
targets: text2, this.showShot('intro_zombies', 21000, 24000, { red: true, strobe: true });
alpha: 1, this.time.delayedCall(21200, () => this.playVoice('kai_05')); // "Sosedi, prijatelji..."
duration: 800,
delay: 300
});
// Shots sequence - faster, chaotic (~4s each) // Shot 9 (24-27s): Parents Ghosts + Ana voice
this.showShot('intro_virus', 15000, 19000, { toxic: true, glitch: true }); this.showShot('intro_parents_ghosts', 24000, 27000, { fadeIn: true });
this.showShot('intro_zombies', 19000, 23000, { red: true, glitch: true, strobe: true }); this.time.delayedCall(24200, () => this.playVoice('ana_05')); // "Starša sta se borila..."
this.showShot('intro_chaos', 23000, 27000, { chaos: true });
this.showShot('intro_ana_taken', 27000, 30000, { blur: true, red: true });
// Add camera shake for chaos // Shot 10 (27-30s): Ana Taken + Ana SCREAM
this.time.delayedCall(19000, () => { this.showShot('intro_ana_taken', 27000, 30000, { red: true, blur: true });
this.cameras.main.shake(4000, 0.005); this.time.delayedCall(27200, () => this.playVoice('ana_06')); // "KAI! NE POZABI ME!"
});
// Transition to Phase 3 // Transition to Phase 3
this.time.delayedCall(29500, () => { this.time.delayedCall(30000, () => this.playPhase3TheAmnesia());
this.tweens.add({
targets: text2,
alpha: 0,
duration: 500
});
});
this.time.delayedCall(30000, () => {
text2.destroy();
this.playPhase3AmnesiaWakeUp();
});
} }
playPhase3AmnesiaWakeUp() { // ═══════════════════════════════════════════════════════════
// PHASE 3: AMNESIA WAKE-UP (30-45s) // PHASE 3: THE AMNESIA (30-45s)
console.log('🎬 Phase 3: Amnesia Wake-Up'); // ═══════════════════════════════════════════════════════════
playPhase3TheAmnesia() {
console.log('🎬 Phase 3: The Amnesia (30-45s)');
this.currentPhase = 3; this.currentPhase = 3;
const width = this.cameras.main.width; // Shot 11 (30-33s): Kai Alone + Kai voice
const height = this.cameras.main.height; this.showShot('intro_kai_alone', 30000, 33000, { fadeIn: true });
this.time.delayedCall(30200, () => this.playVoice('kai_06')); // "Ostal sem sam..."
// Screen goes black first (amnesia darkness) // Shot 12 (33-36s): Kai Young + Kai voice
const blackScreen = this.add.rectangle( this.showShot('intro_kai_young', 33000, 36000, { fadeIn: true });
width / 2, this.time.delayedCall(33200, () => this.playVoice('kai_07')); // "Leta so minila..."
height / 2,
width,
height,
0x000000
);
blackScreen.setDepth(50);
blackScreen.setAlpha(0);
this.tweens.add({ // Shot 13 (36-39s): Kai Adult + Kai voice
targets: blackScreen, this.showShot('intro_kai_adult', 36000, 39000, { fadeIn: true });
alpha: 1, this.time.delayedCall(36200, () => this.playVoice('kai_08')); // "...brada je zrasla..."
duration: 1000,
delay: 0
});
// Text overlays // Shot 14 (39-42s): Kai Elder + Kai voice
const text3a = this.add.text( this.showShot('intro_kai_elder', 39000, 42000, { fadeIn: true });
width / 2, this.time.delayedCall(39200, () => this.playVoice('kai_09')); // "Spomin je ostal megla..."
height / 2 - 40,
'In ostal sem sam...',
{
fontFamily: 'Courier New',
fontSize: '20px',
fill: '#666666',
stroke: '#000000',
strokeThickness: 2
}
);
text3a.setOrigin(0.5);
text3a.setAlpha(0);
text3a.setDepth(100);
const text3b = this.add.text( // Shot 15 (42-45s): Ana Memory + Ana voice (echo)
width / 2, this.showShot('intro_ana_memory', 42000, 45000, { fadeIn: true });
height / 2, this.time.delayedCall(42200, () => this.playVoice('ana_07')); // "Ana... Sestra..."
'z luknjo v glavi.',
{
fontFamily: 'Courier New',
fontSize: '20px',
fill: '#999999',
stroke: '#000000',
strokeThickness: 2
}
);
text3b.setOrigin(0.5);
text3b.setAlpha(0);
text3b.setDepth(100);
this.tweens.add({ // Transition to Phase 4
targets: text3a, this.time.delayedCall(45000, () => this.playPhase4TheAwakening());
alpha: 1, }
duration: 1500,
delay: 1500
});
this.tweens.add({ // ═══════════════════════════════════════════════════════════
targets: text3b, // PHASE 4: THE AWAKENING (45-60s)
alpha: 1, // ═══════════════════════════════════════════════════════════
duration: 1500, playPhase4TheAwakening() {
delay: 2500 console.log('🎬 Phase 4: The Awakening (45-60s)');
}); this.currentPhase = 4;
// Fade out black screen and text, show bedroom // Shot 16 (45-48s): Bedroom + Kai voice
this.time.delayedCall(5000, () => { this.showShot('intro_bedroom', 45000, 48000, { fadeIn: true });
this.tweens.add({ this.time.delayedCall(45200, () => this.playVoice('kai_10')); // "In zdaj... se zbudim..."
targets: [blackScreen, text3a, text3b],
alpha: 0,
duration: 2000
});
});
// Bedroom appears // Shot 17 (48-51s): Gronk + Gronk voice
this.time.delayedCall(7000, () => { this.showShot('intro_gronk', 48000, 51000, { fadeIn: true });
blackScreen.destroy(); this.time.delayedCall(48200, () => this.playVoice('gronk_01')); // "Končno si buden..."
text3a.destroy();
text3b.destroy();
this.showShot('intro_bedroom', 37000, 40000, { fadeIn: true });
});
// Ana memory flash // Shot 18 (51-54s): Ana Memory Reprise + Kai voice
this.time.delayedCall(10000, () => { this.showShot('intro_ana_memory', 51000, 54000, { fadeIn: true });
const flash = this.add.image(width / 2, height / 2, 'intro_ana_memory'); this.time.delayedCall(51200, () => this.playVoice('kai_11')); // "Moram jo najti."
flash.setAlpha(0);
flash.setDepth(80); // Shot 19 (54-57s): Twins Childhood + Ana voice
flash.setScale(0.8); this.showShot('intro_twins_childhood', 54000, 57000, { warm: true, fadeIn: true });
this.time.delayedCall(54200, () => this.playVoice('ana_08')); // "Vedno sva bila dva..."
// Shot 20 (57-60s): Fade to Black + Kai FINAL
this.time.delayedCall(57000, () => {
this.playVoice('kai_12'); // "...tudi če mi vzame celo življenje."
// Fade to black
const blackScreen = this.add.rectangle(
this.cameras.main.width / 2,
this.cameras.main.height / 2,
this.cameras.main.width,
this.cameras.main.height,
0x000000
);
blackScreen.setAlpha(0);
blackScreen.setDepth(1000);
this.tweens.add({ this.tweens.add({
targets: flash, targets: blackScreen,
alpha: 1, alpha: 1,
duration: 300, duration: 3000
yoyo: true,
repeat: 2,
onComplete: () => flash.destroy()
});
});
// Gronk entrance
this.time.delayedCall(12000, () => {
this.showShot('intro_gronk', 42000, 45000, { fadeIn: true });
});
// Final text
const textFinal = this.add.text(
width / 2,
height - 100,
'Moram jo najti.\nTudi če mi vzame celo življenje.',
{
fontFamily: 'Courier New',
fontSize: '18px',
fill: '#ffffff',
stroke: '#ff00ff',
strokeThickness: 1,
align: 'center',
lineSpacing: 10
}
);
textFinal.setOrigin(0.5);
textFinal.setAlpha(0);
textFinal.setDepth(100);
this.time.delayedCall(13000, () => {
this.tweens.add({
targets: textFinal,
alpha: 1,
duration: 2000
}); });
}); });
// Transition to GameScene // Transition to GameScene
this.time.delayedCall(17000, () => { this.time.delayedCall(60000, () => {
console.log('🎬 IntroScene: Complete! Starting game...'); console.log('🎬 IntroScene: EPIC COMPLETE! Starting game...');
this.cameras.main.fadeOut(2000, 0, 0, 0); if (this.ambientAudio) this.ambientAudio.stop();
this.cameras.main.fadeOut(1000, 0, 0, 0);
this.cameras.main.once('camerafadeoutcomplete', () => { this.cameras.main.once('camerafadeoutcomplete', () => {
this.scene.start('GameScene'); this.scene.start('GameScene');
}); });
@@ -503,7 +402,7 @@ class IntroScene extends Phaser.Scene {
// Create photo image (65% of screen) // Create photo image (65% of screen)
const photo = this.add.image(width / 2, height / 2 - 30, imageKey); const photo = this.add.image(width / 2, height / 2 - 30, imageKey);
photo.setAlpha(options.fadeIn ? 0 : 1); photo.setAlpha(0);
photo.setDepth(20); photo.setDepth(20);
// Scale to 65% of screen size // Scale to 65% of screen size
@@ -512,14 +411,15 @@ class IntroScene extends Phaser.Scene {
photo.setScale(photoScale); photo.setScale(photoScale);
// Create Polaroid white frame // Create Polaroid white frame
const frameWidth = photo.displayWidth + 40; // 20px padding each side const frameWidth = photo.displayWidth + 40;
const frameHeight = photo.displayHeight + 80; // 20px top, 60px bottom (Polaroid style!) const frameHeight = photo.displayHeight + 80;
const frame = this.add.graphics(); const frame = this.add.graphics();
frame.setDepth(19); frame.setDepth(19);
frame.setAlpha(0);
// Dirty white Polaroid background // Dirty white Polaroid background
frame.fillStyle(0xf5f5dc, 1); // Beige white frame.fillStyle(0xf5f5dc, 1);
frame.fillRect( frame.fillRect(
(width - frameWidth) / 2, (width - frameWidth) / 2,
(height - frameHeight) / 2 - 30, (height - frameHeight) / 2 - 30,
@@ -527,7 +427,7 @@ class IntroScene extends Phaser.Scene {
frameHeight frameHeight
); );
// Add subtle dirt/grain texture // Add dirt/grain texture
for (let i = 0; i < 50; i++) { for (let i = 0; i < 50; i++) {
const x = (width - frameWidth) / 2 + Math.random() * frameWidth; const x = (width - frameWidth) / 2 + Math.random() * frameWidth;
const y = (height - frameHeight) / 2 - 30 + Math.random() * frameHeight; const y = (height - frameHeight) / 2 - 30 + Math.random() * frameHeight;
@@ -537,7 +437,7 @@ class IntroScene extends Phaser.Scene {
this.currentPolaroid = { photo, frame }; this.currentPolaroid = { photo, frame };
// 🌊 FLOATING ANIMATION (5px up/down) // 🌊 FLOATING ANIMATION
this.tweens.add({ this.tweens.add({
targets: [photo, frame], targets: [photo, frame],
y: '-=5', y: '-=5',
@@ -547,40 +447,38 @@ class IntroScene extends Phaser.Scene {
ease: 'Sine.easeInOut' ease: 'Sine.easeInOut'
}); });
// Apply visual effects to photo // Apply visual effects
if (options.warm) { if (options.warm) {
photo.setTint(0xffddaa); // Warm nostalgic tint photo.setTint(0xffddaa);
} }
if (options.red) { if (options.red) {
photo.setTint(0xff6666); // Red danger tint photo.setTint(0xff6666);
} }
if (options.toxic) { if (options.toxic) {
photo.setTint(0x66ff66); // Green toxic tint photo.setTint(0x66ff66);
} }
// 2 SECOND FADE-IN // 2 SECOND FADE-IN
if (options.fadeIn !== false) { this.tweens.add({
this.tweens.add({ targets: [photo, frame],
targets: [photo, frame], alpha: { from: 0, to: 1 },
alpha: { from: 0, to: 1 }, duration: 2000,
duration: 2000, ease: 'Power2.easeOut'
ease: 'Power2.easeOut' });
});
}
// GLITCH-OUT transition for next shot // GLITCH-OUT transition
this.time.delayedCall(duration - 500, () => { this.time.delayedCall(duration - 500, () => {
if (this.currentPolaroid) { if (this.currentPolaroid) {
// First, quickly fade out the frame (so it doesn't show during glitch!) // Frame fades first
this.tweens.add({ this.tweens.add({
targets: frame, targets: frame,
alpha: 0, alpha: 0,
duration: 100 duration: 100
}); });
// Then glitch effect on photo only // Photo glitches
this.tweens.add({ this.tweens.add({
targets: photo, targets: photo,
x: { from: photo.x - 10, to: photo.x + 10 }, x: { from: photo.x - 10, to: photo.x + 10 },
@@ -588,12 +486,11 @@ class IntroScene extends Phaser.Scene {
repeat: 5, repeat: 5,
yoyo: true, yoyo: true,
onComplete: () => { onComplete: () => {
// Chromatic aberration effect (RGB flash) // RGB flash
photo.setTint(0xff0000); photo.setTint(0xff0000);
this.time.delayedCall(50, () => photo.setTint(0x00ff00)); this.time.delayedCall(50, () => photo.setTint(0x00ff00));
this.time.delayedCall(100, () => photo.setTint(0x0000ff)); this.time.delayedCall(100, () => photo.setTint(0x0000ff));
this.time.delayedCall(150, () => { this.time.delayedCall(150, () => {
// Final fade out
this.tweens.add({ this.tweens.add({
targets: photo, targets: photo,
alpha: 0, alpha: 0,
@@ -606,7 +503,6 @@ class IntroScene extends Phaser.Scene {
}); });
if (options.glitch) { if (options.glitch) {
// Extra glitch during display
this.tweens.add({ this.tweens.add({
targets: [photo, frame], targets: [photo, frame],
x: { from: width / 2 - 5, to: width / 2 + 5 }, x: { from: width / 2 - 5, to: width / 2 + 5 },
@@ -617,7 +513,6 @@ class IntroScene extends Phaser.Scene {
} }
if (options.strobe) { if (options.strobe) {
// Strobe effect
this.tweens.add({ this.tweens.add({
targets: photo, targets: photo,
alpha: { from: 0.7, to: 1.0 }, alpha: { from: 0.7, to: 1.0 },
@@ -630,12 +525,12 @@ class IntroScene extends Phaser.Scene {
} }
shutdown() { shutdown() {
// Cleanup if (this.ambientAudio) this.ambientAudio.stop();
if (this.skipPrompt) { if (this.currentVoice) this.currentVoice.stop();
this.skipPrompt.destroy(); if (this.skipPrompt) this.skipPrompt.destroy();
} if (this.currentPolaroid) {
if (this.currentShot) { this.currentPolaroid.frame.destroy();
this.currentShot.destroy(); this.currentPolaroid.photo.destroy();
} }
this.tweens.killAll(); this.tweens.killAll();
this.time.removeAllEvents(); this.time.removeAllEvents();