Add generated VibeVoice audio assets, dialogue JSON, and updated PrologueScene

This commit is contained in:
2025-12-27 01:56:31 +01:00
parent bec3d8b59a
commit 6a01731de0
26 changed files with 529 additions and 155 deletions

View File

@@ -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);