🌲 Interactive Forest Path Scene - Faza 1 Demo

 Dodane features:
- Interaktivna kamera z mouse wheel zoom (0.5x - 2.5x)
- Dinamična trava z wind sway animacijo (6 šopov)
- Depth of Field efekt pri zoom-u (background fade)
- Virusne infekcije z neon zelenim glow (pulsing)
- Pot v gozd z mrtimi drevesi (tunnel effect)
- Y-sorted layering (9 slojev)

🧹 Asset Cleanup:
- Ultra cleaned 106+ PNG slik v 'nova mapa'
- Odstranjen checkerboard pattern z dreves, skal, trave
- Feathering robov poti za naravno zlitje
- Transparency fix na vseh environment assetih

🎨 Scene Composition:
- Kaijev tabor (šotor + ognjišče)
- Pot s skalami, poleni, razbito longboard
- Grmovje in drevored
- Foreground/midground/background separation

📁 Assets iz: nova mapa/ (Characters, Environment, UI)
🎮 Testno: http://localhost:3000 + mouse wheel zoom
This commit is contained in:
2026-01-21 17:52:07 +01:00
parent 06505bde64
commit 26d689de03
112 changed files with 590 additions and 58 deletions

View File

@@ -1,83 +1,267 @@
export default class GrassScene extends Phaser.Scene {
constructor() {
super({ key: 'GrassScene' });
this.currentZoom = 1.0;
this.targetZoom = 1.0;
}
preload() {
console.log("👻 Loading Haunted Memory Assets...");
console.log("🌲 Loading Interactive Forest...");
// 1. TERRAIN & CHARACTER
this.load.image('grass', 'assets/slike/environment/grass_tile.png');
this.load.image('kai', 'assets/slike/characters/liki_kai_ref_kai.png');
// TERRAIN
this.load.image('grass', 'assets/slike/environment/trava .png');
this.load.image('dirt_path', 'assets/slike/nova mapa /Environment/podlaga/dirt_path.png');
this.load.image('tall_grass', 'assets/slike/environment/tall_grass.png');
// 2. GHOSTS (Memory of Parents)
// Path corrected after rename (Ghost: -> Ghost)
this.load.image('ghost_father', 'assets/slike/NOVE_SLIKE/Characters/starsa/Ghost/ghost_otac_cyan.png');
this.load.image('ghost_parents', 'assets/slike/NOVE_SLIKE/Characters/starsa/Ghost/MOJE_SLIKE_KONCNA_ostalo_parents_transparent_ghosts_clean.png');
// CAMP
this.load.image('tent', 'assets/slike/nova mapa /Environment/stavbe/MOJE_SLIKE_KONCNA_ostalo_tent_basic_style32.png');
this.load.image('campfire', 'assets/slike/nova mapa /Environment/props/MOJE_SLIKE_KONCNA_ostalo_campfire_frame1.png');
// 3. UI ELEMENTS (Rusty Industrial Style)
this.load.image('frame_rusty', 'assets/slike/NOVE_SLIKE/UI/okvir_zarjavel.png');
this.load.image('health_gauge', 'assets/slike/NOVE_SLIKE/UI/merilec_zdravja.png');
this.load.image('amnesia_mask', 'assets/slike/NOVE_SLIKE/UI/amnezija_maska.png');
// NATURE
this.load.image('dead_tree', 'assets/slike/nova mapa /Environment/narava/assets_maps_tilesets_Tree_Dead.png');
this.load.image('bush', 'assets/slike/nova mapa /Environment/narava/MOJE_SLIKE_KONCNA_okolje_bush_green.png');
this.load.image('rock_small', 'assets/slike/nova mapa /Environment/narava/MOJE_SLIKE_KONCNA_okolje_biomi_gore_rock_small_style32.png');
this.load.image('rock_medium', 'assets/slike/nova mapa /Environment/narava/MOJE_SLIKE_KONCNA_okolje_biomi_gore_rock_medium_style32.png');
// PROPS
this.load.image('wood_log', 'assets/slike/nova mapa /Environment/props/wood_log.png');
this.load.image('broken_board', 'assets/slike/nova mapa /UI/icon_longboard.png');
// CHARACTER
this.load.image('kai', 'assets/slike/characters/kai_idle_west_2_styleA_1024x1024.png');
}
create() {
console.log("💀 Reconstructing Memory...");
console.log("🏕️ Building Interactive Forest...");
const { width, height } = this.cameras.main;
const centerX = width / 2;
const centerY = height / 2;
// --- LAYER 0: BACKGROUND ---
// Trava (Depth: 0)
const bg = this.add.tileSprite(0, 0, width, height, 'grass').setOrigin(0, 0);
bg.setTint(0x888888);
bg.setDepth(0);
// Store all objects for DOF effect
this.backgroundObjects = [];
this.foregroundObjects = [];
// --- LAYER 10: CHARACTERS ---
// Father Ghost (Left) - Depth: 10
const father = this.add.image(centerX - 300, centerY, 'ghost_father');
father.setAlpha(0.4);
father.setScale(0.8);
father.setDepth(10);
// --- LAYER 0: GRASS BACKGROUND ---
const grass = this.add.tileSprite(0, 0, width, height, 'grass').setOrigin(0, 0);
grass.setDepth(0);
// Parents Ghost (Right) - Depth: 10
const parents = this.add.image(centerX + 300, centerY, 'ghost_parents');
parents.setAlpha(0.4);
parents.setScale(0.8);
parents.setDepth(10);
// --- LAYER 1: DIRT PATH with FEATHERING ---
for (let i = 0; i < 8; i++) {
const pathX = width / 2 + (i * 120);
const pathY = height / 2 + 100 + (i * 40);
const path = this.add.image(pathX, pathY, 'dirt_path');
path.setScale(0.5);
path.setDepth(1);
path.setAlpha(0.7 + (i * 0.025));
}
// Kai (Center) - Depth: 10
const kai = this.add.image(centerX, centerY, 'kai');
kai.setScale(0.8);
kai.setDepth(10);
// --- LAYER 2: BACKGROUND TREES ---
const bgTree1 = this.add.image(width / 2 + 450, height / 2 - 120, 'dead_tree');
bgTree1.setScale(0.4);
bgTree1.setDepth(2);
bgTree1.setAlpha(0.5);
bgTree1.setTint(0x666666);
this.backgroundObjects.push(bgTree1);
// --- LAYER 100: UI & EFFECTS ---
const bgTree2 = this.add.image(width / 2 + 650, height / 2 + 20, 'dead_tree');
bgTree2.setScale(0.38);
bgTree2.setDepth(2);
bgTree2.setAlpha(0.45);
bgTree2.setTint(0x666666);
this.backgroundObjects.push(bgTree2);
// 1. Amnesia Mask (Full Screen Overlay) - Depth: 100
const mask = this.add.image(centerX, centerY, 'amnesia_mask');
mask.setDisplaySize(width, height); // Stretch to cover FULL screen
mask.setAlpha(0.9);
mask.setDepth(100);
// --- LAYER 3: VIRUS GLOW ---
const virusGlow1 = this.add.circle(width / 2 + 280, height / 2 + 50, 80, 0x00ff00, 0.25);
virusGlow1.setDepth(3);
virusGlow1.setBlendMode(Phaser.BlendModes.ADD);
// 2. Health Gauge (Top Left, Small) - Depth: 100
const gauge = this.add.image(90, 90, 'health_gauge');
gauge.setDisplaySize(150, 150); // Resize to 150x150 as requested
gauge.setDepth(100);
const virusGlow2 = this.add.circle(width / 2 + 530, height / 2 + 200, 70, 0x00ff00, 0.2);
virusGlow2.setDepth(3);
virusGlow2.setBlendMode(Phaser.BlendModes.ADD);
// 3. Rusty Frame (Bottom Center) - Depth: 100
const frameY = height - 100;
const frame = this.add.image(centerX, frameY, 'frame_rusty');
frame.setDepth(100);
const virusGlow3 = this.add.circle(width / 2 + 650, height / 2 + 50, 60, 0x00ff00, 0.18);
virusGlow3.setDepth(3);
virusGlow3.setBlendMode(Phaser.BlendModes.ADD);
// 4. Dialog Text (Centered on Frame) - Depth: 101 (On top of frame)
this.add.text(centerX, frameY, "Kai... se naju spomniš?", {
this.tweens.add({
targets: [virusGlow1, virusGlow2, virusGlow3],
alpha: { from: 0.15, to: 0.35 },
scaleX: { from: 0.85, to: 1.15 },
scaleY: { from: 0.85, to: 1.15 },
duration: 2500,
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut'
});
// --- LAYER 4: CAMP ---
const tent = this.add.image(width / 2 - 300, height / 2 - 50, 'tent');
tent.setScale(0.4);
tent.setDepth(10);
const campfire = this.add.image(width / 2 - 100, height / 2 + 30, 'campfire');
campfire.setScale(0.3);
campfire.setDepth(11);
// --- LAYER 5: PATH DECORATIONS ---
const rock1 = this.add.image(width / 2 + 150, height / 2 + 120, 'rock_small');
rock1.setScale(0.28);
rock1.setDepth(8);
const rock2 = this.add.image(width / 2 + 380, height / 2 + 210, 'rock_medium');
rock2.setScale(0.32);
rock2.setDepth(8);
const rock3 = this.add.image(width / 2 + 520, height / 2 + 260, 'rock_small');
rock3.setScale(0.25);
rock3.setDepth(8);
const log1 = this.add.image(width / 2 + 240, height / 2 + 150, 'wood_log');
log1.setScale(0.22);
log1.setDepth(9);
log1.setAngle(35);
const brokenBoard = this.add.image(width / 2 + 460, height / 2 + 235, 'broken_board');
brokenBoard.setScale(0.08);
brokenBoard.setDepth(9);
brokenBoard.setAngle(-20);
brokenBoard.setTint(0x555555);
// --- LAYER 6: MID-GROUND TREES ---
const tree1 = this.add.image(width / 2 + 280, height / 2 + 20, 'dead_tree');
tree1.setScale(0.55);
tree1.setDepth(13);
tree1.setAngle(-12);
this.backgroundObjects.push(tree1);
const tree2 = this.add.image(width / 2 + 530, height / 2 + 170, 'dead_tree');
tree2.setScale(0.58);
tree2.setDepth(13);
tree2.setAngle(10);
this.backgroundObjects.push(tree2);
// Bushes
const bush1 = this.add.image(width / 2 + 330, height / 2 + 75, 'bush');
bush1.setScale(0.32);
bush1.setDepth(12);
const bush2 = this.add.image(width / 2 + 460, height / 2 + 165, 'bush');
bush2.setScale(0.35);
bush2.setDepth(12);
const bush3 = this.add.image(width / 2 + 590, height / 2 + 240, 'bush');
bush3.setScale(0.3);
bush3.setDepth(12);
// --- LAYER 7: DYNAMIC GRASS TUFTS (wind effect) ---
this.grassTufts = [];
const tuftsPositions = [
{ x: width / 2 + 180, y: height / 2 + 110, delay: 0, duration: 3500 },
{ x: width / 2 + 350, y: height / 2 + 60, delay: 0.5, duration: 4000 },
{ x: width / 2 + 270, y: height / 2 + 180, delay: 1.0, duration: 3200 },
{ x: width / 2 + 490, y: height / 2 + 150, delay: 1.5, duration: 3800 },
{ x: width / 2 + 400, y: height / 2 + 240, delay: 0.8, duration: 3600 },
{ x: width / 2 + 560, y: height / 2 + 220, delay: 1.2, duration: 4200 },
];
tuftsPositions.forEach(pos => {
const tuft = this.add.image(pos.x, pos.y, 'tall_grass');
tuft.setScale(0.12);
tuft.setDepth(16);
tuft.setOrigin(0.5, 1); // Bottom center
// Wind sway animation
this.tweens.add({
targets: tuft,
angle: { from: -3, to: 3 },
duration: pos.duration,
delay: pos.delay * 1000,
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut'
});
this.grassTufts.push(tuft);
});
// --- LAYER 8: FOREGROUND TREE ---
const fgTree1 = this.add.image(width / 2 + 200, height / 2 + 180, 'dead_tree');
fgTree1.setScale(0.7);
fgTree1.setDepth(25);
fgTree1.setAngle(-5);
fgTree1.setAlpha(0.95);
this.foregroundObjects.push(fgTree1);
// --- LAYER 9: KAI (focus point) ---
this.kai = this.add.image(width / 2 + 200, height / 2 + 140, 'kai');
this.kai.setScale(0.16);
this.kai.setDepth(20);
// --- CAMERA SETUP ---
this.cameras.main.setBounds(0, 0, width * 2, height * 2);
this.cameras.main.startFollow(this.kai, false, 0.1, 0.1);
// --- MOUSE WHEEL ZOOM ---
this.input.on('wheel', (pointer, gameObjects, deltaX, deltaY, deltaZ) => {
if (deltaY > 0) {
// Zoom Out
this.targetZoom = Math.max(0.5, this.targetZoom - 0.15);
} else {
// Zoom In
this.targetZoom = Math.min(2.5, this.targetZoom + 0.15);
}
});
// --- UI ---
const uiText = this.add.text(20, 20, "🎮 INTERACTIVE FOREST", {
fontFamily: 'Courier New, monospace',
fontSize: '28px',
color: '#e0e0e0',
fontStyle: 'bold',
stroke: '#000000',
strokeThickness: 5,
shadow: { offsetX: 2, offsetY: 2, color: '#000', blur: 4, fill: true }
}).setOrigin(0.5).setDepth(101);
fontSize: '20px',
color: '#d4af37',
backgroundColor: '#000000',
padding: { x: 10, y: 5 },
fixedToCamera: true
}).setScrollFactor(0).setDepth(100);
const controlsText = this.add.text(20, 55, "🖱️ Mouse Wheel: Zoom In/Out", {
fontFamily: 'Courier New, monospace',
fontSize: '14px',
color: '#ffffff',
backgroundColor: '#000000',
padding: { x: 10, y: 5 }
}).setScrollFactor(0).setDepth(100);
this.zoomText = this.add.text(20, 90, `📷 Zoom: ${this.currentZoom.toFixed(2)}x`, {
fontFamily: 'Courier New, monospace',
fontSize: '14px',
color: '#00ff88',
backgroundColor: '#000000',
padding: { x: 10, y: 5 }
}).setScrollFactor(0).setDepth(100);
console.log("✅ Interactive forest ready! Use mouse wheel to zoom!");
}
update() {
// Smooth zoom transition
if (Math.abs(this.currentZoom - this.targetZoom) > 0.01) {
this.currentZoom = Phaser.Math.Linear(this.currentZoom, this.targetZoom, 0.1);
this.cameras.main.setZoom(this.currentZoom);
// Update zoom text
if (this.zoomText) {
this.zoomText.setText(`📷 Zoom: ${this.currentZoom.toFixed(2)}x`);
}
// Depth of Field effect based on zoom
const dofFactor = Phaser.Math.Clamp((this.currentZoom - 1) / 1.5, 0, 1);
// Blur background when zoomed in
this.backgroundObjects.forEach(obj => {
obj.setAlpha(0.5 - (dofFactor * 0.3)); // Fade out
});
// Slight blur on foreground too
this.foregroundObjects.forEach(obj => {
obj.setAlpha(0.95 - (dofFactor * 0.2));
});
}
}
}