Files
novafarma/src/scenes/GameScene.js
NovaFarma Dev 80bddf5d61 feat: Complete 2D Visual Overhaul - Isometric to Flat Top-Down
- NEW: Flat2DTerrainSystem.js (375 lines)
- NEW: map2d_data.js procedural map (221 lines)
- MODIFIED: GameScene async create, 2D terrain integration
- MODIFIED: Player.js flat 2D positioning
- MODIFIED: game.js disabled pixelArt for smooth rendering
- FIXED: 15+ bugs (updateCulling, isometric conversions, grid lines)
- ADDED: Phase 28 to TASKS.md
- DOCS: DNEVNIK.md session summary

Result: Working flat 2D game with Stardew Valley style!
Time: 5.5 hours
2025-12-14 17:12:40 +01:00

1969 lines
72 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Game Scene - Glavna igralna scena
class GameScene extends Phaser.Scene {
constructor() {
super({ key: 'GameScene' });
this.terrainSystem = null;
this.terrainContainer = null;
this.player = null;
this.npcs = []; // Array za NPCje
// Settings
this.settings = {
viewDistance: 'HIGH', // LOW, MEDIUM, HIGH
particles: 'HIGH', // NONE, LOW, HIGH
shadows: true
};
}
async create() {
console.log('🎮 GameScene: Initialized!');
// Generate procedural textures
new TextureGenerator(this).generateAll();
InventoryIcons.create(this); // Override with flat 2D inventory icons
window.gameState.currentScene = 'GameScene';
window.gameState.gameScene = this; // Reference for global inventory helper
const width = this.cameras.main.width;
const height = this.cameras.main.height;
// Setup kamere - SVETLO SIVO OZADJE!
this.cameras.main.setBackgroundColor('#c8c8c8');
// Initialize Isometric Utils
this.iso = new IsometricUtils();
// Initialize Spatial Grid
this.spatialGrid = new SpatialGrid(10);
// Initialize Concept Systems (Zombie Roots)
this.zombieSystem = new ZombieWorkerSystem(this);
this.legacySystem = new LegacySystem(this);
this.expansionSystem = new ExpansionSystem(this);
this.blueprintSystem = new BlueprintSystem(this);
// Farm Stats Tracking for UI
this.farmStats = {
cropsPlanted: 0,
totalHarvested: 0,
goldEarned: 0,
daysFarmed: 0
};
// PARALLAX BACKGROUND - Clouds & Birds
this.createParallaxBackground();
// Inicializiraj terrain sistem - 100x100 mapa
console.log('🌍 Initializing terrain...');
try {
// 🎲 SEED-BASED GENERATION - Vsak krat ista mapa!
// Preveri če že imaš shranjeno spawn točko
let spawnPoint = localStorage.getItem('novafarma_spawn_point');
let terrainSeed = localStorage.getItem('novafarma_terrain_seed');
if (!terrainSeed) {
// PRVI LOGIN - generiraj nov seed
terrainSeed = Math.random().toString(36).substring(7);
localStorage.setItem('novafarma_terrain_seed', terrainSeed);
console.log('🆕 New world seed:', terrainSeed);
} else {
console.log('♻️ Loading existing world with seed:', terrainSeed);
}
// 🎨 2D FLAT TERRAIN SYSTEM (NEW!)
console.log('🎨 Initializing Flat 2D Terrain...');
this.terrainSystem = new Flat2DTerrainSystem(this);
await this.terrainSystem.generate();
console.log('✅ Flat 2D terrain ready!');
// Initialize Farming System
this.farmingSystem = new FarmingSystem(this);
console.log('🌾 Farming system initialized!');
// Initialize Build System
this.buildSystem = new BuildSystem(this);
console.log('🏗️ Build system initialized!');
// ========================================================
// 🏗️ TESTNI PRIMERI - Postavitev Ograj (ONEMOGOČENO)
// ========================================================
// Odstrani // pred vrsticami, če želiš videti testne ograje!
// ALI pritisni B v igri za Build Mode in postavljaj ročno!
// PRIMER 1: Ena sama ograja
// this.buildSystem.placeSingleFence(50, 50, 'fence_post', false);
// PRIMER 2: Vodoravna linija ograj (10 ograj)
// for (let i = 0; i < 10; i++) {
// this.buildSystem.placeSingleFence(45 + i, 52, 'fence_horizontal', false);
// }
// PRIMER 3: Navpična linija ograj (10 ograj)
// for (let i = 0; i < 10; i++) {
// this.buildSystem.placeSingleFence(43, 48 + i, 'fence_vertical', false);
// }
// PRIMER 4: Majhen pravokotnik (8x6)
// this.buildSystem.placeFenceRectangle(60, 45, 8, 6, 'fence_post', false);
// PRIMER 5: Diagonalna linija (Bresenham)
// this.buildSystem.placeFenceLine(30, 30, 40, 40, 'fence_corner', false);
// PRIMER 6: Večji pravokotnik (20x15)
// this.buildSystem.placeFenceRectangle(20, 60, 20, 15, 'fence_horizontal', false);
// PRIMER 7: Različni tipi ograj v vrsti
// this.buildSystem.placeSingleFence(70, 50, 'fence', false);
// this.buildSystem.placeSingleFence(71, 50, 'fence_post', false);
// this.buildSystem.placeSingleFence(72, 50, 'fence_horizontal', false);
// this.buildSystem.placeSingleFence(73, 50, 'fence_vertical', false);
// this.buildSystem.placeSingleFence(74, 50, 'fence_corner', false);
// console.log('✅ Testne ograje postavljene! Preveri mapo.');
// ========================================================
// Terrain offset
this.terrainOffsetX = width / 2;
this.terrainOffsetY = 100;
// Initialization for culling
this.terrainSystem.init(this.terrainOffsetX, this.terrainOffsetY);
// Initial force update to render active tiles before first frame
this.terrainSystem.updateCulling(this.cameras.main);
// 🎲 RANDOM SPAWN POINT + 8x8 FARM (Prvi login)
if (!spawnPoint) {
// PRVI LOGIN - Random spawn točka
const spawnX = Math.floor(Math.random() * 80) + 10; // 10-90
const spawnY = Math.floor(Math.random() * 80) + 10; // 10-90
spawnPoint = `${spawnX},${spawnY}`;
localStorage.setItem('novafarma_spawn_point', spawnPoint);
console.log(`🎲 First login - Random spawn at (${spawnX}, ${spawnY})`);
console.log(`🏡 Creating 8x8 starter farm at spawn location...`);
// Ustvari 8x8 farmo na spawn točki
this.initializeFarmWorld(spawnX, spawnY);
} else {
// NI PRVI LOGIN - Naloži obstoječo spawn točko
const [spawnX, spawnY] = spawnPoint.split(',').map(Number);
console.log(`♻️ Returning player - spawn at (${spawnX}, ${spawnY})`);
// Obnovi farmo (če je shranjena)
this.initializeFarmWorld(spawnX, spawnY);
}
// 🍎 SADOVNJAK - Sadna Drevesa (ONEMOGOČENO)
// ========================================================
// Odstrani // če želiš sadovnjak
/*
console.log('🍎 Ustvarjam sadovnjak...');
const orchardX = 35; // Lokacija sadovnjaka
const orchardY = 60;
const orchardSize = 10; // 10x10 območje
// 1. Očisti območje (odstrani obstoječe drevese)
for (let x = orchardX; x < orchardX + orchardSize; x++) {
for (let y = orchardY; y < orchardY + orchardSize; y++) {
if (x >= 0 && x < 100 && y >= 0 && y < 100) {
const key = `${x},${y}`;
if (this.terrainSystem.decorationsMap.has(key)) {
this.terrainSystem.removeDecoration(x, y);
}
// Spremeni teren v travo
if (this.terrainSystem.tiles[y] && this.terrainSystem.tiles[y][x]) {
this.terrainSystem.tiles[y][x].type = 'grass';
if (this.terrainSystem.tiles[y][x].sprite) {
this.terrainSystem.tiles[y][x].sprite.setTexture('grass');
this.terrainSystem.tiles[y][x].sprite.clearTint();
}
}
}
}
}
// 2. Dodaj SADIKE (tree_sapling) - bodo rasle v sadna drevesa!
const fruitTreeTypes = ['tree_apple', 'tree_orange', 'tree_cherry'];
let treeCount = 0;
const saplingPositions = []; // Shrani pozicije za ograje
for (let x = orchardX + 1; x < orchardX + orchardSize - 1; x += 2) {
for (let y = orchardY + 1; y < orchardY + orchardSize - 1; y += 2) {
if (x >= 0 && x < 100 && y >= 0 && y < 100) {
// Dodaj SADIKO (bo rasla v sadno drevo)
this.terrainSystem.addDecoration(x, y, 'tree_sapling');
saplingPositions.push({ x, y, type: fruitTreeTypes[treeCount % fruitTreeTypes.length] });
treeCount++;
}
}
}
// 3. Dodaj LESENO OGRAJO okoli vsakega drevesa (3x3 kvadrat)
saplingPositions.forEach(pos => {
// Ograja okoli drevesa (3x3)
const fencePositions = [
// Zgornja vrstica
{ x: pos.x - 1, y: pos.y - 1 },
{ x: pos.x, y: pos.y - 1 },
{ x: pos.x + 1, y: pos.y - 1 },
// Spodnja vrstica
{ x: pos.x - 1, y: pos.y + 1 },
{ x: pos.x, y: pos.y + 1 },
{ x: pos.x + 1, y: pos.y + 1 },
// Leva stran
{ x: pos.x - 1, y: pos.y },
// Desna stran
{ x: pos.x + 1, y: pos.y }
];
fencePositions.forEach(fPos => {
if (fPos.x >= 0 && fPos.x < 100 && fPos.y >= 0 && fPos.y < 100) {
this.buildSystem.placeSingleFence(fPos.x, fPos.y, 'fence_horizontal', false);
}
});
});
// 4. Dodaj ZUNANJO OGRAJO okoli celega sadovnjaka
this.buildSystem.placeFenceRectangle(
orchardX - 1,
orchardY - 1,
orchardSize + 2,
orchardSize + 2,
'fence_post',
false
);
// 5. Dodaj cvetje med ograjami
for (let x = orchardX; x < orchardX + orchardSize; x++) {
for (let y = orchardY; y < orchardY + orchardSize; y++) {
if (x >= 0 && x < 100 && y >= 0 && y < 100) {
const key = `${x},${y}`;
if (!this.terrainSystem.decorationsMap.has(key) && Math.random() > 0.85) {
this.terrainSystem.addDecoration(x, y, 'flowers_new');
}
}
}
}
// 6. RAST DREVES - Sadike bodo rasle v sadna drevesa!
// Nastavi timer za rast (vsako drevo raste po 30 sekundah)
saplingPositions.forEach((pos, index) => {
this.time.delayedCall(30000 + (index * 2000), () => {
const key = `${pos.x},${pos.y}`;
// Odstrani sadiko
if (this.terrainSystem.decorationsMap.has(key)) {
this.terrainSystem.removeDecoration(pos.x, pos.y);
}
// Dodaj SADNO DREVO
this.terrainSystem.addDecoration(pos.x, pos.y, pos.type);
// Animacija rasti
if (this.terrainSystem.visibleDecorations.has(key)) {
const sprite = this.terrainSystem.visibleDecorations.get(key);
sprite.setScale(0.01);
this.tweens.add({
targets: sprite,
scaleX: 0.04,
scaleY: 0.04,
duration: 2000,
ease: 'Bounce.out'
});
}
console.log(`🌳 Drevo zraslo: ${pos.type} na (${pos.x}, ${pos.y})`);
});
});
console.log(`✅ Sadovnjak ustvarjen na (${orchardX}, ${orchardY}) - ${treeCount} sadik (bodo rasle v 30s)`);
*/
// ========================================================
// CITY CONTENT: Ruins, Chests, Spawners
console.log('🏚️ Generating City Content...');
// DISABLED - City structures removed for cleaner gameplay
// Main Ruins
// this.terrainSystem.placeStructure(55, 55, 'ruin');
// this.terrainSystem.placeStructure(65, 65, 'ruin');
// this.terrainSystem.placeStructure(75, 75, 'ruin');
// this.terrainSystem.placeStructure(60, 70, 'ruin');
// this.terrainSystem.placeStructure(70, 60, 'ruin');
// Arena (Boss battle area)
// this.terrainSystem.placeStructure(75, 55, 'arena');
// Treasure Chests (scattered in ruins)
// this.terrainSystem.placeStructure(56, 56, 'chest');
// this.terrainSystem.placeStructure(66, 66, 'chest');
// this.terrainSystem.placeStructure(76, 76, 'chest');
// Zombie Spawners (in city)
// this.terrainSystem.placeStructure(58, 68, 'spawner');
// this.terrainSystem.placeStructure(72, 62, 'spawner');
// CESTE (ROADS) - povezava med farmo (20,20) in mestom (65,65)
console.log('🛣️ Building Roads...');
// Horizontalna cesta od farme
for (let x = 20; x <= 45; x++) {
if (this.terrainSystem.tiles[22] && this.terrainSystem.tiles[22][x]) {
this.terrainSystem.tiles[22][x].type = 'pavement';
if (this.terrainSystem.tiles[22][x].sprite) {
this.terrainSystem.tiles[22][x].sprite.setTexture('dirt');
this.terrainSystem.tiles[22][x].sprite.setTint(0x808080);
}
}
}
// Vertikalna cesta do mesta
for (let y = 22; y <= 65; y++) {
if (this.terrainSystem.tiles[y] && this.terrainSystem.tiles[y][45]) {
this.terrainSystem.tiles[y][45].type = 'pavement';
if (this.terrainSystem.tiles[y][45].sprite) {
this.terrainSystem.tiles[y][45].sprite.setTexture('dirt');
this.terrainSystem.tiles[y][45].sprite.setTint(0x808080);
}
}
}
// Horizontalna cesta do mesta
for (let x = 45; x <= 65; x++) {
if (this.terrainSystem.tiles[65] && this.terrainSystem.tiles[65][x]) {
this.terrainSystem.tiles[65][x].type = 'pavement';
if (this.terrainSystem.tiles[65][x].sprite) {
this.terrainSystem.tiles[65][x].sprite.setTexture('dirt');
this.terrainSystem.tiles[65][x].sprite.setTint(0x808080);
}
}
}
// SIGNPOSTS - navigacijske table
// SIGNPOSTS - DISABLED (User request: clean world)
// console.log('🪧 Placing Signposts...');
// this.terrainSystem.placeStructure(23, 22, 'signpost_city');
// this.terrainSystem.placeStructure(65, 64, 'signpost_farm');
// this.terrainSystem.placeStructure(45, 40, 'signpost_both');
// DAMAGED CITY WALLS - DISABLED (User request: clean world)
// console.log('🏚️ Placing Damaged City Walls...');
// const wallPositions = [
// [65, 65], [70, 65], [75, 65],
// [65, 79], [70, 79], [75, 79],
// [65, 70], [65, 75],
// [79, 70], [79, 75]
// ];
// wallPositions.forEach(([wx, wy]) => {
// if (Math.random() < 0.7) {
// this.terrainSystem.placeStructure(wx, wy, 'wall_damaged');
// }
// });
// Initialize Pathfinding (Worker)
console.log('🗺️ Initializing Pathfinding...');
this.pathfinding = new PathfindingSystem(this);
this.pathfinding.updateGrid();
} catch (e) {
console.error("Terrain system failed:", e);
}
// Dodaj igralca NA SPAWN TOČKI
console.log('👤 Initializing player...');
const savedSpawn = localStorage.getItem('novafarma_spawn_point');
let playerSpawnX = 50, playerSpawnY = 50;
if (savedSpawn) {
[playerSpawnX, playerSpawnY] = savedSpawn.split(',').map(Number);
console.log(`👤 Spawning player at saved location: (${playerSpawnX}, ${playerSpawnY})`);
}
this.player = new Player(this, playerSpawnX, playerSpawnY, this.terrainOffsetX, this.terrainOffsetY);
// 🎯 SORTABLE OBJECTS GROUP - Za 2.5D Z-Sorting
console.log('🎯 Creating sortableObjects group for Z-sorting...');
this.sortableObjects = this.add.group();
// Dodaj player sprite v sortableObjects
if (this.player && this.player.sprite) {
this.sortableObjects.add(this.player.sprite);
console.log('✅ Player added to sortableObjects');
}
// ALL NPCs REMOVED - Solo farming mode
console.log('🌾 Solo farming mode - no NPCs');
// FPS Monitor (Performance)
// FPS Monitor - DISABLED (Using UnifiedStatsPanel instead)
// console.log('📊 Initializing FPS Monitor...');
// this.fpsMonitor = new FPSMonitor(this);
// Unified Stats Panel (Performance + Debug in one)
console.log('📊 Initializing Unified Stats Panel...');
this.unifiedStatsPanel = new UnifiedStatsPanel(this);
// NPC Spawner - DISABLED (NPCs look like player duplicates)
console.log('🧟 NPC Spawner - DISABLED');
this.npcSpawner = null; // new NPCSpawner(this);
// this.npcSpawner.spawnInitialNPCs();
// Easter Egg: Broken Scooter
console.log('🛵 Spawning Scooter Easter Egg...');
this.vehicles = [];
// const scooter = new Scooter(this, 25, 25);
// this.vehicles.push(scooter);
// ZOMBIE SPAWNERS (City area)
console.log('👹 Creating Zombie Spawners...');
this.spawners = [];
// DISABLED - Too many zombies for testing
// this.spawners.push(new ZombieSpawner(this, 55, 55, 5, 2, 25000)); // NW
// this.spawners.push(new ZombieSpawner(this, 75, 55, 5, 2, 25000)); // NE
// this.spawners.push(new ZombieSpawner(this, 65, 75, 5, 3, 20000)); // South
// LOOT CHESTS
console.log('📦 Placing Loot Chests...');
this.chests = [];
// Farm Starter Chest ONLY (near spawn)
this.chests.push(new LootChest(this, 28, 28, 'farm_starter'));
// DISABLED - City chests removed for cleaner gameplay
// this.chests.push(new LootChest(this, 60, 60, 'city'));
// this.chests.push(new LootChest(this, 70, 60, 'city'));
// this.chests.push(new LootChest(this, 65, 70, 'elite'));
// SIGNPOSTS/NAVIGATION
console.log('🪧 Adding Signposts...');
this.signposts = [];
// Path markers (using fence sprites as signposts)
// ONLY if terrainSystem was successfully initialized
if (this.terrainSystem) {
const pathMarkers = [
{ x: 35, y: 35, label: '→ City' },
{ x: 50, y: 50, label: '← Farm' },
];
for (const marker of pathMarkers) {
this.terrainSystem.addDecoration(marker.x, marker.y, 'fence');
this.signposts.push({ gridX: marker.x, gridY: marker.y, label: marker.label });
}
} else {
console.warn('⚠️ TerrainSystem not initialized - skipping signposts');
}
// Kamera sledi igralcu z gladko interpolacijo (lerp 0.1)
this.cameras.main.startFollow(this.player.sprite, true, 0.1, 0.1);
// Nastavi deadzone (100px border)
this.cameras.main.setDeadzone(100, 100);
// Round pixels za crisp pixel art
this.cameras.main.roundPixels = true;
// Zoom out za boljši pogled (85% zoom)
this.cameras.main.setZoom(0.85);
// Parallax oblaki
this.createClouds();
// Kamera kontrole
this.setupCamera();
// Initialize Systems
console.log('🌦️ Initializing Unified Weather System...');
this.weatherSystem = new WeatherSystem(this);
this.timeSystem = this.weatherSystem; // Alias
this.statsSystem = new StatsSystem(this);
this.inventorySystem = new InventorySystem(this);
// 🛠️ CRAFTING SYSTEM
this.craftingSystem = new CraftingSystem(this);
this.craftingSystem.loadRecipes().then(() => {
console.log('🛠️ Crafting system ready!');
// Create UI after recipes loaded
this.craftingUI = new CraftingUI(this);
// Add C key to toggle crafting UI
this.input.keyboard.on('keydown-C', () => {
if (this.craftingUI) {
this.craftingUI.toggle();
}
});
});
// ========================================================
// 💎 NEOMEJENI VIRI - Les in Kamen
// ========================================================
console.log('💎 Dodajam neomejene vire...');
this.inventorySystem.addItem('wood', 999999);
this.inventorySystem.addItem('stone', 999999);
this.inventorySystem.gold = 999999;
console.log('✅ Neomejeni viri dodani: 999,999 lesa, kamna in zlata!');
// ========================================================
this.lootSystem = new LootSystem(this);
this.interactionSystem = new InteractionSystem(this);
this.farmingSystem = new FarmingSystem(this);
this.buildingSystem = new BuildingSystem(this);
// this.pathfinding = new Pathfinding(this); // REMOVED: Using PathfindingSystem (Worker) instead
this.questSystem = new QuestSystem(this);
this.collectionSystem = new CollectionSystem(this);
this.multiplayerSystem = new MultiplayerSystem(this);
this.worldEventSystem = new WorldEventSystem(this);
this.hybridSkillSystem = new HybridSkillSystem(this);
this.oceanSystem = new OceanSystem(this);
// Central Popup System (for quests, dialogs, etc.)
this.centralPopup = new CentralPopupSystem(this);
// Tutorial System (shows keyboard shortcuts)
this.tutorialSystem = new TutorialSystem(this);
// Full Inventory UI (24 slots, I key to open)
this.fullInventoryUI = new FullInventoryUI(this);
this.legacySystem = new LegacySystem(this);
// Initialize Sound Manager
console.log('🎵 Initializing Sound Manager...');
this.soundManager = new SoundManager(this);
this.soundManager.startMusic();
// Initialize Parallax System
console.log('🌄 Initializing Parallax System...');
this.parallaxSystem = new ParallaxSystem(this);
// Initialize Particle Effects
console.log('✨ Initializing Particle Effects...');
this.particleEffects = new ParticleEffects(this);
this.particleEffects.createFallingLeaves();
// Initialize Accessibility System
console.log('♿ Initializing Accessibility System...');
this.accessibilitySystem = new AccessibilitySystem(this);
// Initialize Visual Sound Cue System (for deaf/hard-of-hearing players)
console.log('👁️ Initializing Visual Sound Cue System...');
this.visualSoundCueSystem = new VisualSoundCueSystem(this);
// Initialize Input Remapping System (for custom controls)
console.log('🎮 Initializing Input Remapping System...');
this.inputRemapping = new InputRemappingSystem(this);
// Initialize Screen Reader System (for blind/visually impaired players)
console.log('🔊 Initializing Screen Reader System...');
this.screenReader = new ScreenReaderSystem(this);
// Initialize Dyslexia Support System
console.log('📖 Initializing Dyslexia Support System...');
this.dyslexiaSupport = new DyslexiaSupportSystem(this);
// Initialize ADHD/Autism Support System
console.log('🧠 Initializing ADHD/Autism Support System...');
this.adhdAutismSupport = new ADHDAutismSupportSystem(this);
// Initialize Motor Accessibility System
console.log('🦾 Initializing Motor Accessibility System...');
this.motorAccessibility = new MotorAccessibilitySystem(this);
// Initialize Visual Enhancement System
console.log('✨ Initializing Visual Enhancement System...');
this.visualEnhancements = new VisualEnhancementSystem(this);
// Initialize Fog of War System
console.log('🌫️ Initializing Fog of War System...');
this.fogOfWar = new FogOfWarSystem(this);
// Initialize UI Graphics System
console.log('🎨 Initializing UI Graphics System...');
this.uiGraphics = new UIGraphicsSystem(this);
// Initialize Building Visuals System
console.log('🏭 Initializing Building Visuals System...');
this.buildingVisuals = new BuildingVisualsSystem(this);
// Initialize Skill Tree System
console.log('🌳 Initializing Skill Tree System...');
this.skillTree = new SkillTreeSystem(this);
// Initialize Crafting Tiers System
console.log('⚒️ Initializing Crafting Tiers System...');
this.craftingTiers = new CraftingTiersSystem(this);
// Initialize Farm Automation System
console.log('🤖 Initializing Farm Automation System...');
this.farmAutomation = new FarmAutomationSystem(this);
// Initialize Animal Breeding System
console.log('🐑 Initializing Animal Breeding System...');
this.animalBreeding = new AnimalBreedingSystem(this);
// Initialize Automation Tier System
console.log('🤖 Initializing Automation Tier System...');
this.automationTiers = new AutomationTierSystem(this);
// Initialize Breeding UI System
console.log('🌳 Initializing Breeding UI System...');
this.breedingUI = new BreedingUISystem(this);
// Initialize Cooking System
console.log('🍳 Initializing Cooking System...');
this.cooking = new CookingSystem(this);
// Initialize Fishing System
console.log('🎣 Initializing Fishing System...');
this.fishing = new FishingSystem(this);
// Initialize Worker Creatures System
console.log('🦌 Initializing Worker Creatures System...');
this.workerCreatures = new WorkerCreaturesSystem(this);
// Initialize Mining & Dungeons System
console.log('⛏️ Initializing Mining & Dungeons System...');
this.miningDungeons = new MiningDungeonsSystem(this);
// Initialize Boss Battles System
console.log('👹 Initializing Boss Battles System...');
this.bossBattles = new BossBattlesSystem(this);
// Initialize Story & Quest System
console.log('📖 Initializing Story & Quest System...');
this.storyQuest = new StoryQuestSystem(this);
// Initialize Multiplayer & Social System
console.log('🌐 Initializing Multiplayer & Social System...');
this.multiplayerSocial = new MultiplayerSocialSystem(this);
// Initialize Technical & Performance System
console.log('⚡ Initializing Technical & Performance System...');
this.technicalPerformance = new TechnicalPerformanceSystem(this);
// Initialize Platform Support System
console.log('🎮 Initializing Platform Support System...');
this.platformSupport = new PlatformSupportSystem(this);
// Initialize Save System Expansion
console.log('💾 Initializing Save System Expansion...');
this.saveSystemExpansion = new SaveSystemExpansion(this);
console.log('🎉🎉🎉 ALL 27 SYSTEMS INITIALIZED! 🎉🎉🎉');
console.log('💀 MRTVA DOLINA - DEATH VALLEY 💀');
// Show epilepsy warning on first launch
const hasSeenWarning = localStorage.getItem('novafarma_epilepsy_warning');
if (!hasSeenWarning) {
this.time.delayedCall(2000, () => {
this.accessibilitySystem.showEpilepsyWarning(() => {
localStorage.setItem('novafarma_epilepsy_warning', 'true');
});
});
}
// Generate Item Sprites for UI
TextureGenerator.createItemSprites(this);
// Launch UI Scene
console.log('🖥️ Launching UI Scene...');
this.scene.launch('UIScene');
// Initialize Save System
this.saveSystem = new SaveSystem(this);
// Auto-load if available (DISABLED in SaveSystem!)
this.saveSystem.loadGame(); // Vrne false - ne naloži save-a!
// Debug Text - REMOVED (Version shown in UnifiedStatsPanel)
// this.add.text(10, 10, 'NovaFarma Alpha v0.6', { font: '16px monospace', fill: '#ffffff' })
// .setScrollFactor(0).setDepth(10000);
console.log('✅ GameScene ready - FAZA 20 (Full Features)!');
// Global command: giveSeeds(amount) - daj seeds najbližjemu tamed zombiju
window.giveSeeds = (amount = 10) => {
if (!this.zombieWorkerSystem || !this.player) {
console.log('🚫 System not ready!');
return;
}
const workers = this.zombieWorkerSystem.workers;
if (workers.length === 0) {
console.log('🚫 No tamed zombies found!');
return;
}
// Find closest worker
const playerPos = this.player.getPosition();
let closest = null;
let minDist = 999;
for (const worker of workers) {
const dist = Phaser.Math.Distance.Between(playerPos.x, playerPos.y, worker.gridX, worker.gridY);
if (dist < minDist) {
minDist = dist;
closest = worker;
}
}
if (closest && closest.workerData) {
closest.workerData.inventory.seeds += amount;
closest.showEmote(`📦+${amount}`);
console.log(`🧟📦 Gave ${amount} seeds to worker! (Total: ${closest.workerData.inventory.seeds})`);
}
};
console.log('💡 TIP: Use giveSeeds(20) to give 20 seeds to nearest zombie');
// Global command: placeGrave() - postavi grob pri playerju
window.placeGrave = () => {
if (!this.graveSystem || !this.player) {
console.log('🚫 System not ready!');
return;
}
const playerPos = this.player.getPosition();
const result = this.graveSystem.placeGrave(
Math.floor(playerPos.x),
Math.floor(playerPos.y)
);
if (result) {
console.log('🪦 Grave placed successfully!');
}
};
console.log('💡 TIP: Use placeGrave() to place grave at your location');
// Global command: giveAllParts() - daj vse scooter parts
window.giveAllParts = () => {
if (!this.scooterRepairSystem || !this.inventorySystem) {
console.log('🚫 System not ready!');
return;
}
const parts = this.scooterRepairSystem.requiredParts;
const tools = this.scooterRepairSystem.requiredTools;
for (const [part, count] of Object.entries(parts)) {
this.inventorySystem.addItem(part, count);
}
for (const [tool, count] of Object.entries(tools)) {
this.inventorySystem.addItem(tool, count);
}
console.log('✅ All scooter parts and tools added!');
this.scooterRepairSystem.listMissingParts();
};
// Global command: checkScooter() - preveri kaj manjka
window.checkScooter = () => {
if (!this.scooterRepairSystem) {
console.log('🚫 System not ready!');
return;
}
this.scooterRepairSystem.listMissingParts();
};
console.log('💡 TIP: Use checkScooter() to see repair requirements');
console.log('💡 TIP: Use giveAllParts() to get all scooter parts (testing)');
// Global command: unlockZone(id)
window.unlockZone = (id) => {
if (this.expansionSystem) {
this.expansionSystem.unlockZone(id);
}
};
// Global command: dropBlueprint()
window.dropBlueprint = () => {
if (this.blueprintSystem && this.player) {
const pos = this.player.getPosition();
this.blueprintSystem.tryDropBlueprint(pos.x, pos.y, 'boss'); // 100% chance
}
};
// Global command: placeFurnace()
window.placeFurnace = () => {
if (this.terrainSystem && this.player) {
const pos = this.player.getPosition();
const x = Math.floor(pos.x);
const y = Math.floor(pos.y);
this.terrainSystem.placeStructure(x, y, 'furnace');
if (this.inventorySystem) {
this.inventorySystem.addItem('coal', 10);
this.inventorySystem.addItem('ore_iron', 10);
}
console.log(`🏭 Furnace placed at ${x},${y}`);
}
};
// Global command: placeMint()
window.placeMint = () => {
if (this.terrainSystem && this.player) {
const pos = this.player.getPosition();
const x = Math.floor(pos.x);
const y = Math.floor(pos.y);
this.terrainSystem.placeStructure(x, y, 'mint');
if (this.inventorySystem) {
this.inventorySystem.addItem('iron_bar', 10);
this.inventorySystem.addItem('coal', 10);
}
console.log(`💰 Mint placed at ${x},${y}`);
}
};
// TESTNA DREVESA IN KAMNI - Za testiranje
console.log('🌳 Adding test trees and rocks near player...');
this.terrainSystem.addDecoration(52, 50, 'tree_green');
this.terrainSystem.addDecoration(48, 50, 'rock');
this.terrainSystem.addDecoration(50, 52, 'tree_oak');
this.terrainSystem.addDecoration(50, 48, 'rock_large');
console.log('✅ Test decorations added at (50±2, 50±2)');
// Start Engine
this.Antigravity_Start();
}
setupCamera() {
const cam = this.cameras.main;
// 🎨 FLAT 2D CAMERA SETUP (NEW!)
const worldSize = 100 * 48; // 100 tiles × 48px = 4800px
cam.setBounds(0, 0, worldSize, worldSize);
cam.setZoom(1.0); // Default zoom for 2D
// Follow player
if (this.player && this.player.sprite) {
cam.startFollow(this.player.sprite, true, 0.1, 0.1);
}
console.log('📹 2D Camera setup:', worldSize, 'x', worldSize);
// Zoom kontrole (Mouse Wheel)
this.input.on('wheel', (pointer, gameObjects, deltaX, deltaY, deltaZ) => {
const zoomSpeed = 0.001;
const newZoom = Phaser.Math.Clamp(
cam.zoom - deltaY * zoomSpeed,
0.3,
2.0
);
cam.setZoom(newZoom);
});
// Q/E za zoom
this.zoomKeys = this.input.keyboard.addKeys({
zoomIn: Phaser.Input.Keyboard.KeyCodes.Q,
zoomOut: Phaser.Input.Keyboard.KeyCodes.E
});
// Save/Load Keys
this.input.keyboard.on('keydown-F8', () => this.saveGame());
this.input.keyboard.on('keydown-F9', () => this.loadGame());
// Spawn Boss (Debug)
this.input.keyboard.on('keydown-K', () => this.spawnBoss());
// Build Mode Keys
this.input.keyboard.on('keydown-B', () => {
if (this.buildSystem) this.buildSystem.toggleBuildMode();
});
this.input.keyboard.on('keydown-ONE', () => {
if (this.buildSystem && this.buildSystem.buildMode) this.buildSystem.selectBuilding('fence_post');
else if (this.scene.get('UIScene')) this.scene.get('UIScene').selectSlot(0);
});
this.input.keyboard.on('keydown-TWO', () => {
if (this.buildSystem && this.buildSystem.buildMode) this.buildSystem.selectBuilding('fence_horizontal');
else if (this.scene.get('UIScene')) this.scene.get('UIScene').selectSlot(1);
});
this.input.keyboard.on('keydown-THREE', () => {
if (this.buildSystem && this.buildSystem.buildMode) this.buildSystem.selectBuilding('fence_vertical');
else if (this.scene.get('UIScene')) this.scene.get('UIScene').selectSlot(2);
});
this.input.keyboard.on('keydown-FOUR', () => {
if (this.buildSystem && this.buildSystem.buildMode) this.buildSystem.selectBuilding('fence_corner');
else if (this.scene.get('UIScene')) this.scene.get('UIScene').selectSlot(3);
});
this.input.keyboard.on('keydown-FIVE', () => {
if (this.buildSystem && this.buildSystem.buildMode) this.buildSystem.selectBuilding('barn');
else if (this.scene.get('UIScene')) this.scene.get('UIScene').selectSlot(4);
});
// Soft Reset (F4)
this.input.keyboard.on('keydown-F4', () => window.location.reload());
// Help / Tutorial (H key)
this.input.keyboard.on('keydown-H', () => {
if (this.tutorialSystem) {
this.tutorialSystem.showHelp();
}
});
// Mute Toggle (M key)
this.input.keyboard.on('keydown-M', () => {
if (this.soundManager) this.soundManager.toggleMute();
});
// 🌧️ WEATHER SYSTEM KEYS
this.input.keyboard.on('keydown-R', () => this.setWeather('rain'));
this.input.keyboard.on('keydown-SHIFT-S', () => this.setWeather('snow'));
this.input.keyboard.on('keydown-T', () => this.setWeather('storm'));
this.input.keyboard.on('keydown-F', () => this.setWeather('fog'));
this.input.keyboard.on('keydown-SHIFT-C', () => this.setWeather('clear'));
// Initialize weather system
this.initializeWeatherSystem();
// Initialize Weather UI Panel
this.weatherUI = new WeatherUI(this);
console.log('📊 Weather UI Panel created (press W to toggle)');
}
// 🌦️ COMPLETE WEATHER SYSTEM
initializeWeatherSystem() {
this.currentWeather = 'clear';
this.weatherIntensity = 1.0;
this.puddles = [];
this.splashes = [];
this.autoWeatherEnabled = false;
this.weatherCycleTimer = null;
// Load saved weather state
this.loadWeatherState();
console.log('🌦️ Weather system initialized');
console.log('💡 R = Rain | Shift+S = Snow | T = Storm | F = Fog | Shift+C = Clear');
console.log('💡 Shift+A = Toggle Auto Weather Cycle');
// Auto weather cycle toggle
this.input.keyboard.on('keydown-SHIFT-A', () => {
this.toggleAutoWeather();
});
// Intensity controls (+/-)
this.input.keyboard.on('keydown-PLUS', () => this.adjustIntensity(0.2));
this.input.keyboard.on('keydown-MINUS', () => this.adjustIntensity(-0.2));
}
toggleAutoWeather() {
this.autoWeatherEnabled = !this.autoWeatherEnabled;
if (this.autoWeatherEnabled) {
console.log('🔄 Auto weather cycle ENABLED');
this.startWeatherCycle();
} else {
console.log('⏸️ Auto weather cycle DISABLED');
if (this.weatherCycleTimer) {
this.weatherCycleTimer.destroy();
this.weatherCycleTimer = null;
}
}
this.saveWeatherState();
}
startWeatherCycle() {
// Weather cycle: Clear → Rain → Storm → Clear → Snow → Fog → Clear
const weatherSequence = ['clear', 'rain', 'storm', 'clear', 'snow', 'fog'];
const weatherDurations = {
clear: 120000, // 2 minutes
rain: 90000, // 1.5 minutes
storm: 60000, // 1 minute
snow: 90000, // 1.5 minutes
fog: 60000 // 1 minute
};
let currentIndex = 0;
const cycleWeather = () => {
const nextWeather = weatherSequence[currentIndex];
this.setWeather(nextWeather);
currentIndex = (currentIndex + 1) % weatherSequence.length;
const duration = weatherDurations[nextWeather] || 120000;
this.weatherCycleTimer = this.time.delayedCall(duration, () => {
if (this.autoWeatherEnabled) {
cycleWeather();
}
});
console.log(`🌦️ Auto weather: ${nextWeather} (${duration / 1000}s)`);
};
cycleWeather();
}
adjustIntensity(delta) {
this.weatherIntensity = Phaser.Math.Clamp(this.weatherIntensity + delta, 0.2, 2.0);
// Update current weather with new intensity
if (this.currentWeather !== 'clear' && this.currentWeather !== 'fog') {
this.setWeather(this.currentWeather); // Restart with new intensity
}
console.log(`🎚️ Weather intensity: ${(this.weatherIntensity * 100).toFixed(0)}%`);
this.saveWeatherState();
}
saveWeatherState() {
const state = {
currentWeather: this.currentWeather,
intensity: this.weatherIntensity,
autoEnabled: this.autoWeatherEnabled
};
localStorage.setItem('novafarma_weather_state', JSON.stringify(state));
}
loadWeatherState() {
const saved = localStorage.getItem('novafarma_weather_state');
if (saved) {
try {
const state = JSON.parse(saved);
this.currentWeather = state.currentWeather || 'clear';
this.weatherIntensity = state.intensity || 1.0;
this.autoWeatherEnabled = state.autoEnabled || false;
console.log('📂 Weather state loaded:', state);
// Restore weather (delayed to avoid initialization issues)
this.time.delayedCall(1000, () => {
if (this.currentWeather !== 'clear') {
this.setWeather(this.currentWeather);
}
if (this.autoWeatherEnabled) {
this.startWeatherCycle();
}
});
} catch (e) {
console.warn('⚠️ Failed to load weather state:', e);
}
}
}
setWeather(type) {
// Stop current weather
this.stopAllWeather();
this.currentWeather = type;
switch (type) {
case 'rain':
this.startRain();
break;
case 'snow':
this.startSnow();
break;
case 'storm':
this.startStorm();
break;
case 'fog':
this.startFog();
break;
case 'clear':
console.log('☀️ Clear weather');
break;
}
this.saveWeatherState();
}
stopAllWeather() {
// Stop all particle emitters
if (this.rainEmitter) this.rainEmitter.stop();
if (this.snowEmitter) this.snowEmitter.stop();
if (this.stormEmitter) this.stormEmitter.stop();
// Stop lightning
if (this.lightningTimer) {
this.lightningTimer.destroy();
this.lightningTimer = null;
}
// Stop puddle spawning
if (this.puddleTimer) {
this.puddleTimer.destroy();
this.puddleTimer = null;
}
// Fade out fog
if (this.fogOverlay) {
this.tweens.add({
targets: this.fogOverlay,
alpha: 0,
duration: 2000,
onComplete: () => {
if (this.fogOverlay) this.fogOverlay.destroy();
this.fogOverlay = null;
}
});
}
// Cleanup puddles
this.puddles.forEach(puddle => {
this.tweens.add({
targets: puddle,
alpha: 0,
duration: 3000,
onComplete: () => puddle.destroy()
});
});
this.puddles = [];
}
// ☔ RAIN SYSTEM
startRain() {
if (!this.rainEmitter) {
this.createRainParticles();
}
// Apply intensity
this.rainEmitter.setQuantity(Math.floor(3 * this.weatherIntensity));
this.rainEmitter.setFrequency(30 / this.weatherIntensity);
this.rainEmitter.start();
console.log('🌧️ Rain started!');
// Start puddle spawning
this.puddleTimer = this.time.addEvent({
delay: 3000 / this.weatherIntensity,
callback: () => this.spawnPuddle(),
loop: true
});
// Play rain sound
if (this.soundManager && this.soundManager.playRainSound) {
this.soundManager.playRainSound();
}
}
createRainParticles() {
if (!this.textures.exists('raindrop')) {
const graphics = this.make.graphics({ x: 0, y: 0, add: false });
graphics.fillStyle(0x88ccff, 1);
graphics.fillCircle(1, 2, 1);
graphics.generateTexture('raindrop', 2, 4);
graphics.destroy();
}
const cam = this.cameras.main;
this.rainEmitter = this.add.particles(0, 0, 'raindrop', {
x: { min: 0, max: cam.width },
y: -50,
lifespan: 3000,
speedY: { min: 400, max: 600 },
scale: { start: 1, end: 0.5 },
alpha: { start: 0.6, end: 0.2 },
quantity: 3,
frequency: 30,
blendMode: 'ADD',
// 🌊 DETECT WHEN RAINDROP HITS GROUND
deathCallback: (particle) => {
// Convert camera-relative position to world position
const worldX = particle.x + cam.scrollX;
const worldY = particle.y + cam.scrollY;
// Check if hit water tile
this.checkRainImpactOnWater(worldX, worldY);
}
});
this.rainEmitter.setScrollFactor(0);
this.rainEmitter.setDepth(999999);
this.rainEmitter.stop();
}
// ❄️ SNOW SYSTEM
startSnow() {
if (!this.snowEmitter) {
this.createSnowParticles();
}
this.snowEmitter.start();
console.log('❄️ Snow started!');
}
createSnowParticles() {
if (!this.textures.exists('snowflake')) {
const graphics = this.make.graphics({ x: 0, y: 0, add: false });
graphics.fillStyle(0xffffff, 1);
graphics.fillCircle(2, 2, 2);
graphics.generateTexture('snowflake', 4, 4);
graphics.destroy();
}
const cam = this.cameras.main;
this.snowEmitter = this.add.particles(0, 0, 'snowflake', {
x: { min: 0, max: cam.width },
y: -50,
lifespan: 8000,
speedY: { min: 50, max: 150 },
speedX: { min: -30, max: 30 },
scale: { start: 0.5, end: 1.5 },
alpha: { start: 0.8, end: 0.3 },
quantity: 2,
frequency: 80,
blendMode: 'ADD'
});
this.snowEmitter.setScrollFactor(0);
this.snowEmitter.setDepth(999999);
this.snowEmitter.stop();
}
// ⚡ STORM SYSTEM
startStorm() {
if (!this.stormEmitter) {
this.createStormParticles();
}
this.stormEmitter.start();
console.log('⛈️ Storm started!');
// Lightning flashes
this.lightningTimer = this.time.addEvent({
delay: Phaser.Math.Between(3000, 8000),
callback: () => this.triggerLightning(),
loop: true
});
// Puddles (faster spawn)
this.puddleTimer = this.time.addEvent({
delay: 2000,
callback: () => this.spawnPuddle(),
loop: true
});
}
createStormParticles() {
if (!this.textures.exists('raindrop')) {
this.createRainParticles();
}
const cam = this.cameras.main;
this.stormEmitter = this.add.particles(0, 0, 'raindrop', {
x: { min: 0, max: cam.width },
y: -50,
lifespan: 2000,
speedY: { min: 600, max: 900 },
speedX: { min: 50, max: 150 },
scale: { start: 1.5, end: 0.5 },
alpha: { start: 0.8, end: 0.3 },
quantity: 5,
frequency: 20,
blendMode: 'ADD'
});
this.stormEmitter.setScrollFactor(0);
this.stormEmitter.setDepth(999999);
this.stormEmitter.stop();
}
triggerLightning() {
// White flash overlay
const flash = this.add.rectangle(
this.cameras.main.scrollX,
this.cameras.main.scrollY,
this.cameras.main.width,
this.cameras.main.height,
0xffffff,
0.8
);
flash.setOrigin(0, 0);
flash.setScrollFactor(0);
flash.setDepth(1000000);
// Fade out
this.tweens.add({
targets: flash,
alpha: 0,
duration: 200,
onComplete: () => flash.destroy()
});
// Screen shake
this.cameras.main.shake(200, 0.005);
// Thunder sound (if available)
if (this.soundManager && this.soundManager.playThunderSound) {
this.time.delayedCall(300, () => {
this.soundManager.playThunderSound();
});
}
console.log('⚡ Lightning strike!');
}
// 🌫️ FOG SYSTEM
startFog() {
if (!this.fogOverlay) {
this.fogOverlay = this.add.rectangle(
0, 0,
this.cameras.main.width * 2,
this.cameras.main.height * 2,
0xcccccc,
0
);
this.fogOverlay.setOrigin(0, 0);
this.fogOverlay.setScrollFactor(0);
this.fogOverlay.setDepth(500000);
}
this.tweens.add({
targets: this.fogOverlay,
alpha: 0.4,
duration: 3000
});
console.log('🌫️ Fog started!');
}
// 💧 PUDDLES SYSTEM (Spawn on grass/dirt where rain lands!)
spawnPuddle() {
if (!this.terrainSystem) return;
const cam = this.cameras.main;
const worldX = cam.scrollX + Phaser.Math.Between(100, cam.width - 100);
const worldY = cam.scrollY + Phaser.Math.Between(100, cam.height - 100);
// 🎨 FLAT 2D CONVERSION (NEW!)
const tileSize = 48;
const x = Math.floor(worldX / tileSize);
const y = Math.floor(worldY / tileSize);
// Get tile type
const tile = this.terrainSystem.getTile(x, y);
// ONLY spawn puddles on grass or dirt!
if (!tile || (tile.type !== 'grass' && tile.type !== 'dirt' && tile.type !== 'farmland')) {
return; // Skip - not valid surface
}
// Limit max puddles
if (this.puddles.length >= 15) {
const oldest = this.puddles.shift();
if (oldest && oldest.active) oldest.destroy();
}
// Create puddle SPRITE (realistic!)
const puddle = this.add.image(worldX, worldY, 'luza_sprite');
puddle.setOrigin(0.5, 0.5);
puddle.setScale(1.5); // BIGGER - more visible!
puddle.setDepth(10); // ABOVE terrain
puddle.setScrollFactor(1);
puddle.setAlpha(0); // Start invisible
// Fade in
this.tweens.add({
targets: puddle,
alpha: 0.35,
duration: 2000
});
this.puddles.push(puddle);
// Auto cleanup after 30 seconds
this.time.delayedCall(30000, () => {
if (puddle && puddle.active) {
this.tweens.add({
targets: puddle,
alpha: 0,
duration: 3000,
onComplete: () => {
puddle.destroy();
const index = this.puddles.indexOf(puddle);
if (index > -1) this.puddles.splice(index, 1);
}
});
}
});
// Random splash effects
this.time.addEvent({
delay: Phaser.Math.Between(1000, 3000),
callback: () => {
if (puddle && puddle.active && (this.currentWeather === 'rain' || this.currentWeather === 'storm')) {
this.createSplash(puddle.x, puddle.y);
}
},
loop: true,
repeat: 5
});
}
// 🌊 CHECK IF RAIN HIT WATER TILE
checkRainImpactOnWater(worldX, worldY) {
if (!this.terrainSystem) return;
// 🎨 FLAT 2D CONVERSION (NEW!)
const tileSize = 48;
const x = Math.floor(worldX / tileSize);
const y = Math.floor(worldY / tileSize);
// Get tile at position
const tile = this.terrainSystem.getTile(x, y);
// If water tile, create ripple!
if (tile && tile.type === 'water') {
this.createWaterRipple(worldX, worldY);
}
// If grass/dirt, 3% chance to spawn puddle
else if (tile && (tile.type === 'grass' || tile.type === 'dirt' || tile.type === 'farmland')) {
if (Math.random() < 0.03) {
this.spawnPuddleAtLocation(worldX, worldY);
}
}
}
// 💧 CREATE WATER RIPPLE EFFECT
createWaterRipple(x, y) {
// Small expanding circle on water surface
const ripple = this.add.circle(x, y, 2, 0xffffff, 0.5);
ripple.setDepth(500); // Above water tiles
ripple.setScrollFactor(1); // World-bound
this.tweens.add({
targets: ripple,
radius: 10,
alpha: 0,
duration: 400,
ease: 'Quad.easeOut',
onComplete: () => ripple.destroy()
});
}
// 💧 SPAWN PUDDLE AT EXACT LOCATION (from rain impact)
spawnPuddleAtLocation(worldX, worldY) {
// Limit max puddles
if (this.puddles.length >= 15) {
// Remove oldest puddle
const oldest = this.puddles.shift();
if (oldest && oldest.active) oldest.destroy();
}
// Create puddle SPRITE (realistic!)
const puddle = this.add.image(worldX, worldY, 'luza_sprite');
puddle.setOrigin(0.5, 0.5);
puddle.setScale(1.5); // BIGGER - more visible!
puddle.setDepth(10); // ABOVE terrain
puddle.setScrollFactor(1);
puddle.setAlpha(0); // Start invisible
// Fade in
this.tweens.add({
targets: puddle,
alpha: 0.35,
duration: 2000
});
this.puddles.push(puddle);
// Auto cleanup after 30 seconds
this.time.delayedCall(30000, () => {
if (puddle && puddle.active) {
this.tweens.add({
targets: puddle,
alpha: 0,
duration: 3000,
onComplete: () => {
puddle.destroy();
const index = this.puddles.indexOf(puddle);
if (index > -1) this.puddles.splice(index, 1);
}
});
}
});
}
// 💦 SPLASH EFFECT (Ripples)
createSplash(x, y) {
// Concentric circles
for (let i = 0; i < 3; i++) {
this.time.delayedCall(i * 100, () => {
const circle = this.add.circle(x, y, 3, 0xffffff, 0.5);
circle.setDepth(2);
this.tweens.add({
targets: circle,
radius: 20 + (i * 5),
alpha: 0,
duration: 600,
onComplete: () => circle.destroy()
});
});
}
}
update(time, delta) {
if (this.player) this.player.update(delta);
// 🎯 Z-SORTING: SortableObjects based on Y position
if (this.sortableObjects) {
const children = this.sortableObjects.getChildren();
// Sortiranje po Y koordinati (nižji Y = nižji depth)
children.sort((a, b) => a.y - b.y);
// Nastavi depth glede na vrstni red (index)
children.forEach((obj, index) => {
// Use LAYER_OBJECTS base + index for depth
obj.setDepth(200000 + index);
});
}
// Weather UI Update
if (this.weatherUI) this.weatherUI.update();
// Update Systems
if (this.terrainSystem) this.terrainSystem.update(time, delta); // Water animation!
if (this.statsSystem) this.statsSystem.update(delta);
if (this.craftingSystem) this.craftingSystem.update(delta); // 🛠️ Crafting progress
if (this.lootSystem) this.lootSystem.update(delta);
if (this.interactionSystem) this.interactionSystem.update(delta);
if (this.farmingSystem) this.farmingSystem.update(delta);
if (this.buildSystem) this.buildSystem.update(delta);
if (this.questSystem) this.questSystem.update(delta);
if (this.multiplayerSystem) this.multiplayerSystem.update(delta);
if (this.weatherSystem) {
this.weatherSystem.update(delta);
// Concept Systems Updates
if (this.zombieSystem) this.zombieSystem.update(this.time.now, delta);
// Night Logic
if (this.weatherSystem.isNight()) {
const isHorde = this.weatherSystem.isHordeNight();
const spawnInterval = isHorde ? 2000 : 10000;
// Check for Horde Start Warning
if (isHorde && !this.hordeWarningShown) {
this.showHordeWarning();
this.hordeWarningShown = true;
}
if (!this.nightSpawnTimer) this.nightSpawnTimer = 0;
this.nightSpawnTimer += delta;
if (this.nightSpawnTimer > spawnInterval) {
this.nightSpawnTimer = 0;
this.spawnNightZombie();
if (isHorde) {
this.spawnNightZombie();
this.spawnNightZombie();
}
}
} else {
this.hordeWarningShown = false;
}
}
// NPC Update - DISABLED (no NPCs)
/*
for (const npc of this.npcs) {
npc.update(delta);
}
*/
// Vehicles Update
if (this.vehicles) {
for (const vehicle of this.vehicles) {
if (vehicle.update) vehicle.update(delta);
}
}
// Spawners Update
if (this.spawners) {
for (const spawner of this.spawners) {
if (spawner.update) spawner.update(delta);
}
}
// Zombie Worker System
if (this.zombieWorkerSystem) this.zombieWorkerSystem.update(delta);
// Workstation System
if (this.workstationSystem) this.workstationSystem.update(delta);
// Grave System Update (regeneration)
if (this.graveSystem) {
this.graveSystem.update(delta);
// Auto-rest check every 5 seconds
if (!this.graveAutoRestTimer) this.graveAutoRestTimer = 0;
this.graveAutoRestTimer += delta;
if (this.graveAutoRestTimer >= 5000) {
this.graveSystem.autoRest();
this.graveAutoRestTimer = 0;
}
}
// Parallax Logic
if (this.parallaxSystem && this.player) {
const playerPos = this.player.getPosition();
// 🎨 FLAT 2D (NEW!) - Direct position, no conversion
const tileSize = 48;
const screenX = playerPos.x * tileSize + tileSize / 2;
const screenY = playerPos.y * tileSize + tileSize / 2;
this.parallaxSystem.update(screenX, screenY);
}
// Terrain Update
if (this.terrainSystem) {
// Note: Flat2D doesn't need culling (already optimized)
// this.terrainSystem.updateCulling(this.cameras.main);
this.terrainSystem.update(delta);
}
// Clouds
if (this.clouds) {
for (const cloud of this.clouds) {
if (cloud && cloud.sprite) {
cloud.sprite.x += cloud.speed * (delta / 1000);
if (cloud.sprite.x > this.terrainOffsetX + 2000) {
cloud.sprite.x = this.terrainOffsetX - 2000;
cloud.sprite.y = Phaser.Math.Between(0, 1000);
}
}
}
}
if (this.worldEventSystem) this.worldEventSystem.update(delta);
// FPS Monitor Update
if (this.fpsMonitor) this.fpsMonitor.update();
// Performance Monitor Update
if (this.performanceMonitor) this.performanceMonitor.update(delta);
// NPC Spawner Update
if (this.npcSpawner) this.npcSpawner.update(delta);
// Visual Sound Cue System Update
if (this.visualSoundCueSystem) this.visualSoundCueSystem.update();
// Screen Reader System Update
if (this.screenReader) this.screenReader.update();
// Motor Accessibility System Update
if (this.motorAccessibility) this.motorAccessibility.update();
// Visual Enhancement System Update
if (this.visualEnhancements) this.visualEnhancements.update(delta);
// Fog of War System Update
if (this.fogOfWar) this.fogOfWar.update();
// Farm Automation System Update
if (this.farmAutomation) this.farmAutomation.update(delta);
// Animal Breeding System Update
if (this.animalBreeding) this.animalBreeding.update(delta);
// Automation Tier System Update
if (this.automationTiers) this.automationTiers.update(delta);
// Cooking System Update
if (this.cooking) this.cooking.update(delta);
// Fishing System Update
if (this.fishing) this.fishing.update(delta);
// Worker Creatures System Update
if (this.workerCreatures) this.workerCreatures.update(delta);
// Boss Battles System Update
if (this.bossBattles) this.bossBattles.update(delta);
// Multiplayer & Social System Update
if (this.multiplayerSocial) this.multiplayerSocial.update(delta);
// Technical & Performance System Update
if (this.technicalPerformance) this.technicalPerformance.update(delta);
// Platform Support System Update
if (this.platformSupport) this.platformSupport.update(delta);
// Save System Expansion Update
if (this.saveSystemExpansion) this.saveSystemExpansion.update(delta);
// Update NPCs
for (const npc of this.npcs) {
if (npc.update) npc.update(delta);
}
// Update Unified Stats Panel
if (this.unifiedStatsPanel) {
this.unifiedStatsPanel.update(delta);
}
// Update Full Inventory UI
if (this.fullInventoryUI) {
this.fullInventoryUI.update();
}
// Run Antigravity Engine Update
this.Antigravity_Update(delta);
}
spawnNightZombie() {
// DISABLED - No NPCs allowed
return;
/*
if (!this.player || this.npcs.length > 50) return;
const playerPos = this.player.getPosition();
const angle = Math.random() * Math.PI * 2;
const distance = Phaser.Math.Between(15, 25);
const spawnX = Math.floor(playerPos.x + Math.cos(angle) * distance);
const spawnY = Math.floor(playerPos.y + Math.sin(angle) * distance);
if (spawnX < 0 || spawnX >= 100 || spawnY < 0 || spawnY >= 100) return;
if (Phaser.Math.Distance.Between(spawnX, spawnY, 20, 20) < 15) return;
const tile = this.terrainSystem.getTile(spawnX, spawnY);
if (tile && tile.type !== 'water') {
console.log(`🌑 Night Spawn: Zombie at ${spawnX},${spawnY}`);
const zombie = new NPC(this, spawnX, spawnY, this.terrainOffsetX, this.terrainOffsetY, 'zombie');
zombie.state = 'CHASE';
this.npcs.push(zombie);
}
*/
}
showHordeWarning() {
console.log('🩸 BLOOD MOON RISING!');
if (this.soundManager) this.soundManager.playDeath();
const width = this.cameras.main.width;
const height = this.cameras.main.height;
const text = this.add.text(width / 2, height / 3, 'THE HORDE IS APPROACHING...', {
fontSize: '40px', fontFamily: 'Courier New', fill: '#ff0000', fontStyle: 'bold', stroke: '#000000', strokeThickness: 6
}).setOrigin(0.5).setScrollFactor(0).setDepth(10000);
this.tweens.add({
targets: text, scale: 1.2, duration: 500, yoyo: true, repeat: 5,
onComplete: () => {
this.tweens.add({
targets: text, alpha: 0, duration: 2000,
onComplete: () => text.destroy()
});
}
});
}
createClouds() {
if (!this.textures.exists('cloud')) TextureGenerator.createCloudSprite(this, 'cloud');
this.clouds = [];
console.log('☁️ Creating parallax clouds...');
for (let i = 0; i < 8; i++) {
const x = Phaser.Math.Between(-1000, 3000);
const y = Phaser.Math.Between(-500, 1500);
const cloud = this.add.sprite(x, y, 'cloud');
cloud.setAlpha(0.4).setScrollFactor(0.2).setDepth(2000).setScale(Phaser.Math.FloatBetween(2, 4));
this.clouds.push({ sprite: cloud, speed: Phaser.Math.FloatBetween(10, 30) });
}
}
spawnBoss() {
// DISABLED - No NPCs allowed
return;
/*
if (!this.player) return;
console.log('👑 SPANWING ZOMBIE KING!');
const playerPos = this.player.getPosition();
const spawnX = Math.floor(playerPos.x + 8);
const spawnY = Math.floor(playerPos.y + 8);
const boss = new Boss(this, spawnX, spawnY);
boss.state = 'CHASE';
this.npcs.push(boss);
this.showHordeWarning();
this.events.emit('show-floating-text', { x: this.player.x, y: this.player.y - 100, text: "THE KING HAS ARRIVED!", color: '#AA00FF' });
*/
}
saveGame() {
if (this.saveSystem) this.saveSystem.saveGame();
}
loadGame() {
if (this.saveSystem) this.saveSystem.loadGame();
}
initializeFarmWorld(spawnX = 20, spawnY = 20) {
console.log(`🌾 Initializing 8x8 Farm Area at (${spawnX}, ${spawnY})...`);
const farmX = spawnX; // Farm center (custom spawn)
const farmY = spawnY;
const farmRadius = 4; // 8x8 = radius 4 (4 tiles in each direction)
// 1. Clear farm area (odstrani drevesa in kamne)
for (let x = farmX - farmRadius; x <= farmX + farmRadius; x++) {
for (let y = farmY - farmRadius; y <= farmY + farmRadius; y++) {
if (x >= 0 && x < 100 && y >= 0 && y < 100) {
const key = `${x},${y}`;
// Remove trees and rocks in farm area
if (this.terrainSystem.decorationsMap.has(key)) {
this.terrainSystem.removeDecoration(x, y);
}
// Change terrain to grass
if (this.terrainSystem.tiles[y] && this.terrainSystem.tiles[y][x]) {
this.terrainSystem.tiles[y][x].type = 'grass';
this.terrainSystem.tiles[y][x].solid = false;
if (this.terrainSystem.tiles[y][x].sprite) {
this.terrainSystem.tiles[y][x].sprite.setTexture('grass');
this.terrainSystem.tiles[y][x].sprite.clearTint();
}
}
}
}
}
// 2. Optional: Add fence around farm (commented out)
// const minX = farmX - farmRadius - 1;
// const maxX = farmX + farmRadius + 1;
// const minY = farmY - farmRadius - 1;
// const maxY = farmY + farmRadius + 1;
// // Top and bottom horizontal fences
// for (let x = minX; x <= maxX; x++) {
// if (x >= 0 && x < 100) {
// this.terrainSystem.placeStructure(x, minY, 'fence_full'); // Top
// this.terrainSystem.placeStructure(x, maxY, 'fence_full'); // Bottom
// }
// }
// // Left and right vertical fences
// for (let y = minY; y <= maxY; y++) {
// if (y >= 0 && y < 100) {
// this.terrainSystem.placeStructure(minX, y, 'fence_full'); // Left
// this.terrainSystem.placeStructure(maxX, y, 'fence_full'); // Right
// }
// }
console.log(`✅ 8x8 Farm Area Initialized at (${spawnX},${spawnY})`);
}
// ========================================================
// ANTIGRAVITY ENGINE UPDATE
// ========================================================
Antigravity_Start() {
console.log('🚀 Starting Antigravity Engine...');
if (window.Antigravity) {
// Camera Setup
if (this.player && this.player.sprite) {
window.Antigravity.Camera.follow(this, this.player.sprite);
}
// ZOOM SETUP - 0.75 za "Open World" pregled
window.Antigravity.Camera.setZoom(this, 0.75);
}
}
Antigravity_Update(delta) {
// Globalni update klic
if (window.Antigravity) {
window.Antigravity.Update(this, delta);
}
// Parallax background update
this.updateParallax(delta);
// Terrain system update (za water animacijo)
if (this.terrainSystem && this.terrainSystem.update) {
this.terrainSystem.update(Date.now(), delta);
} else {
console.warn('⚠️ TerrainSystem.update not available!');
}
}
createParallaxBackground() {
const width = this.cameras.main.width;
const height = this.cameras.main.height;
// Parallax container
this.parallaxContainer = this.add.container(0, 0);
this.parallaxContainer.setDepth(-1000); // Always behind everything
this.clouds = [];
this.birds = [];
// Create 5 clouds
for (let i = 0; i < 5; i++) {
const cloud = this.add.text(
Math.random() * width * 2,
Math.random() * height * 0.5,
'☁️',
{ fontSize: `${30 + Math.random() * 20}px` }
);
cloud.speed = 0.3 + Math.random() * 0.2; // 0.3-0.5x speed
this.parallaxContainer.add(cloud);
this.clouds.push(cloud);
}
// Create 3 birds
for (let i = 0; i < 3; i++) {
const bird = this.add.text(
Math.random() * width * 2,
100 + Math.random() * 200,
'🐦',
{ fontSize: '20px' }
);
bird.speed = 0.5 + Math.random() * 0.3; // 0.5-0.8x speed
this.parallaxContainer.add(bird);
this.birds.push(bird);
}
console.log('☁️ Parallax background created!');
}
updateParallax(delta) {
if (!this.parallaxContainer) return;
const width = this.cameras.main.width;
// Update clouds
this.clouds.forEach(cloud => {
cloud.x -= cloud.speed * (delta / 16);
if (cloud.x < -100) {
cloud.x = width + 100;
cloud.y = Math.random() * this.cameras.main.height * 0.5;
}
});
// Update birds
this.birds.forEach(bird => {
bird.x -= bird.speed * (delta / 16);
bird.y += Math.sin(Date.now() / 1000 + bird.x) * 0.5; // Flutter effect
if (bird.x < -100) {
bird.x = width + 100;
bird.y = 100 + Math.random() * 200;
}
});
}
}