// Flat2DTerrainSystem - Complete 2D top-down tile rendering // Replaces isometric TerrainSystem for Stardew Valley style class Flat2DTerrainSystem { constructor(scene) { this.scene = scene; this.tileSize = 48; this.width = 100; this.height = 100; // Tile map data this.tiles = []; // Rendering containers this.groundLayer = null; this.pathsLayer = null; this.decorLayer = null; // Textures ready flag this.texturesReady = false; console.log('🎨 Flat2DTerrainSystem initialized'); } async generate() { console.log('πŸ—ΊοΈ Generating flat 2D map...'); // Create textures first this.createTileTextures(); // Load map data if (typeof Map2DData !== 'undefined') { this.tiles = Map2DData.generateMap(); console.log('βœ… Map data generated:', this.tiles.length, 'rows'); } else { console.error('❌ Map2DData not loaded!'); this.createFallbackMap(); } // Render the map this.renderMap(); console.log('βœ… Flat 2D map ready!'); } createTileTextures() { const graphics = this.scene.make.graphics({ x: 0, y: 0, add: false }); const size = this.tileSize; // GRASS - VIBRANT RICH GREEN! 🌿 graphics.clear(); graphics.fillStyle(0x59b36a); // BRIGHT rich green! graphics.fillRect(0, 0, size, size); // Add grass texture - DARKER spots for (let i = 0; i < 15; i++) { const x = Math.random() * size; const y = Math.random() * size; graphics.fillStyle(0x3a8d4f, 0.5); graphics.fillCircle(x, y, 2 + Math.random() * 3); } // LIGHTER highlights for (let i = 0; i < 10; i++) { const x = Math.random() * size; const y = Math.random() * size; graphics.fillStyle(0x7ad389, 0.6); graphics.fillCircle(x, y, 1.5); } graphics.generateTexture('tile2d_grass', size, size); // GRASS WITH FLOWERS graphics.clear(); graphics.fillStyle(0x4a9d5f); graphics.fillRect(0, 0, size, size); // Grass texture for (let i = 0; i < 10; i++) { graphics.fillStyle(0x3a8d4f, 0.4); graphics.fillCircle(Math.random() * size, Math.random() * size, 1.5); } // Small flowers const flowerColors = [0xff6b6b, 0xffd93d, 0x6bcbff]; for (let i = 0; i < 3; i++) { graphics.fillStyle(flowerColors[Math.floor(Math.random() * 3)]); graphics.fillCircle(Math.random() * size, Math.random() * size, 2); } graphics.generateTexture('tile2d_grass_flowers', size, size); // DIRT - VIBRANT BROWN! 🟀 graphics.clear(); graphics.fillStyle(0xa87f5a); // BRIGHT brown! graphics.fillRect(0, 0, size, size); // Dirt texture - darker clumps for (let i = 0; i < 20; i++) { graphics.fillStyle(0x7a5f3a, 0.6); graphics.fillCircle(Math.random() * size, Math.random() * size, 3 + Math.random() * 4); } // Lighter spots for (let i = 0; i < 12; i++) { graphics.fillStyle(0xc89f6f, 0.5); graphics.fillCircle(Math.random() * size, Math.random() * size, 2); } graphics.generateTexture('tile2d_dirt', size, size); // DIRT EDGE - Transition to grass graphics.clear(); graphics.fillGradientStyle(0x8b6f47, 0x8b6f47, 0x6a9d5f, 0x6a9d5f, 1); graphics.fillRect(0, 0, size, size); graphics.generateTexture('tile2d_dirt_edge', size, size); // WATER - BRIGHT BLUE! πŸ’§ graphics.clear(); graphics.fillStyle(0x3498db); // VIBRANT blue! graphics.fillRect(0, 0, size, size); // Water highlights - darker depth for (let i = 0; i < 8; i++) { graphics.fillStyle(0x2078ab, 0.4); graphics.fillCircle(Math.random() * size, Math.random() * size, 4 + Math.random() * 6); } // Light reflections for (let i = 0; i < 12; i++) { graphics.fillStyle(0x5dade2, 0.5); graphics.fillCircle(Math.random() * size, Math.random() * size, 2); } // White sparkles for (let i = 0; i < 10; i++) { graphics.fillStyle(0xffffff, 0.6); graphics.fillCircle(Math.random() * size, Math.random() * size, 1); } graphics.generateTexture('tile2d_water', size, size); // WATER EDGE - Lighter border graphics.clear(); graphics.fillGradientStyle(0x4aacdc, 0x4aacdc, 0x1a5f7a, 0x1a5f7a, 0.7); graphics.fillRect(0, 0, size, size); graphics.generateTexture('tile2d_water_edge', size, size); // STONE - Gray graphics.clear(); graphics.fillStyle(0x808080); graphics.fillRect(0, 0, size, size); for (let i = 0; i < 12; i++) { graphics.fillStyle(0x606060, 0.6); graphics.fillCircle(Math.random() * size, Math.random() * size, 2 + Math.random() * 3); } graphics.generateTexture('tile2d_stone', size, size); graphics.destroy(); this.texturesReady = true; console.log('βœ… Tile textures created'); } renderMap() { // Create layer containers this.groundLayer = this.scene.add.container(0, 0); this.pathsLayer = this.scene.add.container(0, 0); this.decorLayer = this.scene.add.container(0, 0); // Set depths this.groundLayer.setDepth(1); this.pathsLayer.setDepth(2); this.decorLayer.setDepth(3); const size = this.tileSize; // Render all tiles for (let y = 0; y < this.height; y++) { for (let x = 0; x < this.width; x++) { const tile = this.tiles[y][x]; const worldX = x * size; const worldY = y * size; // Get texture key from tile type const textureKey = this.getTileTexture(tile.base); // Create tile sprite const tileSprite = this.scene.add.image(worldX, worldY, textureKey); tileSprite.setOrigin(0, 0); tileSprite.setDisplaySize(size, size); // Add to appropriate layer if (tile.base <= 1) { this.groundLayer.add(tileSprite); } else { this.pathsLayer.add(tileSprite); } // Add decoration if exists if (tile.decoration) { this.addDecoration(x, y, tile.decoration); } } } console.log('βœ… Map rendered: 3 layers created'); } getTileTexture(tileType) { const types = Map2DData.tileTypes; switch (tileType) { case types.GRASS: return 'tile2d_grass'; case types.GRASS_FLOWERS: return 'tile2d_grass_flowers'; case types.DIRT: return 'tile2d_dirt'; case types.DIRT_EDGE: return 'tile2d_dirt_edge'; case types.WATER: return 'tile2d_water'; case types.WATER_EDGE: return 'tile2d_water_edge'; case types.STONE: return 'tile2d_stone'; default: return 'tile2d_grass'; } } addDecoration(gridX, gridY, decorType) { const size = this.tileSize; const worldX = gridX * size + size / 2; const worldY = gridY * size + size / 2; const types = Map2DData.tileTypes; let sprite; switch (decorType) { case types.TREE: sprite = this.createTree(worldX, worldY); break; case types.FLOWER_RED: sprite = this.createFlower(worldX, worldY, 0xff6b6b); break; case types.FLOWER_YELLOW: sprite = this.createFlower(worldX, worldY, 0xffd93d); break; case types.FLOWER_BLUE: sprite = this.createFlower(worldX, worldY, 0x6bcbff); break; case types.LILY_PAD: sprite = this.createLilyPad(worldX, worldY); break; case types.BUSH: sprite = this.createBush(worldX, worldY); break; case 'puddle': sprite = this.createPuddle(worldX, worldY); break; } if (sprite) { this.decorLayer.add(sprite); } } createTree(x, y) { const graphics = this.scene.add.graphics(); // Trunk graphics.fillStyle(0x8B4513); graphics.fillRect(x - 6, y, 12, 20); // Crown (round) graphics.fillStyle(0x2d5016, 0.9); graphics.fillCircle(x, y - 10, 18); graphics.fillStyle(0x3a6b1f, 0.8); graphics.fillCircle(x - 5, y - 12, 14); graphics.fillCircle(x + 5, y - 8, 12); graphics.fillStyle(0x4a8d2f, 0.7); graphics.fillCircle(x, y - 15, 10); return graphics; } createFlower(x, y, color) { const graphics = this.scene.add.graphics(); // Petals graphics.fillStyle(color); for (let i = 0; i < 5; i++) { const angle = (Math.PI * 2 * i) / 5; const px = x + Math.cos(angle) * 3; const py = y + Math.sin(angle) * 3; graphics.fillCircle(px, py, 2); } // Center graphics.fillStyle(0xFFEB3B); graphics.fillCircle(x, y, 2); return graphics; } createLilyPad(x, y) { const graphics = this.scene.add.graphics(); // Lily pad (green circle) graphics.fillStyle(0x4a8d2f); graphics.fillCircle(x, y, 8); // Pink flower graphics.fillStyle(0xFF69B4); for (let i = 0; i < 5; i++) { const angle = (Math.PI * 2 * i) / 5; const px = x + Math.cos(angle) * 3; const py = y + Math.sin(angle) * 3; graphics.fillCircle(px, py, 2); } graphics.fillStyle(0xFFD700); graphics.fillCircle(x, y, 1.5); return graphics; } createBush(x, y) { const graphics = this.scene.add.graphics(); graphics.fillStyle(0x3a6b1f, 0.9); graphics.fillCircle(x, y, 10); graphics.fillCircle(x - 6, y + 2, 8); graphics.fillCircle(x + 6, y + 2, 8); graphics.fillStyle(0x4a8d2f, 0.7); graphics.fillCircle(x, y - 3, 6); return graphics; } createPuddle(x, y) { // Use existing puddle sprite if available if (this.scene.textures.exists('luza_sprite')) { const sprite = this.scene.add.image(x, y, 'luza_sprite'); sprite.setScale(0.8); sprite.setAlpha(0.4); return sprite; } // Fallback const graphics = this.scene.add.graphics(); graphics.fillStyle(0x4488bb, 0.5); graphics.fillEllipse(x, y, 12, 8); return graphics; } createFallbackMap() { // Create simple fallback if Map2DData fails for (let y = 0; y < this.height; y++) { this.tiles[y] = []; for (let x = 0; x < this.width; x++) { this.tiles[y][x] = { base: 0, // Grass decoration: null, walkable: true }; } } } getTile(x, y) { if (x < 0 || x >= this.width || y < 0 || y >= this.height) { return null; } // Safety check: ensure tiles array is initialized if (!this.tiles || !this.tiles[y]) { return null; } return this.tiles[y][x]; } isWalkable(x, y) { const tile = this.getTile(x, y); return tile ? tile.walkable : false; } update(time, delta) { // Reserved for animations (water waves, etc) } destroy() { if (this.groundLayer) this.groundLayer.destroy(); if (this.pathsLayer) this.pathsLayer.destroy(); if (this.decorLayer) this.decorLayer.destroy(); } }