-
- Forest Lab
-
- Building up the visual language for forested terrain โ starting from the
- single tree primitive (shadow โ canopy radial gradient โ highlight dot)
- through four arrangement strategies. The density gradient is the target
- pattern: core trees are larger old growth; edge trees are smaller scrub.
- This models how real forests work and will drive per-hex rendering.
-
-
+
+ Terrain Dimensions Lab
+
+ Adjust biome levers to navigate the parameter space. Toggle overlays to stack
+ minerals, flora (ground โ understory โ canopy), and fauna glyphs. Flora renders
+ as a continuous cross-tile point cloud โ trees straddle hex borders naturally.
+
+
-
-
- Single tree anatomy โ each
- tree is three layers: a squashed ground shadow offset down-right (depth),
- a canopy with radial gradient lit from top-left (volume), and a small
- highlight dot (sun catch). Canopy radius varies by tree size; this is
- the same primitive used in all arrangements below.
-
-
- {([12, 18, 26] as const).map((r) => (
-
- {r === 12 ? "Small (r=12)" : r === 18 ? "Medium (r=18)" : "Large (r=26)"}
- {
- ctx.fillStyle = "rgb(118,185,72)";
- ctx.fillRect(0, 0, W, H);
- drawTree(ctx, W / 2, H / 2, r);
- }} />
-
- ))}
-
-
+
+
+
+ Biome classifiers
+ set({ elevation: v })} />
+ set({ moisture: v })} />
+ set({ temp: v })} />
+ set({ ridginess: v })} />
+
-
-
- Arrangements โ four
- strategies for placing trees within a patch of grassland.
-
-
- {ARRANGEMENTS.map((a) => (
-
- {a.label}
-
- {a.sub}
-
- ))}
-
-
+
+ Overlays
+
+ set({ floraOn: !st.floraOn })}>
+ Flora
+
+ {st.floraOn && (
+ set({ floraDensity: v })} />
+ )}
+
+
+ set({ mineralsOn: !st.mineralsOn })}>
+ Minerals
+
+ {st.mineralsOn && (
+ set({ mineralRichness: v })} />
+ )}
+
+
+ set({ faunaOn: !st.faunaOn })}>
+ Fauna
+
+ {st.faunaOn && (
+ set({ faunaActivity: v })} />
+ )}
+
+
+
+
+
+
+ {terrain && (
+
+ {terrain.name}
+ {terrain.description && {terrain.description}}
+
+ 0}>Food {terrain.food}
+ 0}>Prod {terrain.production}
+ 0}>Trade {terrain.trade}
+ Def +{terrain.defense_bonus}%
+ Move ร{terrain.movement_cost}
+
+ {faunaNames.length > 0 && (
+ Fauna ยท {faunaNames.join(" ยท ")}
+ )}
+
+ )}
+
+
);
}
diff --git a/.project/designs/app/src/utils/worldGen/hexCanvas.ts b/.project/designs/app/src/utils/worldGen/hexCanvas.ts
index 0ff20c8c..f440b8cb 100644
--- a/.project/designs/app/src/utils/worldGen/hexCanvas.ts
+++ b/.project/designs/app/src/utils/worldGen/hexCanvas.ts
@@ -109,37 +109,73 @@ function stipple(
}
}
-// โโ Decorations per terrain โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+// โโ 3-layer tree primitives (exported for lab use) โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-function drawTree(
+export type TreeVariety = "temperate" | "tropical";
+
+export function drawTree3Layer(
ctx: CanvasRenderingContext2D,
x: number,
y: number,
r: number,
- color: string
+ variety: TreeVariety = "temperate"
): void {
+ const colors: Record