// Texture Generator // Proceduralno generiranje tekstur in sprite-ov class TextureGenerator { // Generiraj player sprite (32x32px pixel art) static createPlayerSprite(scene, key = 'player') { if (scene.textures.exists(key)) return; const canvas = scene.textures.createCanvas(key, 32, 32); const ctx = canvas.getContext(); ctx.clearRect(0, 0, 32, 32); // Body ctx.fillStyle = '#A0522D'; // Sienna skin ctx.fillRect(10, 8, 12, 12); // Head ctx.fillStyle = '#2F4F4F'; // DarkSlateGray shirt ctx.fillRect(8, 20, 16, 12); // Eyes ctx.fillStyle = '#FFFFFF'; ctx.fillRect(12, 12, 2, 2); ctx.fillRect(18, 12, 2, 2); ctx.fillStyle = '#000000'; ctx.fillRect(13, 12, 1, 1); ctx.fillRect(19, 12, 1, 1); // Hair ctx.fillStyle = '#000000'; ctx.fillRect(10, 6, 12, 4); ctx.fillRect(8, 8, 2, 6); ctx.fillRect(22, 8, 2, 6); canvas.refresh(); } // Generiraj walking animacijo static createPlayerWalkSprite(scene, key = 'player_walk') { if (scene.textures.exists(key)) return; const canvas = scene.textures.createCanvas(key, 128, 32); const ctx = canvas.getContext(); // Simple placeholders for 4 frames for (let i = 0; i < 4; i++) { ctx.fillStyle = '#2F4F4F'; ctx.fillRect(i * 32 + 8, 6, 16, 26); } canvas.refresh(); } // Generiraj NPC sprite static createNPCSprite(scene, key = 'npc', type = 'zombie') { if (scene.textures.exists(key)) return; const canvas = scene.textures.createCanvas(key, 32, 32); const ctx = canvas.getContext(); ctx.clearRect(0, 0, 32, 32); // Elite Zombie: Red body, glowing pink eyes if (type === 'elite_zombie') { ctx.fillStyle = '#8B0000'; // DarkRed ctx.fillRect(8, 6, 16, 26); // Glowing Eyes ctx.fillStyle = '#FF1493'; // Deep Pink (glow) ctx.fillRect(10, 10, 4, 4); ctx.fillRect(20, 10, 4, 4); } else { ctx.fillStyle = (type === 'zombie') ? '#556B2F' : '#DEB887'; ctx.fillRect(8, 6, 16, 26); // Eyes (Red for zombie) ctx.fillStyle = (type === 'zombie') ? '#FF0000' : '#000000'; ctx.fillRect(10, 10, 4, 4); ctx.fillRect(20, 10, 4, 4); } canvas.refresh(); } static createMerchantSprite(scene, key = 'merchant_texture') { if (scene.textures.exists(key)) return; console.log('πŸ§™β€β™‚οΈ Creating Merchant Sprite Texture...'); try { const canvas = scene.textures.createCanvas(key, 32, 32); const ctx = canvas.getContext(); ctx.clearRect(0, 0, 32, 32); // Body (BRIGHT GOLD robe - zelo viden!) ctx.fillStyle = '#FFD700'; // Gold ctx.fillRect(8, 6, 16, 26); // Head ctx.fillStyle = '#FFE4C4'; // Bisque skin ctx.fillRect(10, 4, 12, 12); // Hat (Red Merchants Hat) ctx.fillStyle = '#8B0000'; // DarkRed ctx.fillRect(8, 2, 16, 4); ctx.fillRect(10, 0, 12, 2); // Hat Top // Backpack (Brown - visible on sides) ctx.fillStyle = '#8B4513'; ctx.fillRect(4, 10, 4, 14); // Left side pack ctx.fillRect(24, 10, 4, 14); // Right side pack // Straps ctx.fillStyle = '#A0522D'; ctx.fillRect(8, 10, 16, 2); // Eyes ctx.fillStyle = '#000000'; ctx.fillRect(13, 8, 2, 2); ctx.fillRect(17, 8, 2, 2); // Beard (White) ctx.fillStyle = '#F5F5F5'; ctx.fillRect(10, 12, 12, 4); ctx.fillRect(12, 16, 8, 2); canvas.refresh(); console.log('βœ… Merchant Sprite Created!'); } catch (error) { console.error('❌ ERROR creating merchant sprite:', error); } } static createCloudSprite(scene, key = 'cloud') { if (scene.textures.exists(key)) return; const canvas = scene.textures.createCanvas(key, 64, 32); const ctx = canvas.getContext(); ctx.clearRect(0, 0, 64, 32); ctx.fillStyle = 'rgba(255,255,255,0.6)'; ctx.beginPath(); ctx.arc(20, 20, 15, 0, Math.PI * 2); ctx.fill(); ctx.beginPath(); ctx.arc(35, 15, 18, 0, Math.PI * 2); ctx.fill(); ctx.beginPath(); ctx.arc(50, 20, 12, 0, Math.PI * 2); ctx.fill(); canvas.refresh(); } static createCropSprite(scene, key, stage = 4) { if (scene.textures.exists(key)) return; const canvas = scene.textures.createCanvas(key, 32, 32); const ctx = canvas.getContext(); ctx.clearRect(0, 0, 32, 32); ctx.fillStyle = '#228B22'; // Stem const h = stage * 5; ctx.fillRect(14, 32 - h, 4, h); if (stage >= 3) { ctx.fillStyle = '#FFD700'; // Wheat head ctx.beginPath(); ctx.arc(16, 32 - h, 6, 0, Math.PI * 2); ctx.fill(); } if (stage === 5) { // Withered ctx.fillStyle = '#8B4513'; ctx.fillRect(14, 20, 4, 12); } canvas.refresh(); } static createStructureSprite(scene, key, type) { if (scene.textures.exists(key)) return; const width = (type === 'house' || type === 'ruin') ? 64 : 32; const height = (type === 'house' || type === 'ruin') ? 64 : 32; const canvas = scene.textures.createCanvas(key, width, height); const ctx = canvas.getContext(); ctx.clearRect(0, 0, width, height); if (type === 'ruin') { // Isometric Ruin / Rocks for user ctx.fillStyle = '#696969'; // DimGray // Big Rock 1 ctx.beginPath(); ctx.arc(20, 50, 14, 0, Math.PI * 2); ctx.fill(); // Big Rock 2 ctx.beginPath(); ctx.arc(45, 55, 12, 0, Math.PI * 2); ctx.fill(); // Details ctx.fillStyle = '#555555'; ctx.beginPath(); ctx.arc(25, 45, 6, 0, Math.PI * 2); ctx.fill(); } else { // Generic box for others ctx.fillStyle = '#8B4513'; ctx.fillRect(0, 0, width, height); } canvas.refresh(); } // ========== 3D VOLUMETRIC GENERATORS (RESTORED) ========== // Generiraj 3D volumetric tree (Minecraft-style) static createTreeSprite(scene, key = 'tree') { if (scene.textures.exists(key)) return; const size = 64; const height = 96; // Taller for 3D effect const canvas = scene.textures.createCanvas(key, size, height); const ctx = canvas.getContext(); ctx.clearRect(0, 0, size, height); // Helper to draw isometric-ish cube face const drawCube = (x, y, w, h, d, colorTop, colorSide, colorFront) => { // Front face ctx.fillStyle = colorFront; ctx.fillRect(x, y + d, w, h); // Top face (fake perspective) ctx.fillStyle = colorTop; ctx.beginPath(); ctx.moveTo(x, y + d); ctx.lineTo(x + d, y); ctx.lineTo(x + w + d, y); ctx.lineTo(x + w, y + d); ctx.closePath(); ctx.fill(); // Side face ctx.fillStyle = colorSide; ctx.beginPath(); ctx.moveTo(x + w, y + d); ctx.lineTo(x + w + d, y); ctx.lineTo(x + w + d, y + h); ctx.lineTo(x + w, y + h + d); ctx.closePath(); ctx.fill(); }; // Trunk const trunkColor = '#8B4513'; const trunkTop = '#A0522D'; const trunkDark = '#663300'; drawCube(24, 60, 16, 24, 8, trunkTop, trunkDark, trunkColor); // Leaves chunks (Minecraft style) const leafColor = '#228B22'; // ForestGreen const leafTop = '#32CD32'; // LimeGreen const leafDark = '#006400'; // DarkGreen // Bottom layer drawCube(12, 30, 40, 20, 10, leafTop, leafDark, leafColor); // Top layer drawCube(20, 10, 24, 20, 8, leafTop, leafDark, leafColor); canvas.refresh(); } // Generiraj 3D volumetric Rock (Gray Cubes) static createRockSprite(scene, key = 'rock') { if (scene.textures.exists(key)) return; const size = 48; const canvas = scene.textures.createCanvas(key, size, size); const ctx = canvas.getContext(); ctx.clearRect(0, 0, size, size); // Simple Voxel Draw const drawVoxel = (x, y, c) => { ctx.fillStyle = c; ctx.fillRect(x, y, 10, 10); ctx.fillStyle = '#444444'; // Side ctx.fillRect(x + 10, y, 4, 10); ctx.fillStyle = '#333333'; // Bottom ctx.fillRect(x, y + 10, 10, 4); }; const gray = '#808080'; drawVoxel(10, 25, gray); drawVoxel(20, 20, gray); drawVoxel(15, 15, gray); canvas.refresh(); } // Generiraj 3D flower (simple volumetric) static createFlowerSprite(scene, key = 'flower') { if (scene.textures.exists(key)) return; const size = 32; const canvas = scene.textures.createCanvas(key, size, size); const ctx = canvas.getContext(); ctx.clearRect(0, 0, size, size); ctx.fillStyle = '#228B22'; // Stem ctx.fillRect(15, 10, 2, 10); ctx.fillStyle = '#FF69B4'; // Flower ctx.fillRect(12, 8, 8, 8); canvas.refresh(); } static createBushSprite(scene, key = 'bush') { if (scene.textures.exists(key)) return; const size = 32; const canvas = scene.textures.createCanvas(key, size, size); const ctx = canvas.getContext(); ctx.clearRect(0, 0, size, size); ctx.fillStyle = '#228B22'; ctx.beginPath(); ctx.arc(16, 16, 12, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = 'red'; // Berries ctx.beginPath(); ctx.arc(12, 12, 2, 0, Math.PI * 2); ctx.fill(); ctx.beginPath(); ctx.arc(20, 18, 2, 0, Math.PI * 2); ctx.fill(); canvas.refresh(); } static createGravestoneSprite(scene, key = 'gravestone') { if (scene.textures.exists(key)) return; const canvas = scene.textures.createCanvas(key, 32, 32); const ctx = canvas.getContext(); ctx.clearRect(0, 0, 32, 32); ctx.fillStyle = '#808080'; ctx.fillRect(8, 8, 16, 24); ctx.beginPath(); ctx.arc(16, 8, 8, Math.PI, 0); ctx.fill(); canvas.refresh(); } static createChestSprite(scene, key = 'chest') { if (scene.textures.exists(key)) return; const canvas = scene.textures.createCanvas(key, 32, 32); const ctx = canvas.getContext(); ctx.clearRect(0, 0, 32, 32); // Chest body (brown) ctx.fillStyle = '#8B4513'; // SaddleBrown ctx.fillRect(6, 12, 20, 16); // Lock (gold) ctx.fillStyle = '#FFD700'; ctx.fillRect(14, 18, 4, 6); // Lid ctx.fillStyle = '#A0522D'; ctx.fillRect(6, 8, 20, 4); canvas.refresh(); } static createSpawnerSprite(scene, key = 'spawner') { if (scene.textures.exists(key)) return; const canvas = scene.textures.createCanvas(key, 32, 32); const ctx = canvas.getContext(); ctx.clearRect(0, 0, 32, 32); // Dark portal/spawner ctx.fillStyle = '#2F4F4F'; // DarkSlateGray ctx.fillRect(8, 8, 16, 16); // Red glow ctx.fillStyle = '#8B0000'; ctx.fillRect(10, 10, 12, 12); // Center black hole ctx.fillStyle = '#000000'; ctx.beginPath(); ctx.arc(16, 16, 4, 0, Math.PI * 2); ctx.fill(); canvas.refresh(); } static createSignpostSprite(scene, key = 'signpost', text = 'β†’') { if (scene.textures.exists(key)) return; const canvas = scene.textures.createCanvas(key, 32, 32); const ctx = canvas.getContext(); ctx.clearRect(0, 0, 32, 32); // Wooden post (brown) ctx.fillStyle = '#8B4513'; ctx.fillRect(14, 8, 4, 24); // Sign board ctx.fillStyle = '#D2691E'; ctx.fillRect(6, 10, 20, 12); // Border ctx.strokeStyle = '#000'; ctx.lineWidth = 1; ctx.strokeRect(6, 10, 20, 12); // Text ctx.fillStyle = '#000'; ctx.font = 'bold 14px Courier'; ctx.textAlign = 'center'; ctx.fillText(text, 16, 19); canvas.refresh(); } static createToolSprites(scene) { // --- REALISTIC TOOLS (Procedural Generation) --- // 1. AXE (Sekira) if (!scene.textures.exists('item_axe')) { const c = scene.textures.createCanvas('item_axe', 32, 32); const ctx = c.getContext(); ctx.clearRect(0, 0, 32, 32); // Handle (Wood) ctx.fillStyle = '#8B4513'; ctx.fillRect(14, 12, 4, 18); // Head (Metal) ctx.fillStyle = '#708090'; // SlateGray ctx.beginPath(); ctx.moveTo(16, 12); ctx.lineTo(24, 6); // Top edge ctx.lineTo(24, 18); // Bottom edge ctx.lineTo(16, 14); // Back to handle ctx.fill(); // Edge (Sharp) ctx.fillStyle = '#C0C0C0'; // Silver ctx.fillRect(23, 6, 2, 12); c.refresh(); } // 2. PICKAXE (Kramp) if (!scene.textures.exists('item_pickaxe')) { const c = scene.textures.createCanvas('item_pickaxe', 32, 32); const ctx = c.getContext(); ctx.clearRect(0, 0, 32, 32); // Handle ctx.fillStyle = '#8B4513'; ctx.fillRect(14, 10, 4, 20); // Head (Curved Metal) ctx.fillStyle = '#696969'; // DimGray ctx.beginPath(); ctx.moveTo(6, 14); // Left tip ctx.quadraticCurveTo(16, 4, 26, 14); // Curve over handle ctx.lineTo(26, 16); ctx.quadraticCurveTo(16, 8, 6, 16); ctx.fill(); // Tips ctx.fillStyle = '#DCDCDC'; ctx.fillRect(5, 14, 2, 2); ctx.fillRect(25, 14, 2, 2); c.refresh(); } // 3. HOE (Motika) if (!scene.textures.exists('item_hoe')) { const c = scene.textures.createCanvas('item_hoe', 32, 32); const ctx = c.getContext(); ctx.clearRect(0, 0, 32, 32); // Handle ctx.fillStyle = '#8B4513'; ctx.fillRect(14, 6, 4, 24); // Head ctx.fillStyle = '#778899'; // LightSlateGray ctx.fillRect(12, 6, 10, 4); // Top bar ctx.fillRect(12, 6, 4, 8); // Blade down // Blade Edge ctx.fillStyle = '#C0C0C0'; ctx.fillRect(12, 12, 4, 2); c.refresh(); } // 4. SWORD (Meč) if (!scene.textures.exists('item_sword')) { const c = scene.textures.createCanvas('item_sword', 32, 32); const ctx = c.getContext(); ctx.clearRect(0, 0, 32, 32); // Handle ctx.fillStyle = '#8B4513'; ctx.fillRect(15, 24, 2, 6); // Pommel ctx.fillStyle = '#FFD700'; // Gold ctx.fillRect(14, 29, 4, 2); // Guard ctx.fillStyle = '#FFD700'; ctx.fillRect(11, 22, 10, 2); // Blade ctx.fillStyle = '#C0C0C0'; // Silver ctx.fillRect(14, 4, 4, 18); // Blood Groove / Shine ctx.fillStyle = '#F0F8FF'; // AliceBlue ctx.fillRect(15, 4, 2, 18); c.refresh(); } // 5. WATERING CAN (Zalivalka) if (!scene.textures.exists('item_watering_can')) { const c = scene.textures.createCanvas('item_watering_can', 32, 32); const ctx = c.getContext(); ctx.clearRect(0, 0, 32, 32); // Body ctx.fillStyle = '#A9A9A9'; // DarkGray ctx.fillRect(8, 12, 16, 14); // Handle ctx.strokeStyle = '#696969'; ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo(8, 14); ctx.quadraticCurveTo(4, 10, 8, 6); ctx.lineTo(20, 6); ctx.stroke(); // Spout ctx.fillStyle = '#A9A9A9'; ctx.beginPath(); ctx.moveTo(24, 16); ctx.lineTo(30, 10); ctx.lineTo(28, 20); ctx.fill(); c.refresh(); } } static createItemSprites(scene) { // Placeholder item generation const items = [ { name: 'wood', color: '#8B4513' }, // Rjava { name: 'stone', color: '#808080' }, // Siva { name: 'seeds', color: '#90EE90' }, // Svetlo zelena { name: 'wheat', color: '#FFD700' }, // Zlata { name: 'corn', color: '#FFD700' }, // Zlata (Corn) { name: 'seeds_corn', color: '#B22222' },// FireBrick seeds { name: 'item_bone', color: '#F5F5DC' }, // Beige { name: 'item_scrap', color: '#B87333' }, // Copper/Bronze (kovinski kos) { name: 'item_chip', color: '#00CED1' } // DarkTurquoise (elektronski chip) ]; items.forEach(item => { const it = typeof item === 'string' ? item : item.name; const color = typeof item === 'string' ? 'gold' : item.color; const k = (it.startsWith('item_')) ? it : 'item_' + it; if (!scene.textures.exists(k)) { const c = scene.textures.createCanvas(k, 32, 32); const x = c.getContext(); x.clearRect(0, 0, 32, 32); x.fillStyle = color; x.beginPath(); x.arc(16, 16, 10, 0, Math.PI * 2); x.fill(); c.refresh(); } }); } static createSaplingSprite(scene, key = 'tree_sapling') { if (scene.textures.exists(key)) return; const size = 32; const canvas = scene.textures.createCanvas(key, size, size); const ctx = canvas.getContext(); ctx.clearRect(0, 0, size, size); // Majhno steblo ctx.fillStyle = '#8B4513'; ctx.fillRect(14, 20, 4, 12); // Parnosti listov ctx.fillStyle = '#32CD32'; ctx.beginPath(); ctx.arc(12, 18, 4, 0, Math.PI * 2); ctx.fill(); ctx.beginPath(); ctx.arc(20, 18, 4, 0, Math.PI * 2); ctx.fill(); ctx.beginPath(); ctx.arc(16, 12, 5, 0, Math.PI * 2); ctx.fill(); canvas.refresh(); } static createCornSprites(scene) { for (let i = 1; i <= 4; i++) { const key = `corn_stage_${i}`; if (scene.textures.exists(key)) continue; // Corn is taller const canvas = scene.textures.createCanvas(key, 32, 64); const ctx = canvas.getContext(); ctx.clearRect(0, 0, 32, 64); const startY = 64; // Stalk ctx.fillStyle = '#556B2F'; // DarkOliveGreen const height = 10 + (i * 10); ctx.fillRect(14, startY - height, 4, height); // Leaves ctx.fillStyle = '#32CD32'; // LimeGreen if (i >= 2) { ctx.beginPath(); ctx.ellipse(10, startY - height + 10, 8, 3, 0.5, 0, Math.PI * 2); ctx.fill(); ctx.beginPath(); ctx.ellipse(22, startY - height + 15, 8, 3, -0.5, 0, Math.PI * 2); ctx.fill(); } // Cobs (Only stage 4) if (i === 4) { ctx.fillStyle = '#FFD700'; // Gold ctx.fillRect(12, startY - height + 20, 4, 8); ctx.fillRect(18, startY - height + 25, 4, 8); } canvas.refresh(); } } // Helper to generate ALL textures at once generateAll() { TextureGenerator.createPlayerSprite(this.scene); TextureGenerator.createPlayerWalkSprite(this.scene); TextureGenerator.createNPCSprite(this.scene, 'npc', 'zombie'); TextureGenerator.createMerchantSprite(this.scene, 'merchant_texture'); TextureGenerator.createFlowerSprite(this.scene); TextureGenerator.createBushSprite(this.scene); TextureGenerator.createSaplingSprite(this.scene, 'tree_sapling'); TextureGenerator.createTreeSprite(this.scene); TextureGenerator.createRockSprite(this.scene); TextureGenerator.createCloudSprite(this.scene); // Crops TextureGenerator.createCropSprite(this.scene, 'crop_stage_1', 1); TextureGenerator.createCropSprite(this.scene, 'crop_stage_2', 2); TextureGenerator.createCropSprite(this.scene, 'crop_stage_3', 3); TextureGenerator.createCropSprite(this.scene, 'crop_stage_4', 4); TextureGenerator.createCornSprites(this.scene); // Added Corn TextureGenerator.createGravestoneSprite(this.scene); TextureGenerator.createToolSprites(this.scene); TextureGenerator.createItemSprites(this.scene); } constructor(scene) { this.scene = scene; } }