Cookbook: draft docs
This commit is contained in:
parent
8628ac164b
commit
73230989ad
42 changed files with 3352 additions and 0 deletions
187
docs/cookbook/procgen/34_advanced_volcanic.py
Normal file
187
docs/cookbook/procgen/34_advanced_volcanic.py
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
"""Advanced: Volcanic Crater Region
|
||||
|
||||
Combines: Hills (mountains) + dig_hill (craters) + Voronoi (lava flows) + Erosion + Noise
|
||||
Creates a volcanic landscape with active lava, ash fields, and rocky terrain.
|
||||
"""
|
||||
import mcrfpy
|
||||
from mcrfpy import automation
|
||||
|
||||
GRID_WIDTH, GRID_HEIGHT = 64, 48
|
||||
CELL_SIZE = 16
|
||||
|
||||
def volcanic_color(elevation, lava_intensity, ash_level):
|
||||
"""Color based on elevation, lava presence, and ash coverage."""
|
||||
# Lava overrides everything
|
||||
if lava_intensity > 0.6:
|
||||
t = (lava_intensity - 0.6) / 0.4
|
||||
return mcrfpy.Color(
|
||||
int(200 + t * 55),
|
||||
int(80 + t * 80),
|
||||
int(20 + t * 30)
|
||||
)
|
||||
elif lava_intensity > 0.4:
|
||||
# Cooling lava
|
||||
t = (lava_intensity - 0.4) / 0.2
|
||||
return mcrfpy.Color(
|
||||
int(80 + t * 120),
|
||||
int(30 + t * 50),
|
||||
int(20)
|
||||
)
|
||||
|
||||
# Check for crater interior (very low elevation)
|
||||
if elevation < 0.15:
|
||||
t = elevation / 0.15
|
||||
return mcrfpy.Color(int(40 + t * 30), int(20 + t * 20), int(10 + t * 15))
|
||||
|
||||
# Ash coverage
|
||||
if ash_level > 0.6:
|
||||
t = (ash_level - 0.6) / 0.4
|
||||
base = int(60 + t * 40)
|
||||
return mcrfpy.Color(base, base - 5, base - 10)
|
||||
|
||||
# Normal terrain by elevation
|
||||
if elevation < 0.3:
|
||||
# Volcanic plain
|
||||
t = (elevation - 0.15) / 0.15
|
||||
return mcrfpy.Color(int(50 + t * 30), int(40 + t * 25), int(35 + t * 20))
|
||||
elif elevation < 0.5:
|
||||
# Rocky slopes
|
||||
t = (elevation - 0.3) / 0.2
|
||||
return mcrfpy.Color(int(70 + t * 20), int(60 + t * 15), int(50 + t * 15))
|
||||
elif elevation < 0.7:
|
||||
# Mountain sides
|
||||
t = (elevation - 0.5) / 0.2
|
||||
return mcrfpy.Color(int(85 + t * 25), int(75 + t * 20), int(65 + t * 20))
|
||||
elif elevation < 0.85:
|
||||
# High slopes
|
||||
t = (elevation - 0.7) / 0.15
|
||||
return mcrfpy.Color(int(100 + t * 30), int(90 + t * 25), int(80 + t * 25))
|
||||
else:
|
||||
# Peaks
|
||||
t = (elevation - 0.85) / 0.15
|
||||
return mcrfpy.Color(int(130 + t * 50), int(120 + t * 50), int(115 + t * 50))
|
||||
|
||||
def run_demo(runtime):
|
||||
# Step 1: Create base terrain with noise
|
||||
noise = mcrfpy.NoiseSource(dimensions=2, algorithm='simplex', seed=42)
|
||||
|
||||
terrain = mcrfpy.HeightMap((GRID_WIDTH, GRID_HEIGHT), fill=0.3)
|
||||
terrain.add_noise(noise, world_size=(12, 10), mode='fbm', octaves=4, scale=0.2)
|
||||
|
||||
# Step 2: Add volcanic mountains
|
||||
# Main volcano
|
||||
terrain.add_hill((GRID_WIDTH // 2, GRID_HEIGHT // 2), 20, 0.7)
|
||||
terrain.add_hill((GRID_WIDTH // 2, GRID_HEIGHT // 2), 12, 0.3) # Steep peak
|
||||
|
||||
# Secondary volcanoes
|
||||
terrain.add_hill((15, 15), 10, 0.4)
|
||||
terrain.add_hill((GRID_WIDTH - 12, GRID_HEIGHT - 15), 8, 0.35)
|
||||
terrain.add_hill((10, GRID_HEIGHT - 10), 6, 0.25)
|
||||
|
||||
# Step 3: Create craters
|
||||
terrain.dig_hill((GRID_WIDTH // 2, GRID_HEIGHT // 2), 6, 0.1) # Main crater
|
||||
terrain.dig_hill((15, 15), 4, 0.15) # Secondary crater
|
||||
terrain.dig_hill((GRID_WIDTH - 12, GRID_HEIGHT - 15), 3, 0.18) # Third crater
|
||||
|
||||
# Step 4: Create lava flow pattern using voronoi
|
||||
lava = mcrfpy.HeightMap((GRID_WIDTH, GRID_HEIGHT), fill=0.0)
|
||||
lava.add_voronoi(num_points=12, coefficients=(1.0, -0.8), seed=77)
|
||||
lava.normalize(0.0, 1.0)
|
||||
|
||||
# Lava originates from craters - enhance around crater centers
|
||||
lava.add_hill((GRID_WIDTH // 2, GRID_HEIGHT // 2), 8, 0.5)
|
||||
lava.add_hill((15, 15), 5, 0.3)
|
||||
|
||||
# Lava flows downhill - multiply by inverted terrain
|
||||
terrain_inv = terrain.inverse()
|
||||
terrain_inv.normalize(0.0, 1.0)
|
||||
lava.multiply(terrain_inv)
|
||||
lava.normalize(0.0, 1.0)
|
||||
|
||||
# Step 5: Create ash distribution using noise
|
||||
ash_noise = mcrfpy.NoiseSource(dimensions=2, algorithm='perlin', seed=123)
|
||||
ash = mcrfpy.HeightMap((GRID_WIDTH, GRID_HEIGHT), fill=0.0)
|
||||
ash.add_noise(ash_noise, world_size=(8, 6), mode='turbulence', octaves=3)
|
||||
ash.normalize(0.0, 1.0)
|
||||
|
||||
# Ash settles on lower areas
|
||||
ash.multiply(terrain_inv)
|
||||
|
||||
# Step 6: Apply erosion for realistic channels
|
||||
terrain.rain_erosion(drops=1500, erosion=0.1, sedimentation=0.03, seed=42)
|
||||
terrain.normalize(0.0, 1.0)
|
||||
|
||||
# Step 7: Add lava rivers from craters
|
||||
lava.dig_bezier(
|
||||
points=((GRID_WIDTH // 2, GRID_HEIGHT // 2 + 5),
|
||||
(GRID_WIDTH // 2 - 5, GRID_HEIGHT // 2 + 15),
|
||||
(GRID_WIDTH // 3, GRID_HEIGHT - 10),
|
||||
(10, GRID_HEIGHT - 5)),
|
||||
start_radius=2, end_radius=3,
|
||||
start_height=0.9, end_height=0.7
|
||||
)
|
||||
|
||||
lava.dig_bezier(
|
||||
points=((GRID_WIDTH // 2 + 3, GRID_HEIGHT // 2 + 3),
|
||||
(GRID_WIDTH // 2 + 15, GRID_HEIGHT // 2 + 8),
|
||||
(GRID_WIDTH - 15, GRID_HEIGHT // 2 + 5),
|
||||
(GRID_WIDTH - 5, GRID_HEIGHT // 2 + 10)),
|
||||
start_radius=1.5, end_radius=2.5,
|
||||
start_height=0.85, end_height=0.65
|
||||
)
|
||||
|
||||
# Step 8: Render
|
||||
for y in range(GRID_HEIGHT):
|
||||
for x in range(GRID_WIDTH):
|
||||
elev = terrain.get((x, y))
|
||||
lava_val = lava.get((x, y))
|
||||
ash_val = ash.get((x, y))
|
||||
|
||||
color_layer.set(((x, y)), volcanic_color(elev, lava_val, ash_val))
|
||||
|
||||
# Add smoke/steam particles around crater rims
|
||||
crater_centers = [
|
||||
(GRID_WIDTH // 2, GRID_HEIGHT // 2, 6),
|
||||
(15, 15, 4),
|
||||
(GRID_WIDTH - 12, GRID_HEIGHT - 15, 3)
|
||||
]
|
||||
|
||||
import math
|
||||
for cx, cy, radius in crater_centers:
|
||||
for angle in range(0, 360, 30):
|
||||
rad = math.radians(angle)
|
||||
px = int(cx + math.cos(rad) * radius)
|
||||
py = int(cy + math.sin(rad) * radius)
|
||||
if 0 <= px < GRID_WIDTH and 0 <= py < GRID_HEIGHT:
|
||||
# Smoke color
|
||||
color_layer.set(((px, py)), mcrfpy.Color(150, 140, 130, 180))
|
||||
|
||||
# Title
|
||||
title = mcrfpy.Caption(text="Volcanic Region: Hills + Craters + Voronoi Lava + Erosion", 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("volcanic")
|
||||
|
||||
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_34_advanced_volcanic.png")
|
||||
print("Screenshot saved: procgen_34_advanced_volcanic.png")
|
||||
Loading…
Add table
Add a link
Reference in a new issue