🎨 INTRO POLISHED - Polaroid + VHS effects!

 POLAROID AESTHETIC:
- 65% screen size with white beige frame
- Floating animation (5px up/down)
- Dirty grain texture on frame
- Glitch-out transitions with chromatic aberration

 VHS RETRO EFFECTS:
- Scanline overlay (every 4px)
- VHS noise flicker animation
- Chromatic aberration on transitions

 READY TO TEST!
Audio placeholders added but will not crash if missing.

Run game to see polished intro!
This commit is contained in:
2026-01-10 13:31:47 +01:00
parent 13fc18bc9e
commit 5a1ede6ca7

View File

@@ -10,7 +10,12 @@ class IntroScene extends Phaser.Scene {
this.currentPhase = 0; this.currentPhase = 0;
this.skipPrompt = null; this.skipPrompt = null;
this.currentShot = null; this.currentShot = null;
this.currentMusic = null; this.currentPolaroid = null;
this.currentText = null;
this.vhsNoise = null;
this.scanlines = null;
this.ambientAudio = null;
this.projectorAudio = null;
} }
preload() { preload() {
@@ -37,10 +42,14 @@ class IntroScene extends Phaser.Scene {
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_gronk', introPath + 'gronk_doorway_silhouette.png'); this.load.image('intro_gronk', introPath + 'gronk_doorway_silhouette.png');
// Optional: Audio files (placeholder paths - not loaded yet) // 🎵 AUDIO (Optional - with safe loading)
// this.load.audio('intro_music_happy', 'assets/audio/intro_happy.ogg'); this.loadAudioSafe('noir_ambience', 'assets/audio/ambient/noir_ambience.ogg');
// this.load.audio('intro_music_punk', 'assets/audio/intro_punk.ogg'); this.loadAudioSafe('projector_loop', 'assets/audio/ambient/projector_loop.ogg');
// this.load.audio('intro_music_ambient', 'assets/audio/intro_ambient.ogg');
// Voice triggers (placeholders)
this.loadAudioSafe('audio_kai_memory_01', 'assets/audio/voiceover/kai_memory_01.mp3');
this.loadAudioSafe('audio_kai_memory_02', 'assets/audio/voiceover/kai_memory_02.mp3');
this.loadAudioSafe('audio_kai_memory_03', 'assets/audio/voiceover/kai_memory_03.mp3');
} }
create() { create() {
@@ -406,56 +415,115 @@ class IntroScene extends Phaser.Scene {
const duration = endTime - startTime; const duration = endTime - startTime;
this.time.delayedCall(startTime, () => { this.time.delayedCall(startTime, () => {
if (this.currentShot) { // Fade out previous polaroid
// Fade out previous shot if (this.currentPolaroid) {
this.tweens.add({ this.tweens.add({
targets: this.currentShot, targets: this.currentPolaroid,
alpha: 0, alpha: 0,
duration: 300, duration: 300,
onComplete: () => { onComplete: () => {
if (this.currentShot) this.currentShot.destroy(); if (this.currentPolaroid) {
this.currentPolaroid.frame.destroy();
this.currentPolaroid.photo.destroy();
this.currentPolaroid = null;
}
} }
}); });
} }
// Create new shot // Create photo image (65% of screen)
const shot = this.add.image(width / 2, height / 2, imageKey); const photo = this.add.image(width / 2, height / 2 - 30, imageKey);
shot.setAlpha(options.fadeIn ? 0 : 1); photo.setAlpha(options.fadeIn ? 0 : 1);
shot.setDepth(10); photo.setDepth(20);
// Scale to fit screen // Scale to 65% of screen size
const scaleX = width / shot.width; const targetSize = Math.min(width, height) * 0.65;
const scaleY = height / shot.height; const photoScale = targetSize / Math.max(photo.width, photo.height);
const scale = Math.max(scaleX, scaleY); photo.setScale(photoScale);
shot.setScale(scale);
this.currentShot = shot; // Create Polaroid white frame
const frameWidth = photo.displayWidth + 40; // 20px padding each side
const frameHeight = photo.displayHeight + 80; // 20px top, 60px bottom (Polaroid style!)
// Apply visual effects const frame = this.add.graphics();
frame.setDepth(19);
// Dirty white Polaroid background
frame.fillStyle(0xf5f5dc, 1); // Beige white
frame.fillRect(
(width - frameWidth) / 2,
(height - frameHeight) / 2 - 30,
frameWidth,
frameHeight
);
// Add subtle dirt/grain texture
for (let i = 0; i < 50; i++) {
const x = (width - frameWidth) / 2 + Math.random() * frameWidth;
const y = (height - frameHeight) / 2 - 30 + Math.random() * frameHeight;
frame.fillStyle(0xccccbb, 0.3);
frame.fillCircle(x, y, 1);
}
this.currentPolaroid = { photo, frame };
// 🌊 FLOATING ANIMATION (5px up/down)
this.tweens.add({
targets: [photo, frame],
y: '-=5',
duration: 2000,
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut'
});
// Apply visual effects to photo
if (options.warm) { if (options.warm) {
shot.setTint(0xffddaa); // Warm nostalgic tint photo.setTint(0xffddaa); // Warm nostalgic tint
} }
if (options.red) { if (options.red) {
shot.setTint(0xff6666); // Red danger tint photo.setTint(0xff6666); // Red danger tint
} }
if (options.toxic) { if (options.toxic) {
shot.setTint(0x66ff66); // Green toxic tint photo.setTint(0x66ff66); // Green toxic tint
} }
if (options.fadeIn) { // 2 SECOND FADE-IN
if (options.fadeIn !== false) {
this.tweens.add({ this.tweens.add({
targets: shot, targets: [photo, frame],
alpha: 1, alpha: { from: 0, to: 1 },
duration: 1500 duration: 2000,
ease: 'Power2.easeOut'
}); });
} }
// GLITCH-OUT transition for next shot
this.time.delayedCall(duration - 500, () => {
if (this.currentPolaroid) {
// Glitch effect before fade
this.tweens.add({
targets: [photo, frame],
x: { from: photo.x - 10, to: photo.x + 10 },
duration: 50,
repeat: 5,
yoyo: true,
onComplete: () => {
// Chromatic aberration effect
photo.setTint(0xff0000);
this.time.delayedCall(50, () => photo.setTint(0x00ff00));
this.time.delayedCall(100, () => photo.setTint(0x0000ff));
}
});
}
});
if (options.glitch) { if (options.glitch) {
// Simple glitch effect - position jitter // Extra glitch during display
this.tweens.add({ this.tweens.add({
targets: shot, targets: [photo, frame],
x: { from: width / 2 - 5, to: width / 2 + 5 }, x: { from: width / 2 - 5, to: width / 2 + 5 },
duration: 100, duration: 100,
repeat: duration / 100, repeat: duration / 100,
@@ -466,7 +534,7 @@ class IntroScene extends Phaser.Scene {
if (options.strobe) { if (options.strobe) {
// Strobe effect // Strobe effect
this.tweens.add({ this.tweens.add({
targets: shot, targets: photo,
alpha: { from: 0.7, to: 1.0 }, alpha: { from: 0.7, to: 1.0 },
duration: 150, duration: 150,
repeat: duration / 150, repeat: duration / 150,