diff options
Diffstat (limited to 'html/rogue')
-rw-r--r-- | html/rogue/js/world.js | 210 |
1 files changed, 104 insertions, 106 deletions
diff --git a/html/rogue/js/world.js b/html/rogue/js/world.js index d0ac529..6213f42 100644 --- a/html/rogue/js/world.js +++ b/html/rogue/js/world.js @@ -16,7 +16,7 @@ const FIR_TYPES = { SMALL: { type: 'fir', width: 100, - height: 130, + height: 230, canopyOffset: 45, canopyColor: '#22aa44', trunkColor: '#553311' @@ -24,7 +24,7 @@ const FIR_TYPES = { LARGE: { type: 'fir', width: 150, - height: 220, + height: 320, canopyOffset: 65, canopyColor: '#11aa44', trunkColor: '#442200' @@ -536,8 +536,8 @@ const renderFirTree = (ctx, tree, groundY) => { const { x, config } = tree; const { width, height, canopyOffset, trunkColor, canopyColor } = config; - // Calculate trunk dimensions - const trunkWidth = width/3; + // Calculate trunk dimensions - make trunk narrower + const trunkWidth = width/4; // Changed from /3 to /4 const trunkHeight = height - (height - canopyOffset)/2; // Draw trunk base @@ -572,133 +572,131 @@ const renderFirTree = (ctx, tree, groundY) => { '#117744', // Dark emerald ].filter(color => color !== canopyColor); - // Draw main triangular canopy with feathered edges - const drawFeatheredTriangle = (baseWidth, baseY, tipY) => { - // Draw main shape - ctx.fillStyle = canopyColor; - ctx.beginPath(); - ctx.moveTo(x - baseWidth/2, baseY); - ctx.lineTo(x + baseWidth/2, baseY); - ctx.lineTo(x, tipY); - ctx.closePath(); - ctx.fill(); - - // Add internal triangles - const spacing = 8; // Smaller spacing for more triangles - const triangleSize = 8; // Size of internal triangles - const margin = 12; // Margin from edges + const drawFeatheredTree = (baseWidth, baseY, tipY) => { + // Enhanced feathering parameters + const rowCount = 40; + const feathersPerRow = 24; + const featherLength = baseWidth * 0.3; + const featherWidth = 2; - // Calculate area for internal triangles - for (let py = tipY + margin; py < baseY - margin; py += spacing) { - // Calculate width at this height - const heightRatio = (py - tipY) / (baseY - tipY); - const levelWidth = baseWidth * heightRatio; + ctx.lineWidth = featherWidth; + + // Draw rows of feathers from bottom to top + for (let row = 0; row < rowCount; row++) { + const t = row / (rowCount - 1); + const rowY = baseY - (baseY - tipY) * t; - // Calculate x bounds for this row - const rowMinX = x - levelWidth/2 + margin; - const rowMaxX = x + levelWidth/2 - margin; + // More aggressive width reduction near top + const taper = Math.pow(1 - t, 0.8); + const rowWidth = baseWidth * taper; - // Add slight offset to alternate rows - const rowOffset = (Math.floor(py / spacing) % 2) * (spacing / 2); + // Reduce feather count more aggressively near top + const featherCount = Math.max(2, Math.floor(feathersPerRow * taper)); - for (let px = rowMinX; px < rowMaxX; px += spacing) { - const seed1 = px * 13.37; - const seed2 = py * 7.89; - - // Random variations - const variation = { - x: (seededRandom(seed1, seed2) - 0.5) * 4, - y: (seededRandom(seed2, seed1) - 0.5) * 4, - rotation: seededRandom(seed1 + seed2, seed2 - seed1) * Math.PI * 0.25, - size: triangleSize * (0.7 + seededRandom(seed1, seed2) * 0.6) - }; - - // Pick a random color - const colorIndex = Math.floor(seededRandom(seed1 * seed2, seed2 * seed1) * greenColors.length); - ctx.fillStyle = greenColors[colorIndex]; + // Skip drawing if width is too small (creates sharp point) + if (rowWidth < 2) continue; + + // Draw center column of needles first + const centerX = x; + // Draw a needle pointing left + ctx.strokeStyle = greenColors[Math.floor(seededRandom(centerX - 1, rowY) * greenColors.length)]; + ctx.beginPath(); + ctx.moveTo(centerX, rowY); + const leftAngle = Math.PI + (Math.PI * 0.05 * seededRandom(centerX, rowY) - Math.PI * 0.025); + ctx.lineTo( + centerX + Math.cos(leftAngle) * featherLength * taper, + rowY + Math.sin(leftAngle) * featherLength * taper + ); + ctx.stroke(); - ctx.save(); - ctx.translate( - px + rowOffset + variation.x, - py + variation.y - ); - ctx.rotate(variation.rotation); + // Draw a needle pointing right + ctx.strokeStyle = greenColors[Math.floor(seededRandom(centerX + 1, rowY) * greenColors.length)]; + ctx.beginPath(); + ctx.moveTo(centerX, rowY); + const rightAngle = 0 + (Math.PI * 0.05 * seededRandom(centerX, rowY) - Math.PI * 0.025); + ctx.lineTo( + centerX + Math.cos(rightAngle) * featherLength * taper, + rowY + Math.sin(rightAngle) * featherLength * taper + ); + ctx.stroke(); + + // Draw regular feathers for this row + for (let i = 0; i < featherCount; i++) { + const featherT = i / (featherCount - 1); + const startX = x - rowWidth/2 + rowWidth * featherT; - // Draw small triangle - ctx.beginPath(); - ctx.moveTo(-variation.size/2, variation.size/2); - ctx.lineTo(variation.size/2, variation.size/2); - ctx.lineTo(0, -variation.size/2); - ctx.closePath(); - ctx.fill(); + // Skip the center point as we've already drawn it + if (Math.abs(startX - x) < 1) continue; - ctx.restore(); - } - } - - // Enhanced feathering - const featherCount = 24; // Doubled from 12 - const featherLength = baseWidth * 0.15; // Increased from 0.1 - const featherWidth = 1.5; // Slightly thinner lines - - ctx.strokeStyle = canopyColor; - ctx.lineWidth = featherWidth; - - // Left edge feathering - two layers - for (let layer = 0; layer < 2; layer++) { - for (let i = 0; i < featherCount; i++) { - const t = i / (featherCount - 1); - const startX = x - baseWidth/2 + (baseWidth/2) * t; - const startY = baseY - (baseY - tipY) * t; + // Calculate angle to point directly away from center with slight upward tilt + const relativeX = (startX - x) / (rowWidth/2); + const baseAngle = relativeX < 0 ? Math.PI : 0; + const upwardTilt = Math.PI * 0.1 * t; + const angleVariation = Math.PI * 0.05; + const angle = baseAngle + (angleVariation * seededRandom(startX, rowY) - angleVariation/2) - upwardTilt; - // Vary angle more with layer - const baseAngle = Math.PI * 0.7; - const angleVariation = Math.PI * (0.15 + layer * 0.1); - const angle = baseAngle + (angleVariation * seededRandom(startX + layer, startY)); + // Reduce length near top but keep needles longer + const lengthMultiplier = 0.8 + (1 - t) * 0.3; + const finalLength = featherLength * lengthMultiplier * taper * + (0.9 + seededRandom(startX * rowY, rowY) * 0.2); - // Vary length with layer - const lengthMultiplier = 1 - t * 0.5; - const layerLength = featherLength * (1 - layer * 0.3) * lengthMultiplier; + const colorIndex = Math.floor(seededRandom(startX, rowY) * greenColors.length); + ctx.strokeStyle = greenColors[colorIndex]; ctx.beginPath(); - ctx.moveTo(startX, startY); + ctx.moveTo(startX, rowY); ctx.lineTo( - startX + Math.cos(angle) * layerLength, - startY + Math.sin(angle) * layerLength + startX + Math.cos(angle) * finalLength, + rowY + Math.sin(angle) * finalLength ); ctx.stroke(); } } - // Right edge feathering - two layers - for (let layer = 0; layer < 2; layer++) { - for (let i = 0; i < featherCount; i++) { - const t = i / (featherCount - 1); - const startX = x + baseWidth/2 - (baseWidth/2) * t; - const startY = baseY - (baseY - tipY) * t; - - // Vary angle more with layer - const baseAngle = Math.PI * 0.3; - const angleVariation = Math.PI * (0.15 + layer * 0.1); - const angle = baseAngle - (angleVariation * seededRandom(startX + layer, startY)); - - // Vary length with layer - const lengthMultiplier = 1 - t * 0.5; - const layerLength = featherLength * (1 - layer * 0.3) * lengthMultiplier; - + // Add extra feathers at the edges with upward tilt + const edgeFeatherCount = 40; + for (let i = 0; i < edgeFeatherCount; i++) { + const t = i / (edgeFeatherCount - 1); + const taper = Math.pow(1 - t, 0.8); + + // Left edge + const leftX = x - baseWidth/2 * taper + (baseWidth/2 * taper) * t; + const leftY = baseY - (baseY - tipY) * t; + const leftUpwardTilt = Math.PI * 0.1 * t; + const leftAngle = Math.PI + (Math.PI * 0.05 * seededRandom(leftX, leftY) - Math.PI * 0.025) - leftUpwardTilt; + + if (taper > 0.1) { + ctx.strokeStyle = greenColors[Math.floor(seededRandom(leftX, leftY) * greenColors.length)]; + ctx.beginPath(); + ctx.moveTo(leftX, leftY); + ctx.lineTo( + leftX + Math.cos(leftAngle) * featherLength * taper * 1.2, + leftY + Math.sin(leftAngle) * featherLength * taper * 1.2 + ); + ctx.stroke(); + } + + // Right edge + const rightX = x + baseWidth/2 * taper - (baseWidth/2 * taper) * t; + const rightY = baseY - (baseY - tipY) * t; + const rightUpwardTilt = Math.PI * 0.1 * t; + const rightAngle = 0 + (Math.PI * 0.05 * seededRandom(rightX, rightY) - Math.PI * 0.025) - rightUpwardTilt; + + if (taper > 0.1) { + ctx.strokeStyle = greenColors[Math.floor(seededRandom(rightX, rightY) * greenColors.length)]; ctx.beginPath(); - ctx.moveTo(startX, startY); + ctx.moveTo(rightX, rightY); ctx.lineTo( - startX + Math.cos(angle) * layerLength, - startY + Math.sin(angle) * layerLength + rightX + Math.cos(rightAngle) * featherLength * taper * 1.2, + rightY + Math.sin(rightAngle) * featherLength * taper * 1.2 ); ctx.stroke(); } } }; - // Draw main triangular canopy - drawFeatheredTriangle( + // Draw feathered tree shape + drawFeatheredTree( width * 1.2, groundY - canopyOffset, groundY - height * 1.1 |