class ParallaxSystem { constructor(scene) { this.scene = scene; this.layers = []; // Layer depths (Phaser depth sorting) this.DEPTH = { SKY: -1000, DISTANT_HILLS: -500, FAR_TREES: -100, TERRAIN: 0, GAME_OBJECTS: 1000, FOREGROUND_GRASS: 5000, FOREGROUND_LEAVES: 5500 }; this.init(); } init() { console.log('🌄 ParallaxSystem: Initialized'); // Layer 1: Sky/Hills (Distant background) // Layer 1: Sky/Hills (Disabled by request) // this.createSkyLayer(); // this.createDistantHills(); // Layer 4: Foreground overlay (High grass patches) this.createForegroundGrass(); } createSkyLayer() { // Gradient sky rectangle const width = 3000; const height = 2000; const skyBg = this.scene.add.rectangle(0, 0, width, height, 0x87CEEB); // Sky blue skyBg.setOrigin(0, 0); skyBg.setScrollFactor(0); // Fixed (no parallax) skyBg.setDepth(this.DEPTH.SKY); this.layers.push({ name: 'sky', objects: [skyBg], scrollFactor: 0 }); } createDistantHills() { // Create simple hill silhouettes in background const hillCount = 5; const hills = []; for (let i = 0; i < hillCount; i++) { const x = i * 800 - 1000; const y = 600; const width = Phaser.Math.Between(400, 800); const height = Phaser.Math.Between(150, 300); // Create hill as ellipse const hill = this.scene.add.ellipse(x, y, width, height, 0x4a5f3a); // Dark green hill.setAlpha(0.4); hill.setDepth(this.DEPTH.DISTANT_HILLS); hill.setScrollFactor(0.2, 0.2); // Slow parallax hills.push(hill); } this.layers.push({ name: 'distant_hills', objects: hills, scrollFactor: 0.2 }); } createForegroundGrass() { // Create tall grass patches that appear in front of player const grassPatches = []; const patchCount = 30; for (let i = 0; i < patchCount; i++) { const x = Phaser.Math.Between(-500, 2500); const y = Phaser.Math.Between(-500, 2500); const grass = this.createGrassPatch(x, y); grass.setDepth(this.DEPTH.FOREGROUND_GRASS); grass.setScrollFactor(1.05, 1.05); // Slight forward parallax grass.setAlpha(0.6); grassPatches.push(grass); } this.layers.push({ name: 'foreground_grass', objects: grassPatches, scrollFactor: 1.05 }); } createGrassPatch(x, y) { // Create procedural grass patch const graphics = this.scene.add.graphics(); // Draw several grass blades for (let i = 0; i < 6; i++) { const offsetX = Phaser.Math.Between(-10, 10); const offsetY = Phaser.Math.Between(-5, 5); const height = Phaser.Math.Between(20, 40); graphics.fillStyle(0x3a5f2a, 0.8); // Dark grass green // Draw grass blade (thin triangle) graphics.beginPath(); graphics.moveTo(x + offsetX, y + offsetY); graphics.lineTo(x + offsetX - 2, y + offsetY + height); graphics.lineTo(x + offsetX + 2, y + offsetY + height); graphics.closePath(); graphics.fillPath(); } return graphics; } update(playerX, playerY) { // Update foreground grass visibility based on player position // Hide/show grass patches that are too close to player for better gameplay const foregroundLayer = this.layers.find(l => l.name === 'foreground_grass'); if (!foregroundLayer) return; for (const grass of foregroundLayer.objects) { const distance = Phaser.Math.Distance.Between( grass.x, grass.y, playerX, playerY ); // Fade out grass when player is very close if (distance < 50) { grass.setAlpha(0.2); } else if (distance < 100) { grass.setAlpha(0.4); } else { grass.setAlpha(0.6); } } } addFarTree(x, y) { // Add a background tree (Layer 2) if (!this.scene.textures.exists('tree')) return; const tree = this.scene.add.sprite(x, y, 'tree'); tree.setDepth(this.DEPTH.FAR_TREES); tree.setScrollFactor(0.7, 0.7); // Medium parallax tree.setAlpha(0.7); tree.setScale(1.5); return tree; } addForegroundLeaves(x, y) { // Add falling leaves or branch overlay (Layer 4) const graphics = this.scene.add.graphics(); // Draw some leaves for (let i = 0; i < 3; i++) { const leafX = x + Phaser.Math.Between(-20, 20); const leafY = y + Phaser.Math.Between(-10, 10); graphics.fillStyle(0x2d4a1f, 0.5); // Dark green leaf graphics.fillEllipse(leafX, leafY, 8, 12); } graphics.setDepth(this.DEPTH.FOREGROUND_LEAVES); graphics.setScrollFactor(1.1, 1.1); // Fastest parallax (closest) return graphics; } clearLayer(layerName) { const layer = this.layers.find(l => l.name === layerName); if (!layer) return; for (const obj of layer.objects) { obj.destroy(); } layer.objects = []; } destroy() { for (const layer of this.layers) { for (const obj of layer.objects) { obj.destroy(); } } this.layers = []; } }