Cookbook: draft docs
This commit is contained in:
parent
8628ac164b
commit
73230989ad
42 changed files with 3352 additions and 0 deletions
140
docs/cookbook/procgen/31_advanced_island.py
Normal file
140
docs/cookbook/procgen/31_advanced_island.py
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
"""Advanced: Island Terrain Generation
|
||||
|
||||
Combines: Noise (base terrain) + Voronoi (biomes) + Hills + Erosion + Bezier (rivers)
|
||||
Creates a tropical island with varied biomes and water features.
|
||||
"""
|
||||
import mcrfpy
|
||||
from mcrfpy import automation
|
||||
|
||||
GRID_WIDTH, GRID_HEIGHT = 64, 48
|
||||
CELL_SIZE = 16
|
||||
|
||||
def biome_color(elevation, moisture):
|
||||
"""Determine color based on elevation and moisture."""
|
||||
if elevation < 0.25:
|
||||
# Water
|
||||
t = elevation / 0.25
|
||||
return mcrfpy.Color(int(30 + t * 30), int(80 + t * 40), int(160 + t * 40))
|
||||
elif elevation < 0.32:
|
||||
# Beach
|
||||
return mcrfpy.Color(220, 200, 150)
|
||||
elif elevation < 0.5:
|
||||
# Lowland - varies by moisture
|
||||
if moisture < 0.3:
|
||||
return mcrfpy.Color(180, 170, 110) # Desert/savanna
|
||||
elif moisture < 0.6:
|
||||
return mcrfpy.Color(80, 140, 60) # Grassland
|
||||
else:
|
||||
return mcrfpy.Color(40, 100, 50) # Rainforest
|
||||
elif elevation < 0.7:
|
||||
# Highland
|
||||
if moisture < 0.4:
|
||||
return mcrfpy.Color(100, 90, 70) # Dry hills
|
||||
else:
|
||||
return mcrfpy.Color(50, 90, 45) # Forest
|
||||
elif elevation < 0.85:
|
||||
# Mountain
|
||||
return mcrfpy.Color(110, 105, 100)
|
||||
else:
|
||||
# Peak
|
||||
return mcrfpy.Color(220, 225, 230)
|
||||
|
||||
def run_demo(runtime):
|
||||
# Step 1: Create base elevation using noise
|
||||
noise = mcrfpy.NoiseSource(dimensions=2, algorithm='simplex', seed=42)
|
||||
|
||||
elevation = mcrfpy.HeightMap((GRID_WIDTH, GRID_HEIGHT), fill=0.0)
|
||||
elevation.add_noise(noise, world_size=(12, 10), mode='fbm', octaves=5)
|
||||
elevation.normalize(0.0, 1.0)
|
||||
|
||||
# Step 2: Create island shape using radial falloff
|
||||
cx, cy = GRID_WIDTH / 2, GRID_HEIGHT / 2
|
||||
max_dist = min(cx, cy) * 0.85
|
||||
|
||||
for y in range(GRID_HEIGHT):
|
||||
for x in range(GRID_WIDTH):
|
||||
dist = ((x - cx) ** 2 + (y - cy) ** 2) ** 0.5
|
||||
falloff = max(0, 1 - (dist / max_dist) ** 1.5)
|
||||
current = elevation.get((x, y))
|
||||
elevation.fill(current * falloff, pos=(x, y), size=(1, 1))
|
||||
|
||||
# Step 3: Add central mountain range
|
||||
elevation.add_hill((GRID_WIDTH // 2, GRID_HEIGHT // 2), 15, 0.5)
|
||||
elevation.add_hill((GRID_WIDTH // 2 - 8, GRID_HEIGHT // 2 + 3), 8, 0.3)
|
||||
elevation.add_hill((GRID_WIDTH // 2 + 10, GRID_HEIGHT // 2 - 5), 6, 0.25)
|
||||
|
||||
# Step 4: Create moisture map using different noise
|
||||
moisture_noise = mcrfpy.NoiseSource(dimensions=2, algorithm='simplex', seed=123)
|
||||
moisture = mcrfpy.HeightMap((GRID_WIDTH, GRID_HEIGHT), fill=0.0)
|
||||
moisture.add_noise(moisture_noise, world_size=(8, 8), mode='fbm', octaves=3)
|
||||
moisture.normalize(0.0, 1.0)
|
||||
|
||||
# Step 5: Add voronoi for biome boundaries
|
||||
biome_regions = mcrfpy.HeightMap((GRID_WIDTH, GRID_HEIGHT), fill=0.0)
|
||||
biome_regions.add_voronoi(num_points=8, coefficients=(0.5, -0.3), seed=77)
|
||||
biome_regions.normalize(0.0, 1.0)
|
||||
|
||||
# Blend voronoi into moisture
|
||||
moisture.lerp(biome_regions, 0.4)
|
||||
|
||||
# Step 6: Apply erosion to elevation
|
||||
elevation.rain_erosion(drops=2000, erosion=0.08, sedimentation=0.04, seed=42)
|
||||
elevation.normalize(0.0, 1.0)
|
||||
|
||||
# Step 7: Carve rivers from mountains to sea
|
||||
# Main river
|
||||
elevation.dig_bezier(
|
||||
points=((GRID_WIDTH // 2, GRID_HEIGHT // 2 - 5),
|
||||
(GRID_WIDTH // 2 - 10, GRID_HEIGHT // 2),
|
||||
(GRID_WIDTH // 4, GRID_HEIGHT // 2 + 5),
|
||||
(5, GRID_HEIGHT // 2 + 8)),
|
||||
start_radius=0.5, end_radius=2,
|
||||
start_height=0.3, end_height=0.15
|
||||
)
|
||||
|
||||
# Secondary river
|
||||
elevation.dig_bezier(
|
||||
points=((GRID_WIDTH // 2 + 5, GRID_HEIGHT // 2),
|
||||
(GRID_WIDTH // 2 + 15, GRID_HEIGHT // 3),
|
||||
(GRID_WIDTH - 15, GRID_HEIGHT // 4),
|
||||
(GRID_WIDTH - 5, GRID_HEIGHT // 4 + 3)),
|
||||
start_radius=0.5, end_radius=1.5,
|
||||
start_height=0.32, end_height=0.18
|
||||
)
|
||||
|
||||
# Step 8: Render
|
||||
for y in range(GRID_HEIGHT):
|
||||
for x in range(GRID_WIDTH):
|
||||
elev = elevation.get((x, y))
|
||||
moist = moisture.get((x, y))
|
||||
color_layer.set(((x, y)), biome_color(elev, moist))
|
||||
|
||||
# Title
|
||||
title = mcrfpy.Caption(text="Island Terrain: Noise + Voronoi + Hills + Erosion + Rivers", pos=(10, 10))
|
||||
title.fill_color = mcrfpy.Color(255, 255, 255)
|
||||
title.outline = 1
|
||||
title.outline_color = mcrfpy.Color(0, 0, 0)
|
||||
scene.children.append(title)
|
||||
|
||||
|
||||
# Setup
|
||||
scene = mcrfpy.Scene("island")
|
||||
|
||||
grid = mcrfpy.Grid(
|
||||
grid_size=(GRID_WIDTH, GRID_HEIGHT),
|
||||
pos=(0, 0),
|
||||
size=(GRID_WIDTH * CELL_SIZE, GRID_HEIGHT * CELL_SIZE),
|
||||
layers={}
|
||||
)
|
||||
grid.fill_color = mcrfpy.Color(0, 0, 0)
|
||||
color_layer = grid.add_layer("color", z_index=-1)
|
||||
scene.children.append(grid)
|
||||
|
||||
scene.activate()
|
||||
|
||||
# Run the demo
|
||||
run_demo(0)
|
||||
|
||||
# Take screenshot
|
||||
automation.screenshot("procgen_31_advanced_island.png")
|
||||
print("Screenshot saved: procgen_31_advanced_island.png")
|
||||
Loading…
Add table
Add a link
Reference in a new issue