// 🌱 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(); } }