🎬🔥 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:
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user