diff --git a/index.html b/index.html index dac4b69..458a403 100644 --- a/index.html +++ b/index.html @@ -166,6 +166,7 @@ + diff --git a/src/scenes/GameScene.js b/src/scenes/GameScene.js index 9e45719..aa659a3 100644 --- a/src/scenes/GameScene.js +++ b/src/scenes/GameScene.js @@ -84,6 +84,11 @@ class GameScene extends Phaser.Scene { this.buildSystem = new BuildSystem(this); console.log('🏗️ Build system initialized!'); + // 🌱 Initialize Micro Farm System (PHASE 37!) + this.microFarmSystem = new MicroFarmSystem(this); + console.log('🌱 Micro Farm system initialized!'); + + // ======================================================== // 🏗️ TESTNI PRIMERI - Postavitev Ograj (ONEMOGOČENO) // ======================================================== diff --git a/src/scenes/UIScene.js b/src/scenes/UIScene.js index 1b7df29..e08e05c 100644 --- a/src/scenes/UIScene.js +++ b/src/scenes/UIScene.js @@ -2689,7 +2689,7 @@ class UIScene extends Phaser.Scene { */ updateMinimapContent() { if (!this.minimapExpanded) return; - if (!this.gameScene || !this.gameScene.terrain) return; + if (!this.gameScene) return; this.minimapGraphics.clear(); @@ -2698,38 +2698,60 @@ class UIScene extends Phaser.Scene { const scale = (mapSize * 2) / worldSize; // Get player position - const playerPos = this.gameScene.player.getPosition(); - const centerX = playerPos.x; - const centerY = playerPos.y; + const player = this.gameScene.player; + if (!player) return; + + const centerX = Math.floor(player.gridX || 0); + const centerY = Math.floor(player.gridY || 0); // View radius around player const viewRadius = 25; // Draw terrain tiles - for (let y = Math.max(0, centerY - viewRadius); y < Math.min(worldSize, centerY + viewRadius); y++) { - for (let x = Math.max(0, centerX - viewRadius); x < Math.min(worldSize, centerX + viewRadius); x++) { - const tile = this.gameScene.terrain[y] && this.gameScene.terrain[y][x]; - if (!tile) continue; + if (this.gameScene.terrainSystem && this.gameScene.terrainSystem.tiles) { + for (let y = Math.max(0, centerY - viewRadius); y < Math.min(worldSize, centerY + viewRadius); y++) { + for (let x = Math.max(0, centerX - viewRadius); x < Math.min(worldSize, centerX + viewRadius); x++) { + const tile = this.gameScene.terrainSystem.getTile(x, y); + if (!tile) continue; - // Calculate position relative to player - const relX = (x - centerX) * scale; - const relY = (y - centerY) * scale; + // Calculate position relative to player + const relX = (x - centerX) * scale; + const relY = (y - centerY) * scale; - // Only draw if within circle - const dist = Math.sqrt(relX * relX + relY * relY); - if (dist > mapSize) continue; + // Only draw if within circle + const dist = Math.sqrt(relX * relX + relY * relY); + if (dist > mapSize) continue; - // Color based on tile type - let color = 0x228B22; // Default green - if (tile.type === 'water') color = 0x4488ff; - else if (tile.type === 'sand') color = 0xf4a460; - else if (tile.type === 'stone') color = 0x808080; - else if (tile.type === 'grass') color = 0x228B22; + // Color based on tile type + let color = 0x228B22; // Default green + if (tile.type === 'water') color = 0x4488ff; + else if (tile.type === 'sand') color = 0xf4a460; + else if (tile.type === 'stone') color = 0x808080; + else if (tile.type === 'grass') color = 0x228B22; - this.minimapGraphics.fillStyle(color, 0.8); - this.minimapGraphics.fillRect(relX - scale / 2, relY - scale / 2, scale, scale); + this.minimapGraphics.fillStyle(color, 0.8); + this.minimapGraphics.fillRect(relX - scale / 2, relY - scale / 2, scale, scale); + } } } + + // 🌱 DRAW MICRO FARM BOUNDARY! + if (this.gameScene.microFarmSystem) { + const farmCenterX = this.gameScene.microFarmSystem.farmCenterX; + const farmCenterY = this.gameScene.microFarmSystem.farmCenterY; + const farmSize = this.gameScene.microFarmSystem.farmSize; + const halfSize = Math.floor(farmSize / 2); + + // Farm boundary in minimap coords + const farmX1 = (farmCenterX - halfSize - centerX) * scale; + const farmY1 = (farmCenterY - halfSize - centerY) * scale; + const farmW = farmSize * scale; + const farmH = farmSize * scale; + + // Draw white farm boundary + this.minimapGraphics.lineStyle(2, 0xFFFFFF, 0.9); + this.minimapGraphics.strokeRect(farmX1, farmY1, farmW, farmH); + } } /** diff --git a/src/systems/FarmingSystem.js b/src/systems/FarmingSystem.js index 8972fa5..7583856 100644 --- a/src/systems/FarmingSystem.js +++ b/src/systems/FarmingSystem.js @@ -26,6 +26,22 @@ class FarmingSystem { tillSoil(gridX, gridY) { if (!this.scene.terrainSystem) return false; + // 🌱 CHECK MICRO FARM BOUNDARY! + if (this.scene.microFarmSystem && !this.scene.microFarmSystem.isTileUnlocked(gridX, gridY)) { + console.log('❌ Cannot till outside farm boundary!'); + + // Show error message + if (this.scene.events) { + this.scene.events.emit('show-floating-text', { + x: gridX * 48, + y: gridY * 48, + text: '🚫 Unlock farm first!', + color: '#ff0000' + }); + } + return false; + } + // Check if already tilled const key = `${gridX},${gridY}`; if (this.isTilled(gridX, gridY)) { diff --git a/src/systems/Flat2DTerrainSystem.js b/src/systems/Flat2DTerrainSystem.js index 8cbee1c..85a575d 100644 --- a/src/systems/Flat2DTerrainSystem.js +++ b/src/systems/Flat2DTerrainSystem.js @@ -16,6 +16,9 @@ class Flat2DTerrainSystem { this.pathsLayer = null; this.decorLayer = null; + // Decoration tracking (for interaction system) + this.decorationsMap = new Map(); + // Textures ready flag this.texturesReady = false; diff --git a/src/systems/MicroFarmSystem.js b/src/systems/MicroFarmSystem.js new file mode 100644 index 0000000..ff3d4db --- /dev/null +++ b/src/systems/MicroFarmSystem.js @@ -0,0 +1,331 @@ +// 🌱 MICRO FARM SYSTEM - Phase 37 +// Začetna 8x8 parcela z postopno širitvijo + +class MicroFarmSystem { + constructor(scene) { + this.scene = scene; + + // MICRO FARM CONFIG + this.farmCenterX = 50; // Center of 100x100 map + this.farmCenterY = 50; + this.farmSize = 8; // 8x8 tiles (initial) + + // EXPANSION SYSTEM + this.unlockedTiles = new Set(); // Tracks unlocked tiles + this.expansionCost = 50; // Gold per 2x2 expansion + + // LAND TYPES + this.landTypes = { + GRASS: 'grass', // Free to use + FOREST: 'forest', // Needs clearing (trees) + ROCKY: 'rocky', // Needs mining (rocks) + SWAMP: 'swamp' // Needs drainage (water) + }; + + this.init(); + } + + init() { + console.log('🌱 MicroFarmSystem initialized'); + + // Unlock initial 8x8 farm + this.unlockInitialFarm(); + + // Create visual boundaries + this.createFarmBoundaries(); + + // Render locked tile overlay + this.renderLockedTileOverlay(); + + // Create expansion UI buttons + this.createExpansionUI(); + } + + createExpansionUI() { + // Create UI buttons for farm expansion + const uiScene = this.scene.scene.get('UIScene'); + if (!uiScene) { + console.warn('⚠️ UIScene not found - cannot create expansion UI'); + return; + } + + // Store reference + this.uiScene = uiScene; + this.expansionButtons = []; + + const buttonSize = 40; + const buttonColor = 0x8B4513; // Brown + const buttonHoverColor = 0xD2691E; + const expandCost = this.expansionCost; + + // Button positions relative to farm center + const farmWorldX = this.farmCenterX * 48; + const farmWorldY = this.farmCenterY * 48; + const farmPixelSize = this.farmSize * 48; + const halfSize = farmPixelSize / 2; + + const buttons = [ + { dir: 'north', x: farmWorldX, y: farmWorldY - halfSize - 60, icon: '⬆️' }, + { dir: 'south', x: farmWorldX, y: farmWorldY + halfSize + 60, icon: '⬇️' }, + { dir: 'east', x: farmWorldX + halfSize + 60, y: farmWorldY, icon: '➡️' }, + { dir: 'west', x: farmWorldX - halfSize - 60, y: farmWorldY, icon: '⬅️' } + ]; + + buttons.forEach(btn => { + // Button background + const bg = this.scene.add.rectangle(btn.x, btn.y, buttonSize, buttonSize, buttonColor); + bg.setStrokeStyle(2, 0xFFFFFF); + bg.setDepth(10); + bg.setInteractive({ useHandCursor: true }); + + // Button text + const text = this.scene.add.text(btn.x, btn.y, btn.icon, { + fontSize: '20px', + color: '#ffffff' + }).setOrigin(0.5); + text.setDepth(11); + + // Cost label + const costLabel = this.scene.add.text(btn.x, btn.y + 30, `${expandCost}g`, { + fontSize: '12px', + color: '#FFD700', + fontStyle: 'bold' + }).setOrigin(0.5); + costLabel.setDepth(11); + + // Hover effects + bg.on('pointerover', () => { + bg.setFillStyle(buttonHoverColor); + bg.setScale(1.1); + }); + + bg.on('pointerout', () => { + bg.setFillStyle(buttonColor); + bg.setScale(1.0); + }); + + // Click handler + bg.on('pointerdown', () => { + this.tryExpandFarm(btn.dir); + }); + + this.expansionButtons.push({ bg, text, costLabel, dir: btn.dir }); + }); + + console.log('✅ Expansion UI created!'); + } + + tryExpandFarm(direction) { + // Check if player has enough gold + const inv = this.scene.inventorySystem; + if (!inv || inv.gold < this.expansionCost) { + console.log(`❌ Not enough gold! Need ${this.expansionCost}g`); + + if (this.scene.events) { + this.scene.events.emit('show-floating-text', { + x: this.scene.cameras.main.width / 2, + y: 100, + text: `Need ${this.expansionCost} gold!`, + color: '#ff0000' + }); + } + return; + } + + // Deduct gold + inv.gold -= this.expansionCost; + + // Expand farm + this.expandFarm(direction); + + // Success feedback + if (this.scene.events) { + this.scene.events.emit('show-floating-text', { + x: this.scene.cameras.main.width / 2, + y: 100, + text: `✅ Farm expanded ${direction.toUpperCase()}!`, + color: '#00ff00' + }); + } + + console.log(`✅ Farm expanded ${direction}! (-${this.expansionCost}g)`); + } + + unlockInitialFarm() { + // Unlock central 8x8 tiles + const halfSize = Math.floor(this.farmSize / 2); + + for (let y = this.farmCenterY - halfSize; y < this.farmCenterY + halfSize; y++) { + for (let x = this.farmCenterX - halfSize; x < this.farmCenterX + halfSize; x++) { + const tileKey = `${x},${y}`; + this.unlockedTiles.add(tileKey); + } + } + + console.log(`✅ Unlocked ${this.unlockedTiles.size} tiles (8x8 micro farm)`); + } + + createFarmBoundaries() { + // Visual indicator of farm boundaries + const graphics = this.scene.add.graphics(); + const halfSize = Math.floor(this.farmSize / 2); + + const startX = (this.farmCenterX - halfSize) * 48; + const startY = (this.farmCenterY - halfSize) * 48; + const width = this.farmSize * 48; + const height = this.farmSize * 48; + + // Farm border (white dashed line) + graphics.lineStyle(3, 0xFFFFFF, 0.8); + graphics.strokeRect(startX, startY, width, height); + + // Corner markers + graphics.fillStyle(0xFFFFFF, 0.9); + const markerSize = 8; + graphics.fillRect(startX - markerSize / 2, startY - markerSize / 2, markerSize, markerSize); + graphics.fillRect(startX + width - markerSize / 2, startY - markerSize / 2, markerSize, markerSize); + graphics.fillRect(startX - markerSize / 2, startY + height - markerSize / 2, markerSize, markerSize); + graphics.fillRect(startX + width - markerSize / 2, startY + height - markerSize / 2, markerSize, markerSize); + + graphics.setDepth(5); // Above ground, below player + + // Store graphics for later updates + this.boundaryGraphics = graphics; + } + + renderLockedTileOverlay() { + // Render dark overlay on locked tiles + if (!this.scene || !this.lockedOverlayGraphics) { + // Create overlay graphics if not exists + this.lockedOverlayGraphics = this.scene.add.graphics(); + this.lockedOverlayGraphics.setDepth(4); // Above ground, below boundaries + } + + this.lockedOverlayGraphics.clear(); + + // Darken all tiles that are NOT unlocked + const halfSize = Math.floor(this.farmSize / 2); + const farmStartX = this.farmCenterX - halfSize; + const farmEndX = this.farmCenterX + halfSize; + const farmStartY = this.farmCenterY - halfSize; + const farmEndY = this.farmCenterY + halfSize; + + // Render grid of locked tiles + const viewRange = 15; // Show some area around farm + for (let y = this.farmCenterY - viewRange; y < this.farmCenterY + viewRange; y++) { + for (let x = this.farmCenterX - viewRange; x < this.farmCenterX + viewRange; x++) { + // Skip if within farm boundaries + if (x >= farmStartX && x < farmEndX && y >= farmStartY && y < farmEndY) { + continue; + } + + // Draw dark overlay (lighter) + const worldX = x * 48; + const worldY = y * 48; + this.lockedOverlayGraphics.fillStyle(0x000000, 0.3); // 0.5 -> 0.3 + this.lockedOverlayGraphics.fillRect(worldX, worldY, 48, 48); + } + } + + console.log('🔒 Locked tile overlay rendered!'); + } + + isTileUnlocked(tileX, tileY) { + const tileKey = `${tileX},${tileY}`; + return this.unlockedTiles.has(tileKey); + } + + canExpand(direction) { + // Check if expansion in direction is possible + // direction: 'north', 'south', 'east', 'west' + // TODO: Implement expansion logic + return true; + } + + expandFarm(direction) { + // Unlock 2x2 tiles in specified direction + const halfSize = Math.floor(this.farmSize / 2); + const expansionSize = 2; // Unlock 2x2 tiles at a time + + let newTiles = []; + + switch (direction) { + case 'north': + for (let y = this.farmCenterY - halfSize - expansionSize; y < this.farmCenterY - halfSize; y++) { + for (let x = this.farmCenterX - halfSize; x < this.farmCenterX + halfSize; x++) { + newTiles.push({ x, y }); + } + } + break; + + case 'south': + for (let y = this.farmCenterY + halfSize; y < this.farmCenterY + halfSize + expansionSize; y++) { + for (let x = this.farmCenterX - halfSize; x < this.farmCenterX + halfSize; x++) { + newTiles.push({ x, y }); + } + } + break; + + case 'east': + for (let y = this.farmCenterY - halfSize; y < this.farmCenterY + halfSize; y++) { + for (let x = this.farmCenterX + halfSize; x < this.farmCenterX + halfSize + expansionSize; x++) { + newTiles.push({ x, y }); + } + } + break; + + case 'west': + for (let y = this.farmCenterY - halfSize; y < this.farmCenterY + halfSize; y++) { + for (let x = this.farmCenterX - halfSize - expansionSize; x < this.farmCenterX - halfSize; x++) { + newTiles.push({ x, y }); + } + } + break; + } + + // Unlock the tiles + newTiles.forEach(tile => { + const tileKey = `${tile.x},${tile.y}`; + this.unlockedTiles.add(tileKey); + }); + + // Update farm size + if (direction === 'north' || direction === 'south') { + this.farmSize += expansionSize; + } else { + this.farmSize += expansionSize; + } + + // Update visuals + this.createFarmBoundaries(); // Redraw boundaries + this.renderLockedTileOverlay(); // Update overlay + + console.log(`🔓 Expanded farm ${direction}! +${newTiles.length} tiles. Total: ${this.unlockedTiles.size}`); + } + + getLandType(tileX, tileY) { + // Determine land type based on tile position + // TODO: Use terrain system data + + // For now, return grass for unlocked tiles + if (this.isTileUnlocked(tileX, tileY)) { + return this.landTypes.GRASS; + } + + // Surrounding areas have different types + const distFromCenter = Math.sqrt( + Math.pow(tileX - this.farmCenterX, 2) + + Math.pow(tileY - this.farmCenterY, 2) + ); + + if (distFromCenter < 10) return this.landTypes.GRASS; + if (distFromCenter < 15) return this.landTypes.FOREST; + if (distFromCenter < 20) return this.landTypes.ROCKY; + return this.landTypes.SWAMP; + } + + destroy() { + // Cleanup + this.unlockedTiles.clear(); + } +}