diff --git a/.DS_Store b/.DS_Store index 81d3f4311..0b27ba02e 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/DEV_LOG.md b/DEV_LOG.md index 207911454..b169db5ce 100644 --- a/DEV_LOG.md +++ b/DEV_LOG.md @@ -41,3 +41,14 @@ Posodobili smo dokument `docs/GAME_DESIGN_NOTES.md` z naslednjimi koncepti: * 10-Fazna struktura izdajanja. * **Licence Preverjene:** Najdene so v (Apache, MIT, BSD), kar je pričakovano za Python knjižnice. * **Koda in Dokumentacija:** Vse posodobljeno in pripravljeno na vnos referenc. + +### 5. Priprava Assetov za Fazo 1 (25.01.2026 13:36 CET) +* **Referenčne slike:** Vse prekopirane v (132 datotek). +* **Obdelava:** + * Konvertirano v PNG. + * *Intelligent Resize* (Gronk 512px, Kai 256px, Insekti 96px). + * *Sharpening* (LANCZOS + Unsharp Mask). + * Ohranjena originalna ozadja. +* **Struktura:** + * Ustvarjena mapa . + * Izbrisane stare neurejene podmape. diff --git a/assets/.DS_Store b/assets/.DS_Store index 881faca91..c67c5ee8d 100644 Binary files a/assets/.DS_Store and b/assets/.DS_Store differ diff --git a/assets/DEMO_FAZA1/drevo_faza_1.png b/assets/DEMO_FAZA1/drevo_faza_1.png new file mode 100644 index 000000000..9e0800035 Binary files /dev/null and b/assets/DEMO_FAZA1/drevo_faza_1.png differ diff --git a/assets/DEMO_FAZA1/drevo_faza_2.png b/assets/DEMO_FAZA1/drevo_faza_2.png new file mode 100644 index 000000000..e8edbff71 Binary files /dev/null and b/assets/DEMO_FAZA1/drevo_faza_2.png differ diff --git a/assets/DEMO_FAZA1/drevo_majhno.png b/assets/DEMO_FAZA1/drevo_majhno.png new file mode 100644 index 000000000..16e46e68d Binary files /dev/null and b/assets/DEMO_FAZA1/drevo_majhno.png differ diff --git a/assets/DEMO_FAZA1/drevo_srednje.png b/assets/DEMO_FAZA1/drevo_srednje.png new file mode 100644 index 000000000..596cff695 Binary files /dev/null and b/assets/DEMO_FAZA1/drevo_srednje.png differ diff --git a/assets/DEMO_FAZA1/drevo_veliko.png b/assets/DEMO_FAZA1/drevo_veliko.png new file mode 100644 index 000000000..f388f3118 Binary files /dev/null and b/assets/DEMO_FAZA1/drevo_veliko.png differ diff --git a/assets/DEMO_FAZA1/megla_ozadje.png b/assets/DEMO_FAZA1/megla_ozadje.png new file mode 100644 index 000000000..ff2b372d8 Binary files /dev/null and b/assets/DEMO_FAZA1/megla_ozadje.png differ diff --git a/assets/DEMO_FAZA1/suho_drevo.png b/assets/DEMO_FAZA1/suho_drevo.png new file mode 100644 index 000000000..6d1c20ac6 Binary files /dev/null and b/assets/DEMO_FAZA1/suho_drevo.png differ diff --git a/assets/DEMO_FAZA1/tla_trava_tekstura.png b/assets/DEMO_FAZA1/tla_trava_tekstura.png new file mode 100644 index 000000000..26f154453 Binary files /dev/null and b/assets/DEMO_FAZA1/tla_trava_tekstura.png differ diff --git a/assets/DEMO_FAZA1/trava_sop.png b/assets/DEMO_FAZA1/trava_sop.png new file mode 100644 index 000000000..eb97bfab5 Binary files /dev/null and b/assets/DEMO_FAZA1/trava_sop.png differ diff --git a/assets/DEMO_FAZA1/visoka_trava.png b/assets/DEMO_FAZA1/visoka_trava.png new file mode 100644 index 000000000..ea80f95ac Binary files /dev/null and b/assets/DEMO_FAZA1/visoka_trava.png differ diff --git a/src/scenes/GrassScene.js b/src/scenes/GrassScene.js index 4a1d794d1..adfeeb066 100644 --- a/src/scenes/GrassScene.js +++ b/src/scenes/GrassScene.js @@ -1,267 +1,144 @@ export default class GrassScene extends Phaser.Scene { constructor() { super({ key: 'GrassScene' }); - this.currentZoom = 1.0; - this.targetZoom = 1.0; + this.baseTime = 12; // Start at 12:00 (Noon) + this.timeSpeed = 0.5; // How fast time passes } preload() { - console.log("🌲 Loading Interactive Forest..."); + console.log("🌿 Loading Environment assets..."); - // TERRAIN - this.load.image('grass', 'assets/slike/environment/trava .png'); - this.load.image('dirt_path', 'assets/slike/nova mapa faza 0-1/Environment/podlaga/dirt_path.png'); - this.load.image('tall_grass', 'assets/slike/environment/tall_grass.png'); + // Load assets from DEMO_FAZA1 + this.load.image('ground_dead', 'assets/DEMO_FAZA1/tla_trava_tekstura.png'); + this.load.image('grass_tall', 'assets/DEMO_FAZA1/visoka_trava.png'); + this.load.image('grass_tuft', 'assets/DEMO_FAZA1/trava_sop.png'); - // CAMP - Cleaned PNG files (256px) - this.load.image('tent', 'assets/slike/nova mapa faza 0-1/Environment/stavbe/MOJE_SLIKE_KONCNA_ostalo_tent_basic_style32.png'); - this.load.image('campfire', 'assets/slike/nova mapa faza 0-1/Environment/props/MOJE_SLIKE_KONCNA_ostalo_campfire_frame1.png'); + // Trees (Growth Stages) + this.load.image('tree_small', 'assets/DEMO_FAZA1/drevo_majhno.png'); + this.load.image('tree_medium', 'assets/DEMO_FAZA1/drevo_srednje.png'); + this.load.image('tree_large', 'assets/DEMO_FAZA1/drevo_veliko.png'); + this.load.image('tree_dead', 'assets/DEMO_FAZA1/suho_drevo.png'); - // NATURE - Cleaned PNG trees (512px) from narava subfolder - this.load.image('dead_tree', 'assets/slike/nova mapa faza 0-1/Environment/narava/unnamed.png'); - this.load.image('bush', 'assets/slike/nova mapa faza 0-1/Environment/narava/MOJE_SLIKE_KONCNA_okolje_bush_green.png'); - this.load.image('rock_small', 'assets/slike/nova mapa faza 0-1/Environment/narava/MOJE_SLIKE_KONCNA_okolje_biomi_gore_rock_small_style32.png'); - this.load.image('rock_medium', 'assets/slike/nova mapa faza 0-1/Environment/narava/MOJE_SLIKE_KONCNA_okolje_biomi_gore_rock_medium_style32.png'); + // Weather + this.load.image('fog', 'assets/DEMO_FAZA1/megla_ozadje.png'); - // PROPS - Cleaned PNG (256px) - this.load.image('wood_log', 'assets/slike/nova mapa faza 0-1/Environment/props/wood_log.png'); - this.load.image('broken_board', 'assets/slike/nova mapa faza 0-1/UI/icon_longboard.png'); - - // CHARACTER - this.load.image('kai', 'assets/slike/characters/kai_idle_west_2_styleA_1024x1024.png'); + // GLSL Wind Shader (Inline for simplicity) + this.windPipeline = null; // Will create in create() } create() { - console.log("🏕️ Building Interactive Forest..."); - const { width, height } = this.cameras.main; + const { width, height } = this.scale; - // Store all objects for DOF effect - this.backgroundObjects = []; - this.foregroundObjects = []; + // 1. DEAD GROUND (Tiling background) + // Uses the 'dead' texture as the base canvas + this.ground = this.add.tileSprite(0, 0, width, height, 'ground_dead').setOrigin(0, 0); - // --- LAYER 0: GRASS BACKGROUND --- - const grass = this.add.tileSprite(0, 0, width, height, 'grass').setOrigin(0, 0); - grass.setDepth(0); + // 2. VEGETATION GROUPS + this.trees = []; + this.grasses = []; - // --- 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)); - } + // 3. GENERATE WORLD (Procedural placement) + this.generateVegetation(width, height); - // --- 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); + // 4. WEATHER LAYERS (Fog) + this.fog1 = this.add.tileSprite(0, 0, width, height, 'fog').setOrigin(0, 0).setAlpha(0.2).setBlendMode(Phaser.BlendModes.ADD); + this.fog2 = this.add.tileSprite(0, 0, width, height, 'fog').setOrigin(0, 0).setAlpha(0.15).setBlendMode(Phaser.BlendModes.ADD); - 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); + // 5. LIGHTING / DAY-NIGHT OVERLAY + this.dayNightOverlay = this.add.rectangle(0, 0, width, height, 0x000000, 0).setOrigin(0, 0).setDepth(1000); - // --- 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); - - const virusGlow2 = this.add.circle(width / 2 + 530, height / 2 + 200, 70, 0x00ff00, 0.2); - virusGlow2.setDepth(3); - virusGlow2.setBlendMode(Phaser.BlendModes.ADD); - - const virusGlow3 = this.add.circle(width / 2 + 650, height / 2 + 50, 60, 0x00ff00, 0.18); - virusGlow3.setDepth(3); - virusGlow3.setBlendMode(Phaser.BlendModes.ADD); - - 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: '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!"); + // UI Info + this.infoText = this.add.text(10, 10, 'Time: 12:00', { font: '16px monospace', fill: '#fff' }).setDepth(2000); } - 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); + generateVegetation(w, h) { + // Randomly place HIGH GRASS (for cutting/hiding) + for (let i = 0; i < 50; i++) { + let x = Phaser.Math.Between(50, w - 50); + let y = Phaser.Math.Between(50, h - 50); - // 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)); - }); + // Swaying tall grass + let grass = this.add.image(x, y, 'grass_tall'); + grass.setScale(0.15 + (Math.random() * 0.1)); // Random size + grass.setDepth(y); // Y-sort + grass.setOrigin(0.5, 1); // Anchor at bottom + grass.swaySpeed = 0.002 + (Math.random() * 0.002); + grass.swayOffset = Math.random() * 100; + this.grasses.push(grass); } + + // Randomly place TREES + for (let i = 0; i < 15; i++) { + let x = Phaser.Math.Between(50, w - 50); + let y = Phaser.Math.Between(50, h - 50); + let type = Phaser.Math.RND.pick(['tree_small', 'tree_medium', 'tree_large', 'tree_dead']); + + let tree = this.add.image(x, y, type); + // Size adjustments based on type + if (type === 'tree_large') tree.setScale(0.8); + else if (type === 'tree_medium') tree.setScale(0.6); + else tree.setScale(0.5); + + tree.setDepth(y); + tree.setOrigin(0.5, 0.95); // Anchor near bottom + tree.swaySpeed = 0.001 + (Math.random() * 0.001); // Slower sway for trees + tree.swayOffset = Math.random() * 100; + this.trees.push(tree); + } + } + + update(time, delta) { + // --- 1. WIND ANIMATION (Manual Vertex Sway Simulation) --- + // Since we aren't using a complex shader pipeline yet, we use rotation/skew + + this.grasses.forEach(g => { + // Simple sway using Sine wave + g.rotation = Math.sin((time * g.swaySpeed) + g.swayOffset) * 0.1; // +/- 0.1 radians + }); + + this.trees.forEach(t => { + // Trees sway less + t.rotation = Math.sin((time * t.swaySpeed) + t.swayOffset) * 0.03; + }); + + // --- 2. FOG MOVEMENT --- + this.fog1.tilePositionX += 0.5; + this.fog2.tilePositionX += 0.2; + this.fog2.tilePositionY += 0.1; + + // --- 3. DAY/NIGHT CYCLE --- + this.baseTime += (delta * 0.001 * this.timeSpeed); // Simulated hours + if (this.baseTime >= 24) this.baseTime = 0; + + this.updateLighting(this.baseTime); + this.infoText.setText(`Time: ${Math.floor(this.baseTime)}:${Math.floor((this.baseTime % 1) * 60).toString().padStart(2, '0')}`); + } + + updateLighting(hour) { + // Simple ambient light logic + let alpha = 0; + let color = 0x000000; // Darkness color + + if (hour >= 6 && hour < 12) { + // Sunrise -> Noon (Brightening) + alpha = Phaser.Math.Interpolation.Linear([0.6, 0.0], (hour - 6) / 6); + color = 0xffaa00; // Orange tint for sunrise + } + else if (hour >= 12 && hour < 18) { + // Noon -> Sunset (Normal) + alpha = 0; + } + else if (hour >= 18 && hour < 21) { + // Sunset -> Night (Darkening) + alpha = Phaser.Math.Interpolation.Linear([0.0, 0.5], (hour - 18) / 3); + color = 0x330066; // Purple evening tint + } + else { + // Night (Dark) + alpha = 0.7; // 70% darkness + color = 0x000022; // Deep blue night + } + + this.dayNightOverlay.setFillStyle(color, alpha); } } diff --git a/web/index.html b/web/index.html index 88939e859..adcc9696a 100644 --- a/web/index.html +++ b/web/index.html @@ -10,8 +10,8 @@
- + - +