about summary refs log tree commit diff stats
path: root/html/rogue/js/world.js
diff options
context:
space:
mode:
Diffstat (limited to 'html/rogue/js/world.js')
-rw-r--r--html/rogue/js/world.js1054
1 files changed, 0 insertions, 1054 deletions
diff --git a/html/rogue/js/world.js b/html/rogue/js/world.js
deleted file mode 100644
index 2b2529a..0000000
--- a/html/rogue/js/world.js
+++ /dev/null
@@ -1,1054 +0,0 @@
-// Color palettes and configurations
-const NATURE_COLORS = {
-    GREENS: [
-        '#11aa33', // Darker forest green
-        '#22bb44', // Medium forest green
-        '#33cc55', // Bright forest green
-        '#118844', // Deep sea green
-        '#22aa66', // Sage green
-        '#11bb55', // Deep pine
-        '#229955', // Ocean green
-        '#33bb66', // Fresh spring green
-        '#117744', // Dark emerald
-    ],
-    TRUNK_COLORS: {
-        LIGHT: '#664422',
-        MEDIUM: '#553311',
-        DARK: '#442200'
-    }
-};
-
-const GRASS_CONFIG = {
-    MIN_BLADES: 4,
-    MAX_BLADES: 8,
-    SPREAD_FACTOR: 0.7,
-    RUSTLE_SPEED: 300,
-    WAVE_SPEED: 1000,
-    GLOW_SPEED: 500,
-    BASE_BLADE_WIDTH: 5
-};
-
-const FIR_CONFIG = {
-    ROW_COUNT: 40,
-    FEATHERS_PER_ROW: 24,
-    EDGE_FEATHER_COUNT: 40,
-    FEATHER_WIDTH: 2,
-    TAPER_POWER: 0.8,
-    CENTER_NEEDLES: 5,     // Number of needles in center column
-    NEEDLE_SPACING: 1.5,   // Spacing between center needles
-    UPWARD_TILT: 0.1,     // Amount of upward tilt (in radians)
-    ANGLE_VARIATION: 0.05, // Variation in needle angles
-    LENGTH_MULTIPLIER: 0.8 // Base length multiplier for needles
-};
-
-// Define world object types
-const WORLD_OBJECTS = {
-    PLATFORM: 'platform',
-    FIR_BACKGROUND: 'fir_background',
-    FIR_FOREGROUND: 'fir_foreground',
-    MAPLE_BACKGROUND: 'maple_background',
-    MAPLE_FOREGROUND: 'maple_foreground',
-    ROCK_BACKGROUND: 'rock_background',
-    ROCK_FOREGROUND: 'rock_foreground',
-    GRASS_BACKGROUND: 'grass_background',
-    GRASS_FOREGROUND: 'grass_foreground'
-};
-
-// Separate configurations for different tree types
-const FIR_TYPES = {
-    SMALL: {
-        type: 'fir',
-        width: 100,
-        height: 230,
-        canopyOffset: 45,
-        canopyColor: '#22aa44',
-        trunkColor: '#553311'
-    },
-    LARGE: {
-        type: 'fir',
-        width: 150,
-        height: 320,
-        canopyOffset: 65,
-        canopyColor: '#11aa44',
-        trunkColor: '#442200'
-    }
-};
-
-const MAPLE_TYPES = {
-    SMALL: {
-        type: 'maple',
-        width: 100,
-        height: 330,
-        trunkHeight: 60,
-        canopyRadius: 35,
-        leafClusters: 5,
-        canopyColor: '#33aa22', // Bright green
-        trunkColor: '#664422'
-    },
-    MEDIUM: {
-        type: 'maple',
-        width: 130,
-        height: 360,
-        trunkHeight: 70,
-        canopyRadius: 45,
-        leafClusters: 6,
-        canopyColor: '#228833', // Deep forest green
-        trunkColor: '#553311'
-    },
-    LARGE: {
-        type: 'maple',
-        width: 160,
-        height: 400,
-        trunkHeight: 85,
-        canopyRadius: 55,
-        leafClusters: 7,
-        canopyColor: '#115522', // Dark green
-        trunkColor: '#553311'
-    },
-    BRIGHT: {
-        type: 'maple',
-        width: 140,
-        height: 380,
-        trunkHeight: 75,
-        canopyRadius: 50,
-        leafClusters: 6,
-        canopyColor: '#44bb33', // Vibrant green
-        trunkColor: '#664422'
-    },
-    SAGE: {
-        type: 'maple',
-        width: 150,
-        height: 490,
-        trunkHeight: 80,
-        canopyRadius: 52,
-        leafClusters: 6,
-        canopyColor: '#225544', // Sage green
-        trunkColor: '#553311'
-    }
-};
-
-// Rock configurations
-const ROCK_TYPES = {
-    SMALL: {
-        width: 40,
-        height: 30,
-        color: '#666',
-        highlights: '#888'
-    },
-    MEDIUM: {
-        width: 70,
-        height: 45,
-        color: '#555',
-        highlights: '#777'
-    },
-    LARGE: {
-        width: 100,
-        height: 60,
-        color: '#444',
-        highlights: '#666'
-    }
-};
-
-// Add grass configurations
-const GRASS_TYPES = {
-    TALL: {
-        type: 'grass',
-        width: 30,
-        height: 40,
-        color: '#33aa55',
-        shadowColor: '#229944'
-    },
-    SHORT: {
-        type: 'grass',
-        width: 20,
-        height: 25,
-        color: '#33bb66',
-        shadowColor: '#22aa55'
-    },
-    GOLDEN_TALL: {
-        type: 'grass',
-        width: 30,
-        height: 40,
-        color: '#eebb33',
-        shadowColor: '#cc9922'
-    },
-    GOLDEN_SHORT: {
-        type: 'grass',
-        width: 20,
-        height: 25,
-        color: '#ffcc44',
-        shadowColor: '#ddaa33'
-    },
-    BLUE_TALL: {
-        type: 'grass',
-        width: 30,
-        height: 40,
-        color: '#44aaff',
-        shadowColor: '#2299ff',
-        glowing: true
-    },
-    BLUE_SHORT: {
-        type: 'grass',
-        width: 20,
-        height: 25,
-        color: '#55bbff',
-        shadowColor: '#33aaff',
-        glowing: true
-    }
-};
-
-// Utility functions
-const utils = {
-    getRandomColorFromPalette: (palette, seed1, seed2) => {
-        const colorIndex = Math.floor(seededRandom(seed1, seed2) * palette.length);
-        return palette[colorIndex];
-    },
-
-    getBladeCount: (x, height) => {
-        const randomValue = Math.abs(seededRandom(x, height));
-        return GRASS_CONFIG.MIN_BLADES + 
-            Math.round(randomValue * (GRASS_CONFIG.MAX_BLADES - GRASS_CONFIG.MIN_BLADES));
-    },
-
-    calculateTaper: (t) => Math.pow(1 - t, FIR_CONFIG.TAPER_POWER)
-};
-
-// Create a world with platforms, trees, and rocks
-const createWorld = () => {
-    const world = {
-        groundHeight: 12,
-        // Separate arrays for different layers
-        backgroundTrees: [
-            // Far left trees
-            {
-                type: WORLD_OBJECTS.FIR_BACKGROUND,
-                x: -1500,
-                config: FIR_TYPES.LARGE
-            },
-            {
-                type: WORLD_OBJECTS.MAPLE_BACKGROUND,
-                x: -1200,
-                config: MAPLE_TYPES.SAGE
-            },
-            {
-                type: WORLD_OBJECTS.FIR_BACKGROUND,
-                x: -900,
-                config: FIR_TYPES.SMALL
-            },
-            // Existing trees
-            {
-                type: WORLD_OBJECTS.FIR_BACKGROUND,
-                x: -400,
-                config: FIR_TYPES.LARGE
-            },
-            {
-                type: WORLD_OBJECTS.MAPLE_BACKGROUND,
-                x: -250,
-                config: MAPLE_TYPES.BRIGHT
-            },
-            {
-                type: WORLD_OBJECTS.FIR_BACKGROUND,
-                x: 50,
-                config: FIR_TYPES.LARGE
-            },
-            {
-                type: WORLD_OBJECTS.MAPLE_BACKGROUND,
-                x: 250,
-                config: MAPLE_TYPES.MEDIUM
-            },
-            {
-                type: WORLD_OBJECTS.FIR_BACKGROUND,
-                x: 500,
-                config: FIR_TYPES.SMALL
-            },
-            {
-                type: WORLD_OBJECTS.MAPLE_BACKGROUND,
-                x: 650,
-                config: MAPLE_TYPES.SMALL
-            },
-            {
-                type: WORLD_OBJECTS.FIR_BACKGROUND,
-                x: 900,
-                config: FIR_TYPES.LARGE
-            },
-            {
-                type: WORLD_OBJECTS.MAPLE_BACKGROUND,
-                x: 1100,
-                config: MAPLE_TYPES.LARGE
-            },
-            // Far right trees
-            {
-                type: WORLD_OBJECTS.MAPLE_BACKGROUND,
-                x: 1400,
-                config: MAPLE_TYPES.LARGE
-            },
-            {
-                type: WORLD_OBJECTS.FIR_BACKGROUND,
-                x: 1700,
-                config: FIR_TYPES.SMALL
-            },
-            {
-                type: WORLD_OBJECTS.MAPLE_BACKGROUND,
-                x: 2000,
-                config: MAPLE_TYPES.LARGE
-            }
-        ],
-        backgroundRocks: [
-            // Far left rocks
-            {
-                type: WORLD_OBJECTS.ROCK_BACKGROUND,
-                x: -1300,
-                config: ROCK_TYPES.LARGE
-            },
-            {
-                type: WORLD_OBJECTS.ROCK_BACKGROUND,
-                x: -1000,
-                config: ROCK_TYPES.SMALL
-            },
-            {
-                type: WORLD_OBJECTS.ROCK_BACKGROUND,
-                x: -300,
-                config: ROCK_TYPES.MEDIUM
-            },
-            {
-                type: WORLD_OBJECTS.ROCK_BACKGROUND,
-                x: -100,
-                config: ROCK_TYPES.SMALL
-            },
-            {
-                type: WORLD_OBJECTS.ROCK_BACKGROUND,
-                x: 150,
-                config: ROCK_TYPES.LARGE
-            },
-            {
-                type: WORLD_OBJECTS.ROCK_BACKGROUND,
-                x: 400,
-                config: ROCK_TYPES.SMALL
-            },
-            {
-                type: WORLD_OBJECTS.ROCK_BACKGROUND,
-                x: 750,
-                config: ROCK_TYPES.MEDIUM
-            },
-            {
-                type: WORLD_OBJECTS.ROCK_BACKGROUND,
-                x: 1000,
-                config: ROCK_TYPES.SMALL
-            },
-            // Far right rocks
-            {
-                type: WORLD_OBJECTS.ROCK_BACKGROUND,
-                x: 1600,
-                config: ROCK_TYPES.MEDIUM
-            },
-            {
-                type: WORLD_OBJECTS.ROCK_BACKGROUND,
-                x: 1900,
-                config: ROCK_TYPES.SMALL
-            }
-        ],
-        platforms: [
-            // {
-            //     type: WORLD_OBJECTS.PLATFORM,
-            //     x: 300,
-            //     y: 300,
-            //     width: 200,
-            //     height: 20,
-            //     color: '#484'
-            // },
-            // {
-            //     type: WORLD_OBJECTS.PLATFORM,
-            //     x: 600,
-            //     y: 200,
-            //     width: 200,
-            //     height: 20,
-            //     color: '#484'
-            // },
-            // {
-            //     type: WORLD_OBJECTS.PLATFORM,
-            //     x: -200,
-            //     y: 250,
-            //     width: 200,
-            //     height: 20,
-            //     color: '#484'
-            // }
-        ],
-        foregroundTrees: [
-            // Far left trees
-            {
-                type: WORLD_OBJECTS.FIR_FOREGROUND,
-                x: -1400,
-                config: FIR_TYPES.LARGE
-            },
-            {
-                type: WORLD_OBJECTS.MAPLE_FOREGROUND,
-                x: -1100,
-                config: MAPLE_TYPES.SMALL
-            },
-            // Existing trees
-            {
-                type: WORLD_OBJECTS.MAPLE_FOREGROUND,
-                x: -150,
-                config: MAPLE_TYPES.BRIGHT
-            },
-            {
-                type: WORLD_OBJECTS.FIR_FOREGROUND,
-                x: 200,
-                config: FIR_TYPES.SMALL
-            },
-            {
-                type: WORLD_OBJECTS.MAPLE_FOREGROUND,
-                x: 450,
-                config: MAPLE_TYPES.SAGE
-            },
-            {
-                type: WORLD_OBJECTS.FIR_FOREGROUND,
-                x: 800,
-                config: FIR_TYPES.LARGE
-            },
-            {
-                type: WORLD_OBJECTS.MAPLE_FOREGROUND,
-                x: 1200,
-                config: MAPLE_TYPES.SMALL
-            },
-            // Far right trees
-            {
-                type: WORLD_OBJECTS.FIR_FOREGROUND,
-                x: 1500,
-                config: FIR_TYPES.LARGE
-            },
-            {
-                type: WORLD_OBJECTS.MAPLE_FOREGROUND,
-                x: 1800,
-                config: MAPLE_TYPES.SMALL
-            }
-        ],
-        foregroundRocks: [
-            // Far left rocks
-            {
-                type: WORLD_OBJECTS.ROCK_FOREGROUND,
-                x: -1000,
-                config: ROCK_TYPES.MEDIUM
-            },
-            {
-                type: WORLD_OBJECTS.ROCK_FOREGROUND,
-                x: 0,
-                config: ROCK_TYPES.SMALL
-            },
-            {
-                type: WORLD_OBJECTS.ROCK_FOREGROUND,
-                x: 300,
-                config: ROCK_TYPES.MEDIUM
-            },
-            {
-                type: WORLD_OBJECTS.ROCK_FOREGROUND,
-                x: 700,
-                config: ROCK_TYPES.SMALL
-            },
-            {
-                type: WORLD_OBJECTS.ROCK_FOREGROUND,
-                x: 950,
-                config: ROCK_TYPES.LARGE
-            },
-            // Far right rocks
-            {
-                type: WORLD_OBJECTS.ROCK_FOREGROUND,
-                x: 1500,
-                config: ROCK_TYPES.LARGE
-            }
-        ],
-        backgroundGrass: [
-            // Far left grass
-            { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: -1400, config: GRASS_TYPES.BLUE_TALL },
-            { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: -1100, config: GRASS_TYPES.GOLDEN_SHORT },
-            { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: -950, config: GRASS_TYPES.TALL },
-            { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: -350, config: GRASS_TYPES.SHORT },
-            { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: -180, config: GRASS_TYPES.GOLDEN_TALL },
-            { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: 100, config: GRASS_TYPES.TALL },
-            { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: 320, config: GRASS_TYPES.BLUE_SHORT },
-            { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: 580, config: GRASS_TYPES.GOLDEN_SHORT },
-            { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: 750, config: GRASS_TYPES.BLUE_TALL },
-            { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: 950, config: GRASS_TYPES.TALL },
-            { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: 1050, config: GRASS_TYPES.GOLDEN_TALL },
-            // Far right grass
-            { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: 1500, config: GRASS_TYPES.BLUE_SHORT },
-            { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: 1750, config: GRASS_TYPES.GOLDEN_TALL },
-            { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: 1850, config: GRASS_TYPES.SHORT }
-        ],
-        foregroundGrass: [
-            // Far left grass
-            { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: -1250, config: GRASS_TYPES.TALL },
-            { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: -1050, config: GRASS_TYPES.BLUE_SHORT },
-            { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: -280, config: GRASS_TYPES.BLUE_TALL },
-            { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: -50, config: GRASS_TYPES.GOLDEN_SHORT },
-            { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: 150, config: GRASS_TYPES.TALL },
-            { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: 420, config: GRASS_TYPES.BLUE_SHORT },
-            { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: 680, config: GRASS_TYPES.GOLDEN_TALL },
-            { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: 880, config: GRASS_TYPES.SHORT },
-            { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: 1150, config: GRASS_TYPES.BLUE_TALL },
-            // Far right grass
-            { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: 1650, config: GRASS_TYPES.GOLDEN_TALL },
-            { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: 1850, config: GRASS_TYPES.BLUE_SHORT }
-        ],
-        // Track grass animation states
-        grassStates: {},
-        // Add methods for quick spatial lookups
-        getObjectsInView: function(bounds) {
-            return {
-                backgroundTrees: this.backgroundTrees.filter(tree => 
-                    tree.x > bounds.left && tree.x < bounds.right
-                ),
-                // ... similar for other object types
-            };
-        }
-    };
-    
-    return world;
-};
-
-// Add seededRandom function
-const seededRandom = (x, y) => {
-    const dot = x * 12.9898 + y * 78.233;
-    return (Math.sin(dot) * 43758.5453123) % 1;
-};
-
-// Add hatching helper function
-const addHatchingPattern = (ctx, x, y, width, height, color) => {
-    const spacing = 4; // Space between hatch lines
-    const length = 10;  // Length of each hatch line
-    const margin = 4; // Increased margin from edges
-    const baseAngle = Math.PI * 1.5; // Vertical angle (pointing down)
-    const angleVariation = Math.PI / 12; // Reduced angle variation
-    
-    // Define darker brown shades
-    const brownShades = [
-        '#442211', // Dark brown
-        '#553322', // Medium dark brown
-        '#443311', // Reddish dark brown
-        '#332211', // Very dark brown
-        '#554422', // Warm dark brown
-    ];
-    
-    // Create clipping path for trunk
-    ctx.save();
-    ctx.beginPath();
-    ctx.rect(
-        x - width/2,
-        y - height,
-        width,
-        height
-    );
-    ctx.clip();
-    
-    // Calculate bounds with increased safety margin
-    const bounds = {
-        minX: x - width/2 + margin,
-        maxX: x + width/2 - margin,
-        minY: y - height + margin,
-        maxY: y - margin
-    };
-
-    // Draw hatching
-    ctx.lineWidth = 1;
-    for (let hatchX = bounds.minX; hatchX < bounds.maxX; hatchX += spacing) {
-        for (let hatchY = bounds.minY; hatchY < bounds.maxY; hatchY += spacing) {
-            // Use position for random variation
-            const seed1 = hatchX * 13.37;
-            const seed2 = hatchY * 7.89;
-            
-            // Random variations with reduced range
-            const variation = {
-                x: (seededRandom(seed1, seed2) - 0.5) * 1.5, // Reduced variation
-                y: (seededRandom(seed2, seed1) - 0.5) * 1.5, // Reduced variation
-                angle: baseAngle + (seededRandom(seed1 + seed2, seed2 - seed1) - 0.5) * angleVariation
-            };
-
-            // Pick a random brown shade
-            const colorIndex = Math.floor(seededRandom(seed1 * seed2, seed2 * seed1) * brownShades.length);
-            ctx.strokeStyle = brownShades[colorIndex];
-
-            // Draw hatch line
-            ctx.beginPath();
-            ctx.moveTo(
-                hatchX + variation.x,
-                hatchY + variation.y
-            );
-            ctx.lineTo(
-                hatchX + Math.cos(variation.angle) * length + variation.x,
-                hatchY + Math.sin(variation.angle) * length + variation.y
-            );
-            ctx.stroke();
-        }
-    }
-    
-    ctx.restore();
-};
-
-class FirTreeRenderer {
-    static renderTrunk(ctx, x, width, height, groundY, trunkColor) {
-        const trunkWidth = width/4;
-        const trunkHeight = height;
-        
-        ctx.fillStyle = trunkColor;
-        ctx.fillRect(
-            x - trunkWidth/2,
-            groundY - trunkHeight,
-            trunkWidth,
-            trunkHeight
-        );
-        
-        addHatchingPattern(ctx, x, groundY, trunkWidth, trunkHeight, trunkColor);
-    }
-
-    static renderCenterNeedles(ctx, x, rowY, taper, featherLength, greenColors) {
-        for (let i = -FIR_CONFIG.CENTER_NEEDLES; i <= FIR_CONFIG.CENTER_NEEDLES; i++) {
-            const offset = i * (FIR_CONFIG.NEEDLE_SPACING * 1.5);
-            
-            // Left needle
-            FirTreeRenderer.renderSingleNeedle(
-                ctx, x + offset, rowY, Math.PI, taper, featherLength, greenColors
-            );
-            
-            // Right needle
-            FirTreeRenderer.renderSingleNeedle(
-                ctx, x + offset, rowY, 0, taper, featherLength, greenColors
-            );
-        }
-    }
-
-    static renderSingleNeedle(ctx, x, y, baseAngle, taper, length, colors) {
-        const angleVar = Math.PI * 0.02;
-        const angle = baseAngle + (angleVar * seededRandom(x, y) - angleVar/2);
-        
-        ctx.strokeStyle = utils.getRandomColorFromPalette(colors, x, y);
-        ctx.beginPath();
-        ctx.moveTo(x, y);
-        ctx.lineTo(
-            x + Math.cos(angle) * length * taper,
-            y + Math.sin(angle) * length * taper
-        );
-        ctx.stroke();
-    }
-
-    static renderRowNeedles(ctx, x, rowY, rowWidth, featherCount, t, taper, featherLength, greenColors) {
-        for (let i = 0; i < featherCount; i++) {
-            const featherT = i / (featherCount - 1);
-            const startX = x - rowWidth/2 + rowWidth * featherT;
-            
-            if (Math.abs(startX - x) < 1) continue;
-            
-            const relativeX = (startX - x) / (rowWidth/2);
-            const baseAngle = relativeX < 0 ? Math.PI : 0;
-            const upwardTilt = Math.PI * FIR_CONFIG.UPWARD_TILT * t;
-            const angle = baseAngle + 
-                (FIR_CONFIG.ANGLE_VARIATION * seededRandom(startX, rowY) - FIR_CONFIG.ANGLE_VARIATION/2) - 
-                upwardTilt;
-            
-            const lengthMultiplier = FIR_CONFIG.LENGTH_MULTIPLIER + (1 - t) * 0.3;
-            const finalLength = featherLength * lengthMultiplier * taper * 
-                (0.9 + seededRandom(startX * rowY, rowY) * 0.2);
-            
-            ctx.strokeStyle = utils.getRandomColorFromPalette(greenColors, startX, rowY);
-            ctx.beginPath();
-            ctx.moveTo(startX, rowY);
-            ctx.lineTo(
-                startX + Math.cos(angle) * finalLength,
-                rowY + Math.sin(angle) * finalLength
-            );
-            ctx.stroke();
-        }
-    }
-
-    static renderEdgeNeedles(ctx, x, baseWidth, baseY, tipY, featherLength, greenColors) {
-        for (let i = 0; i < FIR_CONFIG.EDGE_FEATHER_COUNT; i++) {
-            const t = i / (FIR_CONFIG.EDGE_FEATHER_COUNT - 1);
-            const taper = utils.calculateTaper(t);
-            
-            if (taper <= 0.1) continue;
-            
-            // Left edge
-            FirTreeRenderer.renderEdgeNeedle(
-                ctx, x, baseWidth, baseY, tipY, t, taper, 
-                featherLength, Math.PI, greenColors, true
-            );
-            
-            // Right edge
-            FirTreeRenderer.renderEdgeNeedle(
-                ctx, x, baseWidth, baseY, tipY, t, taper, 
-                featherLength, 0, greenColors, false
-            );
-        }
-    }
-
-    static renderEdgeNeedle(ctx, x, baseWidth, baseY, tipY, t, taper, length, baseAngle, colors, isLeft) {
-        const sign = isLeft ? -1 : 1;
-        const needleX = x + sign * (baseWidth/2 * taper - (baseWidth/2 * taper) * t);
-        const needleY = baseY - (baseY - tipY) * t;
-        
-        const upwardTilt = Math.PI * 0.1 * t;
-        const angle = baseAngle + 
-            (Math.PI * 0.05 * seededRandom(needleX, needleY) - Math.PI * 0.025) - 
-            upwardTilt;
-        
-        ctx.strokeStyle = utils.getRandomColorFromPalette(colors, needleX, needleY);
-        ctx.beginPath();
-        ctx.moveTo(needleX, needleY);
-        ctx.lineTo(
-            needleX + Math.cos(angle) * length * taper * 1.2,
-            needleY + Math.sin(angle) * length * taper * 1.2
-        );
-        ctx.stroke();
-    }
-}
-
-// Helper function to darken/lighten colors
-const shadeColor = (color, percent) => {
-    const num = parseInt(color.replace('#', ''), 16);
-    const amt = Math.round(2.55 * percent);
-    const R = (num >> 16) + amt;
-    const G = (num >> 8 & 0x00FF) + amt;
-    const B = (num & 0x0000FF) + amt;
-    return '#' + (0x1000000 +
-        (R < 255 ? (R < 1 ? 0 : R) : 255) * 0x10000 +
-        (G < 255 ? (G < 1 ? 0 : G) : 255) * 0x100 +
-        (B < 255 ? (B < 1 ? 0 : B) : 255)
-    ).toString(16).slice(1);
-};
-
-// Add new maple tree render function
-const renderMapleTree = (ctx, tree, groundY) => {
-    const { x, config } = tree;
-    const { 
-        width, height, trunkHeight, canopyRadius,
-        leafClusters, trunkColor, canopyColor 
-    } = config;
-    
-    // Draw trunk base with narrower width (changed from width/4 to width/5)
-    const trunkWidth = width/5.5;
-    ctx.fillStyle = trunkColor;
-    ctx.fillRect(
-        x - trunkWidth/2,
-        groundY - trunkHeight,
-        trunkWidth,
-        trunkHeight
-    );
-    
-    // Add trunk hatching with updated width
-    addHatchingPattern(
-        ctx,
-        x,
-        groundY,
-        trunkWidth,
-        trunkHeight,
-        trunkColor
-    );
-
-    // Function to create an irregular polygon
-    const createIrregularPolygon = (centerX, centerY, radius, sides, seed1, seed2) => {
-        ctx.beginPath();
-        
-        // Create points array first to allow smoothing
-        const points = [];
-        for (let i = 0; i < sides; i++) {
-            const angle = (i / sides) * Math.PI * 2;
-            
-            // Even more subtle variation range (0.95-1.05)
-            const radiusVariation = 0.95 + seededRandom(seed1 * i, seed2 * i) * 0.10;
-            const pointRadius = radius * radiusVariation;
-            
-            points.push({
-                x: centerX + Math.cos(angle) * pointRadius,
-                y: centerY + Math.sin(angle) * pointRadius
-            });
-        }
-        
-        // Start the path
-        ctx.moveTo(points[0].x, points[0].y);
-        
-        // Draw smooth curves through all points
-        for (let i = 0; i < points.length; i++) {
-            const current = points[i];
-            const next = points[(i + 1) % points.length];
-            const nextNext = points[(i + 2) % points.length];
-            
-            // Calculate control points for bezier curve with more smoothing
-            const cp1x = current.x + (next.x - points[(i - 1 + points.length) % points.length].x) / 4;
-            const cp1y = current.y + (next.y - points[(i - 1 + points.length) % points.length].y) / 4;
-            const cp2x = next.x - (nextNext.x - current.x) / 4;
-            const cp2y = next.y - (nextNext.y - current.y) / 4;
-            
-            // Draw bezier curve
-            ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, next.x, next.y);
-        }
-        
-        ctx.closePath();
-    };
-
-    // Draw single canopy as irregular polygon
-    const sides = Math.floor(48 + seededRandom(x, groundY) * 16); // 48-64 sides
-    const mainY = groundY - trunkHeight - canopyRadius;
-    
-    ctx.fillStyle = canopyColor;
-    createIrregularPolygon(
-        x,
-        mainY,
-        canopyRadius * 1.4, // Increased size
-        sides,
-        x,
-        groundY
-    );
-    ctx.fill();
-};
-
-// Main tree render function that handles both types
-const renderTree = (ctx, tree, groundY) => {
-    if (tree.config.type === 'fir') {
-        renderFirTree(ctx, tree, groundY);
-    } else if (tree.config.type === 'maple') {
-        renderMapleTree(ctx, tree, groundY);
-    }
-};
-
-const renderRock = (ctx, rock, groundY) => {
-    const { x, config } = rock;
-    const { width, height, color, highlights } = config;
-    
-    // Draw main rock shape (slightly irregular pentagon)
-    ctx.fillStyle = color;
-    ctx.beginPath();
-    ctx.moveTo(x - width/2, groundY);
-    ctx.lineTo(x - width/2 + width/6, groundY - height);
-    ctx.lineTo(x + width/3, groundY - height);
-    ctx.lineTo(x + width/2, groundY - height/2);
-    ctx.lineTo(x + width/2, groundY);
-    ctx.closePath();
-    ctx.fill();
-
-    // Add highlights
-    ctx.fillStyle = highlights;
-    ctx.beginPath();
-    ctx.moveTo(x - width/4, groundY - height);
-    ctx.lineTo(x, groundY - height);
-    ctx.lineTo(x + width/6, groundY - height/2);
-    ctx.lineTo(x - width/6, groundY - height/2);
-    ctx.closePath();
-    ctx.fill();
-};
-
-// Add grass rendering function
-const renderGrass = (ctx, grass, groundY, time) => {
-    const { x, config } = grass;
-    const { width, height, color, shadowColor, glowing } = config;
-    
-    // Initialize or get grass state
-    const stateKey = `grass_${x}`;
-    if (!window.gameState.world.grassStates[stateKey]) {
-        window.gameState.world.grassStates[stateKey] = GrassState.create(x, height);
-    }
-    const state = GrassState.validate(window.gameState.world.grassStates[stateKey]);
-    
-    // Update interaction
-    const player = window.gameState.player;
-    const distanceToPlayer = Math.abs(player.x + player.width / 2 - x);
-    GrassState.update(state, distanceToPlayer, width);
-
-    // Handle rendering
-    setupGlowEffect(ctx, glowing, color, time);
-    renderGrassBlades(ctx, state, x, width, height, groundY, time, color, shadowColor);
-    resetGlowEffect(ctx, glowing);
-};
-
-const setupGlowEffect = (ctx, glowing, color, time) => {
-    if (glowing) {
-        ctx.save();
-        ctx.shadowColor = color;
-        ctx.shadowBlur = 10 + Math.sin(time/GRASS_CONFIG.GLOW_SPEED) * 3;
-    }
-};
-
-const resetGlowEffect = (ctx, glowing) => {
-    if (glowing) {
-        ctx.restore();
-    }
-};
-
-const renderGrassBlades = (ctx, state, x, width, height, groundY, time, color, shadowColor) => {
-    const bladeWidth = width / GRASS_CONFIG.BASE_BLADE_WIDTH * 0.7;
-    
-    for (let i = 0; i < state.bladeCount; i++) {
-        renderSingleBlade(
-            ctx, i, state, x, width, height, groundY, time,
-            bladeWidth, color, shadowColor
-        );
-    }
-};
-
-const renderSingleBlade = (
-    ctx, index, state, x, width, height, groundY, time,
-    bladeWidth, color, shadowColor
-) => {
-    const centerOffset = (index - (state.bladeCount - 1) / 2) * 
-        (width * GRASS_CONFIG.SPREAD_FACTOR / state.bladeCount);
-    const bladeX = x + centerOffset;
-    
-    const rustleOffset = Math.sin(time / GRASS_CONFIG.RUSTLE_SPEED + index) * 5 * state.rustleAmount;
-    const baseWave = Math.sin(time / GRASS_CONFIG.WAVE_SPEED + index) * 2;
-    
-    drawBladeCurve(
-        ctx, bladeX, groundY, height, rustleOffset, baseWave,
-        bladeWidth, index % 2 === 0 ? color : shadowColor
-    );
-};
-
-const drawBladeCurve = (
-    ctx, bladeX, groundY, height, rustleOffset, baseWave,
-    bladeWidth, color
-) => {
-    const cp1x = bladeX + rustleOffset + baseWave;
-    const cp1y = groundY - height / 2;
-    const cp2x = bladeX + rustleOffset * 1.5 + baseWave;
-    const cp2y = groundY - height;
-    
-    ctx.fillStyle = color;
-    ctx.beginPath();
-    ctx.moveTo(bladeX, groundY);
-    ctx.quadraticCurveTo(cp1x, cp1y, cp2x, cp2y);
-    ctx.quadraticCurveTo(cp1x + bladeWidth, cp1y, bladeX + bladeWidth, groundY);
-    ctx.fill();
-};
-
-// Collision detection helper
-const checkCollision = (player, platform) => {
-    return player.x < platform.x + platform.width &&
-           player.x + player.width > platform.x &&
-           player.y < platform.y + platform.height &&
-           player.y + player.height > platform.y;
-};
-
-// World physics helper
-const handleWorldCollisions = (player, world) => {
-    let onGround = false;
-    
-    // Check ground collision first
-    const groundY = window.innerHeight - world.groundHeight;
-    if (player.y + player.height > groundY) {
-        player.y = groundY - player.height;
-        player.velocityY = 0;
-        onGround = true;
-    }
-    
-    // Then check platform collisions
-    for (const platform of world.platforms) {
-        if (checkCollision(player, platform)) {
-            // Calculate overlap on each axis
-            const overlapX = Math.min(
-                player.x + player.width - platform.x,
-                platform.x + platform.width - player.x
-            );
-            const overlapY = Math.min(
-                player.y + player.height - platform.y,
-                platform.y + platform.height - player.y
-            );
-
-            // Resolve collision on the axis with smallest overlap
-            if (overlapX < overlapY) {
-                // Horizontal collision
-                if (player.x < platform.x) {
-                    player.x = platform.x - player.width;
-                } else {
-                    player.x = platform.x + platform.width;
-                }
-                player.velocityX = 0;
-            } else {
-                // Vertical collision
-                if (player.y < platform.y) {
-                    player.y = platform.y - player.height;
-                    player.velocityY = 0;
-                    onGround = true;
-                } else {
-                    player.y = platform.y + platform.height;
-                    player.velocityY = 0;
-                }
-            }
-        }
-    }
-    
-    return { ...player, jumping: !onGround };
-};
-
-class GrassState {
-    static create(x, height) {
-        return {
-            rustleAmount: 0,
-            rustleDecay: 0.95,
-            bladeCount: utils.getBladeCount(x, height)
-        };
-    }
-
-    static validate(state) {
-        if (!state.bladeCount || state.bladeCount < GRASS_CONFIG.MIN_BLADES) {
-            state.bladeCount = GRASS_CONFIG.MIN_BLADES;
-        }
-        return state;
-    }
-
-    static update(state, distanceToPlayer, interactionDistance) {
-        if (distanceToPlayer < interactionDistance) {
-            state.rustleAmount = Math.min(1, state.rustleAmount + 0.3);
-        } else {
-            state.rustleAmount *= state.rustleDecay;
-        }
-    }
-}
-
-const renderFirTree = (ctx, tree, groundY) => {
-    const { x, config } = tree;
-    const { width, height, canopyOffset, trunkColor, canopyColor } = config;
-    
-    // Setup
-    const greenColors = NATURE_COLORS.GREENS.filter(color => color !== canopyColor);
-    ctx.lineWidth = FIR_CONFIG.FEATHER_WIDTH;
-    
-    // Render trunk
-    FirTreeRenderer.renderTrunk(
-        ctx, x, width, height - (height - canopyOffset)/2, 
-        groundY, trunkColor
-    );
-    
-    const drawFeatheredTree = (baseWidth, baseY, tipY) => {
-        const featherLength = baseWidth * 0.3;
-        
-        for (let row = 0; row < FIR_CONFIG.ROW_COUNT; row++) {
-            const t = row / (FIR_CONFIG.ROW_COUNT - 1);
-            const rowY = baseY - (baseY - tipY) * t;
-            
-            const taper = utils.calculateTaper(t);
-            const rowWidth = baseWidth * taper;
-            
-            if (rowWidth < 2) continue;
-            
-            const featherCount = Math.max(2, Math.floor(FIR_CONFIG.FEATHERS_PER_ROW * taper));
-            
-            // Render center column of needles
-            FirTreeRenderer.renderCenterNeedles(ctx, x, rowY, taper, featherLength, greenColors);
-            
-            // Render row needles
-            FirTreeRenderer.renderRowNeedles(
-                ctx, x, rowY, rowWidth, featherCount, t, 
-                taper, featherLength, greenColors
-            );
-        }
-        
-        // Render edge needles
-        FirTreeRenderer.renderEdgeNeedles(
-            ctx, x, baseWidth, baseY, tipY, featherLength, greenColors
-        );
-    };
-
-    // Draw complete tree
-    drawFeatheredTree(
-        width * 1.2,
-        groundY - canopyOffset,
-        groundY - height * 1.1
-    );
-};