Cookbook: draft docs
This commit is contained in:
parent
8628ac164b
commit
73230989ad
42 changed files with 3352 additions and 0 deletions
158
docs/cookbook/procgen/07_heightmap_bezier.py
Normal file
158
docs/cookbook/procgen/07_heightmap_bezier.py
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
"""HeightMap Bezier Curves Demo
|
||||
|
||||
Demonstrates: dig_bezier for rivers, roads, and paths
|
||||
Shows path carving with variable width and depth.
|
||||
"""
|
||||
import mcrfpy
|
||||
from mcrfpy import automation
|
||||
import math
|
||||
|
||||
GRID_WIDTH, GRID_HEIGHT = 64, 48
|
||||
CELL_SIZE = 16
|
||||
|
||||
def terrain_with_water(h):
|
||||
"""Terrain coloring with water in low areas."""
|
||||
if h < 0.15:
|
||||
# Water (carved paths)
|
||||
t = h / 0.15
|
||||
return mcrfpy.Color(int(30 + t * 30), int(60 + t * 50), int(140 + t * 40))
|
||||
elif h < 0.25:
|
||||
# Shore/wet ground
|
||||
t = (h - 0.15) / 0.1
|
||||
return mcrfpy.Color(int(80 + t * 40), int(100 + t * 30), int(80 - t * 20))
|
||||
elif h < 0.5:
|
||||
# Lowland
|
||||
t = (h - 0.25) / 0.25
|
||||
return mcrfpy.Color(int(70 + t * 20), int(130 + t * 20), int(50 + t * 10))
|
||||
elif h < 0.7:
|
||||
# Highland
|
||||
t = (h - 0.5) / 0.2
|
||||
return mcrfpy.Color(int(60 + t * 30), int(110 - t * 20), int(45 + t * 15))
|
||||
elif h < 0.85:
|
||||
# Hills
|
||||
t = (h - 0.7) / 0.15
|
||||
return mcrfpy.Color(int(100 + t * 30), int(95 + t * 25), int(70 + t * 30))
|
||||
else:
|
||||
# Peaks
|
||||
t = (h - 0.85) / 0.15
|
||||
return mcrfpy.Color(int(150 + t * 60), int(150 + t * 60), int(155 + t * 60))
|
||||
|
||||
def run_demo(runtime):
|
||||
panel_w = GRID_WIDTH // 2
|
||||
panel_h = GRID_HEIGHT
|
||||
|
||||
# Left panel: River system
|
||||
river_map = mcrfpy.HeightMap((panel_w, panel_h), fill=0.5)
|
||||
|
||||
# Add terrain
|
||||
noise = mcrfpy.NoiseSource(dimensions=2, algorithm='simplex', seed=42)
|
||||
river_map.add_noise(noise, world_size=(10, 10), mode='fbm', octaves=4, scale=0.3)
|
||||
river_map.add_hill((panel_w // 2, 5), 12, 0.3) # Mountain source
|
||||
river_map.normalize(0.3, 0.9)
|
||||
|
||||
# Main river - wide, flowing from top to bottom
|
||||
river_map.dig_bezier(
|
||||
points=((panel_w // 2, 2), (panel_w // 4, 15), (panel_w * 3 // 4, 30), (panel_w // 2, panel_h - 3)),
|
||||
start_radius=2, end_radius=5,
|
||||
start_height=0.1, end_height=0.05
|
||||
)
|
||||
|
||||
# Tributary from left
|
||||
river_map.dig_bezier(
|
||||
points=((3, 20), (10, 18), (15, 22), (panel_w // 3, 20)),
|
||||
start_radius=1, end_radius=2,
|
||||
start_height=0.12, end_height=0.1
|
||||
)
|
||||
|
||||
# Tributary from right
|
||||
river_map.dig_bezier(
|
||||
points=((panel_w - 3, 15), (panel_w - 8, 20), (panel_w - 12, 18), (panel_w * 2 // 3, 25)),
|
||||
start_radius=1, end_radius=2,
|
||||
start_height=0.12, end_height=0.1
|
||||
)
|
||||
|
||||
# Right panel: Road network
|
||||
road_map = mcrfpy.HeightMap((panel_w, panel_h), fill=0.5)
|
||||
road_map.add_noise(noise, world_size=(8, 8), mode='fbm', octaves=3, scale=0.2)
|
||||
road_map.normalize(0.35, 0.7)
|
||||
|
||||
# Main road - relatively straight
|
||||
road_map.dig_bezier(
|
||||
points=((5, panel_h // 2), (15, panel_h // 2 - 3), (panel_w - 15, panel_h // 2 + 3), (panel_w - 5, panel_h // 2)),
|
||||
start_radius=2, end_radius=2,
|
||||
start_height=0.25, end_height=0.25
|
||||
)
|
||||
|
||||
# North-south crossing road
|
||||
road_map.dig_bezier(
|
||||
points=((panel_w // 2, 5), (panel_w // 2 + 5, 15), (panel_w // 2 - 5, 35), (panel_w // 2, panel_h - 5)),
|
||||
start_radius=2, end_radius=2,
|
||||
start_height=0.25, end_height=0.25
|
||||
)
|
||||
|
||||
# Winding mountain path
|
||||
road_map.dig_bezier(
|
||||
points=((5, 8), (15, 5), (20, 15), (25, 10)),
|
||||
start_radius=1, end_radius=1,
|
||||
start_height=0.28, end_height=0.28
|
||||
)
|
||||
|
||||
# Curved path to settlement
|
||||
road_map.dig_bezier(
|
||||
points=((panel_w - 5, panel_h - 8), (panel_w - 15, panel_h - 5), (panel_w - 10, panel_h - 15), (panel_w // 2 + 5, panel_h - 10)),
|
||||
start_radius=1, end_radius=2,
|
||||
start_height=0.27, end_height=0.26
|
||||
)
|
||||
|
||||
# Apply to grid
|
||||
for y in range(panel_h):
|
||||
for x in range(panel_w):
|
||||
# Left panel: rivers
|
||||
h = river_map.get((x, y))
|
||||
color_layer.set(((x, y)), terrain_with_water(h))
|
||||
|
||||
# Right panel: roads (use brown for roads)
|
||||
h2 = road_map.get((x, y))
|
||||
if h2 < 0.3:
|
||||
# Road surface
|
||||
t = h2 / 0.3
|
||||
color = mcrfpy.Color(int(140 - t * 40), int(120 - t * 30), int(80 - t * 20))
|
||||
else:
|
||||
color = terrain_with_water(h2)
|
||||
color_layer.set(((panel_w + x, y)), color)
|
||||
|
||||
# Divider
|
||||
for y in range(GRID_HEIGHT):
|
||||
color_layer.set(((panel_w - 1, y)), mcrfpy.Color(100, 100, 100))
|
||||
|
||||
# Labels
|
||||
labels = [("Rivers (dig_bezier)", 10, 10), ("Roads & Paths", panel_w * CELL_SIZE + 10, 10)]
|
||||
for text, x, ypos in labels:
|
||||
label = mcrfpy.Caption(text=text, pos=(x, ypos))
|
||||
label.fill_color = mcrfpy.Color(255, 255, 255)
|
||||
label.outline = 1
|
||||
label.outline_color = mcrfpy.Color(0, 0, 0)
|
||||
scene.children.append(label)
|
||||
|
||||
|
||||
# Setup
|
||||
scene = mcrfpy.Scene("bezier_demo")
|
||||
|
||||
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_07_heightmap_bezier.png")
|
||||
print("Screenshot saved: procgen_07_heightmap_bezier.png")
|
||||
Loading…
Add table
Add a link
Reference in a new issue