/** * Enhanced PrologueScene - Cinematic Intro * * Features: * - Black screen opening with breathing * - Blur effect awakening * - Voice-synced visuals * - Cross-fade transitions * - Auto quest trigger */ class EnhancedPrologueScene extends Phaser.Scene { constructor() { super({ key: 'EnhancedPrologueScene' }); this.currentPhase = 0; } preload() { console.log('🎬 Preloading Enhanced Prologue Assets...'); // Load intro assets // Load intro assets (UPDATED paths to assets/slike/zgodba) this.load.image('intro_black', 'assets/slike/zgodba/assets_BACKUP_20260112_064319_references_intro_black_screen.png'); this.load.image('intro_cellar', 'assets/slike/zgodba/assets_references_intro_cellar_ruins.png'); this.load.image('intro_id_card', 'assets/slike/zgodba/assets_references_intro_id_card.png'); this.load.image('intro_twin_photo', 'assets/slike/zgodba/assets_references_intro_twin_photo.png'); this.load.image('intro_blur', 'assets/slike/zgodba/assets_references_intro_blur_overlay.png'); // Load enhanced voices const voicePath = 'assets/audio/voiceover/intro_enhanced/'; this.load.audio('voice_breathing', voicePath + '00_kai_breathing.mp3'); this.load.audio('voice_flyover', voicePath + '01_narrator_flyover_enhanced.mp3'); this.load.audio('voice_awakening', voicePath + '02_kai_awakening_enhanced.mp3'); this.load.audio('voice_truth', voicePath + '03_kai_truth_enhanced.mp3'); this.load.audio('voice_determination', voicePath + '04_kai_determination_enhanced.mp3'); // Load noir music this.load.audio('noir_ambient', 'assets/audio/music/night_theme.wav'); } create() { console.log('🎬 Starting Enhanced Prologue...'); const { width, height } = this.cameras.main; // Start noir music (low volume) this.noirMusic = this.playAudioSafe('noir_ambient', { volume: 0.3, loop: true }); // Create layers this.backgroundLayer = this.add.container(0, 0); this.uiLayer = this.add.container(0, 0); // Start with black screen this.blackScreen = this.add.image(width / 2, height / 2, 'intro_black'); this.blackScreen.setAlpha(1); this.backgroundLayer.add(this.blackScreen); // Subtitle text (centered, bottom) this.subtitleText = this.add.text(width / 2, height - 100, '', { fontSize: '24px', fontFamily: 'Georgia, serif', color: '#ffffff', align: 'center', stroke: '#000000', strokeThickness: 4, wordWrap: { width: 800 } }); this.subtitleText.setOrigin(0.5); this.subtitleText.setAlpha(0); this.uiLayer.add(this.subtitleText); // Skip hint const skipText = this.add.text(width - 20, 20, 'Press ESC to skip', { fontSize: '14px', color: '#888888' }); skipText.setOrigin(1, 0); this.uiLayer.add(skipText); // ESC to skip this.input.keyboard.on('keydown-ESC', () => this.skipIntro()); // Start intro sequence this.startIntroSequence(); } startIntroSequence() { console.log('🎬 Phase 1: Black Screen + Heavy Breathing'); // PHASE 1: Black Screen + Breathing (0:00 - 0:10) this.showSubtitle("Everything is dark... why do I only hear silence?"); this.showSubtitle("Everything is dark... why do I only hear silence?"); const breathingSound = this.playAudioSafe('voice_breathing'); // Fade to cellar after breathing + 2s breathingSound.once('complete', () => { this.time.delayedCall(2000, () => this.phase2_Flyover()); }); } phase2_Flyover() { console.log('🎬 Phase 2: Narrator Flyover'); // PHASE 2: Narrator + Biome Flyover (0:10 - 1:00) this.clearSubtitle(); // Fade black to slight transparency (show void) this.tweens.add({ targets: this.blackScreen, alpha: 0.3, duration: 3000, ease: 'Sine.easeInOut' }); const flyoverVoice = this.playAudioSafe('voice_flyover'); // Show subtitle this.time.delayedCall(500, () => { this.showSubtitle("They say the world didn't die with a bang... but with a quiet whisper."); }); this.time.delayedCall(8000, () => { this.showSubtitle("The Valley of Death is not just a place. It's a memory that no one wants to have anymore."); }); // After flyover, go to awakening flyoverVoice.once('complete', () => { this.time.delayedCall(1000, () => this.phase3_Awakening()); }); } phase3_Awakening() { console.log('🎬 Phase 3: Kai Awakens'); // PHASE 3: Awakening (1:00 - 1:30) this.clearSubtitle(); // Fade in cellar background (blurred) const cellar = this.add.image(this.cameras.main.width / 2, this.cameras.main.height / 2, 'intro_cellar'); cellar.setAlpha(0); this.backgroundLayer.add(cellar); // Blur overlay const blur = this.add.image(this.cameras.main.width / 2, this.cameras.main.height / 2, 'intro_blur'); blur.setAlpha(0); this.backgroundLayer.add(blur); // Fade out black, fade in cellar + blur this.tweens.add({ targets: this.blackScreen, alpha: 0, duration: 2000 }); this.tweens.add({ targets: [cellar, blur], alpha: 1, duration: 3000, ease: 'Sine.easeIn' }); // Play awakening voice this.time.delayedCall(2000, () => { const awakeningVoice = this.playAudioSafe('voice_awakening'); this.showSubtitle("My head... it hurts. Where am I? Who am I...?"); // Clear blur gradually (vision clearing) this.time.delayedCall(3000, () => { this.tweens.add({ targets: blur, alpha: 0, duration: 4000, ease: 'Sine.easeOut' }); }); awakeningVoice.once('complete', () => { this.time.delayedCall(1500, () => this.phase4_IDCard()); }); }); } phase4_IDCard() { console.log('🎬 Phase 4: ID Card Discovery'); // PHASE 4: ID Card (1:30 - 2:30) this.clearSubtitle(); // Show ID card (zoom in effect) const idCard = this.add.image(this.cameras.main.width / 2, this.cameras.main.height / 2, 'intro_id_card'); idCard.setScale(0.5); idCard.setAlpha(0); this.backgroundLayer.add(idCard); this.tweens.add({ targets: idCard, alpha: 1, scale: 1, duration: 2000, ease: 'Cubic.easeOut' }); // Play truth voice this.time.delayedCall(1500, () => { const truthVoice = this.playAudioSafe('voice_truth'); this.showSubtitle("Kai MarkoviΔ‡. 14 years old. That's me. But this other girl... why do I feel so empty?"); // Show twin photo (cross-fade) this.time.delayedCall(8000, () => { this.showSubtitle("Like I'm missing half of my heart."); // Cross-fade to twin photo const twinPhoto = this.add.image( this.cameras.main.width / 2, this.cameras.main.height / 2, 'intro_twin_photo' ); twinPhoto.setAlpha(0); twinPhoto.setScale(1.2); this.backgroundLayer.add(twinPhoto); // Fade out ID, fade in photo this.tweens.add({ targets: idCard, alpha: 0, duration: 2000 }); this.tweens.add({ targets: twinPhoto, alpha: 1, scale: 1, duration: 3000, ease: 'Sine.easeInOut' }); }); truthVoice.once('complete', () => { this.time.delayedCall(1000, () => this.phase5_Determination()); }); }); } phase5_Determination() { console.log('🎬 Phase 5: Determination + Quest'); // PHASE 5: Determination (2:30 - 3:00) this.clearSubtitle(); const determinationVoice = this.playAudioSafe('voice_determination'); this.showSubtitle("Someone is waiting for me out there. I can't remember the face, but I feel the promise."); this.time.delayedCall(5000, () => { this.showSubtitle("I'm coming to find you... Ana."); // Quest trigger flash this.cameras.main.flash(1000, 100, 50, 50); }); determinationVoice.once('complete', () => { // Show quest notification this.showQuestNotification(); // Fade to game after 3s this.time.delayedCall(3000, () => this.endIntro()); }); } showQuestNotification() { const { width, height } = this.cameras.main; // Quest panel const questPanel = this.add.rectangle(width / 2, height / 2, 600, 200, 0x1a1a1a, 0.95); questPanel.setStrokeStyle(4, 0xffaa00); const questTitle = this.add.text(width / 2, height / 2 - 40, 'πŸ“œ NEW QUEST', { fontSize: '32px', fontFamily: 'Georgia, serif', color: '#ffaa00', fontStyle: 'bold' }); questTitle.setOrigin(0.5); const questText = this.add.text(width / 2, height / 2 + 20, 'Find clues about your past', { fontSize: '20px', fontFamily: 'Georgia, serif', color: '#ffffff' }); questText.setOrigin(0.5); this.uiLayer.add([questPanel, questTitle, questText]); // Pulse animation this.tweens.add({ targets: [questPanel, questTitle, questText], alpha: { from: 0, to: 1 }, scale: { from: 0.8, to: 1 }, duration: 800, ease: 'Back.easeOut' }); } showSubtitle(text) { this.subtitleText.setText(text); this.tweens.add({ targets: this.subtitleText, alpha: 1, duration: 500 }); } clearSubtitle() { this.tweens.add({ targets: this.subtitleText, alpha: 0, duration: 500, onComplete: () => this.subtitleText.setText('') }); } skipIntro() { console.log('⏭️ Skipping intro...'); this.endIntro(); } playAudioSafe(key, config = {}) { try { if (this.cache.audio.exists(key)) { const sound = this.sound.add(key, config); sound.play(); return sound; } else { console.warn(`⚠️ Audio key missing: ${key}`); // Return dummy object with 'once' method to prevent crashes on event listeners return { once: (event, callback) => { // Simulate immediate completion if (event === 'complete') callback(); }, stop: () => { }, play: () => { } }; } } catch (e) { console.error(`❌ Audio error for ${key}:`, e); return { once: (e, cb) => { if (e === 'complete') cb(); }, stop: () => { }, play: () => { } }; } } endIntro() { console.log('🎬 Intro complete! Launching GameScene...'); // Fade out music this.tweens.add({ targets: this.noirMusic, volume: 0, duration: 2000, onComplete: () => this.noirMusic.stop() }); // Fade to black this.cameras.main.fadeOut(2000, 0, 0, 0); this.cameras.main.once('camerafadeoutcomplete', () => { this.scene.start('GameScene'); }); } }