🎨 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.skipPrompt = 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() {
@@ -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_gronk', introPath + 'gronk_doorway_silhouette.png');
// Optional: Audio files (placeholder paths - not loaded yet)
// this.load.audio('intro_music_happy', 'assets/audio/intro_happy.ogg');
// this.load.audio('intro_music_punk', 'assets/audio/intro_punk.ogg');
// this.load.audio('intro_music_ambient', 'assets/audio/intro_ambient.ogg');
// 🎵 AUDIO (Optional - with safe loading)
this.loadAudioSafe('noir_ambience', 'assets/audio/ambient/noir_ambience.ogg');
this.loadAudioSafe('projector_loop', 'assets/audio/ambient/projector_loop.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() {
@@ -406,56 +415,115 @@ class IntroScene extends Phaser.Scene {
const duration = endTime - startTime;
this.time.delayedCall(startTime, () => {
if (this.currentShot) {
// Fade out previous shot
// Fade out previous polaroid
if (this.currentPolaroid) {
this.tweens.add({
targets: this.currentShot,
targets: this.currentPolaroid,
alpha: 0,
duration: 300,
onComplete: () => {
if (this.currentShot) this.currentShot.destroy();
if (this.currentPolaroid) {
this.currentPolaroid.frame.destroy();
this.currentPolaroid.photo.destroy();
this.currentPolaroid = null;
}
}
});
}
// Create new shot
const shot = this.add.image(width / 2, height / 2, imageKey);
shot.setAlpha(options.fadeIn ? 0 : 1);
shot.setDepth(10);
// Create photo image (65% of screen)
const photo = this.add.image(width / 2, height / 2 - 30, imageKey);
photo.setAlpha(options.fadeIn ? 0 : 1);
photo.setDepth(20);
// Scale to fit screen
const scaleX = width / shot.width;
const scaleY = height / shot.height;
const scale = Math.max(scaleX, scaleY);
shot.setScale(scale);
// Scale to 65% of screen size
const targetSize = Math.min(width, height) * 0.65;
const photoScale = targetSize / Math.max(photo.width, photo.height);
photo.setScale(photoScale);
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) {
shot.setTint(0xffddaa); // Warm nostalgic tint
photo.setTint(0xffddaa); // Warm nostalgic tint
}
if (options.red) {
shot.setTint(0xff6666); // Red danger tint
photo.setTint(0xff6666); // Red danger tint
}
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({
targets: shot,
alpha: 1,
duration: 1500
targets: [photo, frame],
alpha: { from: 0, to: 1 },
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) {
// Simple glitch effect - position jitter
// Extra glitch during display
this.tweens.add({
targets: shot,
targets: [photo, frame],
x: { from: width / 2 - 5, to: width / 2 + 5 },
duration: 100,
repeat: duration / 100,
@@ -466,7 +534,7 @@ class IntroScene extends Phaser.Scene {
if (options.strobe) {
// Strobe effect
this.tweens.add({
targets: shot,
targets: photo,
alpha: { from: 0.7, to: 1.0 },
duration: 150,
repeat: duration / 150,