Add generated VibeVoice audio assets, dialogue JSON, and updated PrologueScene
This commit is contained in:
@@ -30,17 +30,41 @@ class PrologueScene extends Phaser.Scene {
|
||||
this.autoAdvanceDelay = 3000; // 3 seconds
|
||||
}
|
||||
|
||||
preload() {
|
||||
this.load.json('prologue_data', 'assets/dialogue/prologue.json');
|
||||
|
||||
// Dynamically load audio based on JSON content
|
||||
this.load.on('filecomplete-json-prologue_data', (key, type, data) => {
|
||||
if (Array.isArray(data)) {
|
||||
data.forEach(line => {
|
||||
if (line.id) {
|
||||
// Assuming .wav format as generated by our script
|
||||
this.load.audio(line.id, `assets/audio/voiceover/prologue/${line.id}.wav`);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
create() {
|
||||
const width = this.cameras.main.width;
|
||||
const height = this.cameras.main.height;
|
||||
|
||||
console.log('🎬 Starting Prologue...');
|
||||
|
||||
// Track current audio to stop it when advancing
|
||||
this.currentVoice = null;
|
||||
|
||||
// Black background
|
||||
this.add.rectangle(0, 0, width, height, 0x000000).setOrigin(0);
|
||||
|
||||
// Initialize dialogue data
|
||||
this.dialogueData = this.createDialogueData();
|
||||
// Initialize dialogue data from JSON
|
||||
this.dialogueData = this.cache.json.get('prologue_data');
|
||||
|
||||
if (!this.dialogueData) {
|
||||
console.error('❌ Failed to load prologue dialogue data!');
|
||||
this.dialogueData = [];
|
||||
}
|
||||
|
||||
// Create UI elements
|
||||
this.createDialogueUI(width, height);
|
||||
@@ -83,157 +107,6 @@ class PrologueScene extends Phaser.Scene {
|
||||
this.showDialogue(0);
|
||||
}
|
||||
|
||||
createDialogueData() {
|
||||
return [
|
||||
// ACT 1: THE OUTBREAK
|
||||
{
|
||||
background: 'lab',
|
||||
speaker: 'Narrator',
|
||||
portrait: null,
|
||||
text: '2084. Nova Lab, Slovenia.\nThe world\'s last hope against the zombie virus...',
|
||||
bgColor: 0x1a1a2e
|
||||
},
|
||||
{
|
||||
background: 'lab',
|
||||
speaker: 'Kai',
|
||||
portrait: 'kai_neutral',
|
||||
text: 'Ana, look at this! The Alfa strain is reacting to our blood samples!',
|
||||
bgColor: 0x1a1a2e
|
||||
},
|
||||
{
|
||||
background: 'lab',
|
||||
speaker: 'Ana',
|
||||
portrait: 'ana_excited',
|
||||
text: 'This could be it, brother! A cure that doesn\'t just kill the virus...\nit transforms it!',
|
||||
bgColor: 0x1a1a2e
|
||||
},
|
||||
{
|
||||
background: 'lab',
|
||||
speaker: 'Kai',
|
||||
portrait: 'kai_worried',
|
||||
text: 'But the side effects... subjects gain control over zombies.\nIs that even ethical?',
|
||||
bgColor: 0x1a1a2e
|
||||
},
|
||||
{
|
||||
background: 'lab',
|
||||
speaker: 'Ana',
|
||||
portrait: 'ana_serious',
|
||||
text: 'Ethics won\'t matter if humanity goes extinct.\nWe need to test this NOW.',
|
||||
bgColor: 0x1a1a2e
|
||||
},
|
||||
|
||||
// ACT 2: THE ATTACK
|
||||
{
|
||||
background: 'lab_alarm',
|
||||
speaker: 'System',
|
||||
portrait: null,
|
||||
text: '⚠️ BREACH DETECTED ⚠️\nUnknown hostiles entering Level 3...',
|
||||
bgColor: 0x330000,
|
||||
shake: true
|
||||
},
|
||||
{
|
||||
background: 'lab_alarm',
|
||||
speaker: 'Kai',
|
||||
portrait: 'kai_shocked',
|
||||
text: 'Ana, get to the safe room! I\'ll secure the samples!',
|
||||
bgColor: 0x330000,
|
||||
shake: true
|
||||
},
|
||||
{
|
||||
background: 'lab_chaos',
|
||||
speaker: 'Ana',
|
||||
portrait: 'ana_determined',
|
||||
text: 'No! We inject each other with Alfa NOW!\nIt\'s our only chance!',
|
||||
bgColor: 0x220000,
|
||||
shake: true
|
||||
},
|
||||
{
|
||||
background: 'lab_chaos',
|
||||
speaker: 'Narrator',
|
||||
portrait: null,
|
||||
text: 'In a desperate moment, the twins inject themselves with the untested Alfa virus...',
|
||||
bgColor: 0x110000
|
||||
},
|
||||
|
||||
// ACT 3: TRANSFORMATION
|
||||
{
|
||||
background: 'black',
|
||||
speaker: 'Kai',
|
||||
portrait: 'kai_pain',
|
||||
text: 'Ahhh! It burns! Ana, I can feel... everything!\nEvery zombie in the building!',
|
||||
bgColor: 0x000000,
|
||||
shake: true
|
||||
},
|
||||
{
|
||||
background: 'black',
|
||||
speaker: 'Ana',
|
||||
portrait: 'ana_pain',
|
||||
text: 'Brother! The connection... I can hear them too!\nWe\'re becoming... ALFA!',
|
||||
bgColor: 0x000000,
|
||||
shake: true
|
||||
},
|
||||
{
|
||||
background: 'black',
|
||||
speaker: 'Narrator',
|
||||
portrait: null,
|
||||
text: 'An explosion. Darkness. Then... silence.',
|
||||
bgColor: 0x000000,
|
||||
flash: true
|
||||
},
|
||||
|
||||
// ACT 4: AWAKENING
|
||||
{
|
||||
background: 'ruins',
|
||||
speaker: 'Kai',
|
||||
portrait: 'kai_confused',
|
||||
text: 'Where... where am I?\nAna? ANA!',
|
||||
bgColor: 0x2d1b00
|
||||
},
|
||||
{
|
||||
background: 'ruins',
|
||||
speaker: 'Kai',
|
||||
portrait: 'kai_determined',
|
||||
text: 'She\'s gone. They took her.\nBut I can still feel her... through the Twin Bond.',
|
||||
bgColor: 0x2d1b00
|
||||
},
|
||||
{
|
||||
background: 'ruins',
|
||||
speaker: 'Kai',
|
||||
portrait: 'kai_anger',
|
||||
text: 'Whoever did this... I WILL find you.\nAnd my new "friends" will help me.',
|
||||
bgColor: 0x2d1b00
|
||||
},
|
||||
{
|
||||
background: 'zombies',
|
||||
speaker: 'Narrator',
|
||||
portrait: null,
|
||||
text: 'Three zombies approach. But instead of attacking...\nthey kneel before Kai.',
|
||||
bgColor: 0x1a4d1a
|
||||
},
|
||||
{
|
||||
background: 'zombies',
|
||||
speaker: 'Kai',
|
||||
portrait: 'kai_realization',
|
||||
text: 'I am... Alfa.\nAnd they are mine to command.',
|
||||
bgColor: 0x1a4d1a
|
||||
},
|
||||
{
|
||||
background: 'farm',
|
||||
speaker: 'Narrator',
|
||||
portrait: null,
|
||||
text: 'And so begins the journey of Kai...\nZombie master. Brother. ALFA.',
|
||||
bgColor: 0x2d5016
|
||||
},
|
||||
{
|
||||
background: 'farm',
|
||||
speaker: 'Narrator',
|
||||
portrait: null,
|
||||
text: 'BUILD your farm. COMMAND your undead.\nSEARCH for Ana.\n\nThis is... KRVAVA ŽETEV.',
|
||||
bgColor: 0x2d5016
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
createDialogueUI(width, height) {
|
||||
const dialogueBoxHeight = 180;
|
||||
const dialogueY = height - dialogueBoxHeight;
|
||||
@@ -305,6 +178,27 @@ class PrologueScene extends Phaser.Scene {
|
||||
|
||||
const dialogue = this.dialogueData[index];
|
||||
this.currentDialogueIndex = index;
|
||||
|
||||
// Stop previous audio if playing
|
||||
if (this.currentVoice) {
|
||||
this.currentVoice.stop();
|
||||
this.currentVoice = null;
|
||||
}
|
||||
|
||||
// Play new audio
|
||||
if (dialogue.id) {
|
||||
try {
|
||||
// Check if audio exists in cache (it might not if load failed/missing)
|
||||
if (this.cache.audio.exists(dialogue.id)) {
|
||||
this.currentVoice = this.sound.add(dialogue.id);
|
||||
this.currentVoice.play({ volume: 1.0 });
|
||||
} else {
|
||||
console.warn(`🔊 Audio missing for ${dialogue.id}`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Audio play error:', err);
|
||||
}
|
||||
}
|
||||
|
||||
// Update background
|
||||
this.updateBackground(dialogue.background, dialogue.bgColor);
|
||||
@@ -329,17 +223,35 @@ class PrologueScene extends Phaser.Scene {
|
||||
|
||||
// Auto-advance if enabled
|
||||
if (this.autoAdvance && index < this.dialogueData.length - 1) {
|
||||
this.time.delayedCall(this.autoAdvanceDelay, () => {
|
||||
this.advanceDialogue();
|
||||
// Wait for audio to finish OR standard delay?
|
||||
// Ideally wait for audio duration, but fallback to delay
|
||||
let delay = this.autoAdvanceDelay;
|
||||
if (this.currentVoice && this.currentVoice.duration) {
|
||||
// Add a small buffer after speech ends
|
||||
delay = (this.currentVoice.duration * 1000) + 1000;
|
||||
}
|
||||
|
||||
this.time.delayedCall(delay, () => {
|
||||
// Check if user hasn't already advanced manually
|
||||
if (this.currentDialogueIndex === index) {
|
||||
this.advanceDialogue();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
typewriterEffect(text) {
|
||||
let displayText = '';
|
||||
console.log('Typewriter started for:', text); // Debug
|
||||
let charIndex = 0;
|
||||
|
||||
this.dialogueText.setText('');
|
||||
|
||||
// Safety check for empty text
|
||||
if (!text) {
|
||||
this.canAdvance = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const timer = this.time.addEvent({
|
||||
delay: 30, //CharactersperSeconds
|
||||
@@ -447,17 +359,28 @@ class PrologueScene extends Phaser.Scene {
|
||||
this.canAdvance = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Stop current audio before advancing
|
||||
if (this.currentVoice) {
|
||||
this.currentVoice.stop();
|
||||
}
|
||||
|
||||
this.showDialogue(this.currentDialogueIndex + 1);
|
||||
}
|
||||
|
||||
skipPrologue() {
|
||||
console.log('⏭️ Skipping prologue...');
|
||||
if (this.currentVoice) {
|
||||
this.currentVoice.stop();
|
||||
}
|
||||
this.scene.start('GameScene');
|
||||
}
|
||||
|
||||
completePrologue() {
|
||||
console.log('✅ Prologue complete!');
|
||||
if (this.currentVoice) {
|
||||
this.currentVoice.stop();
|
||||
}
|
||||
|
||||
// Fade out
|
||||
this.cameras.main.fadeOut(2000, 0, 0, 0);
|
||||
|
||||
Reference in New Issue
Block a user