# Capitolo 8: Personalizzazione e Configurazione ## File di Configurazione Tutto è configurabile tramite `config/settings.py`. Non serve modificare il codice sorgente! ## Modificare le Dimensioni del Terreno ### Grid Size (Numero di Tiles) ```python TERRAIN = { 'grid_size': 20, # Griglia 20×20 ... } ``` #### Effetti ``` grid_size = 10: grid_size = 30: ┌────────────┐ ┌────────────────────┐ │ 10×10 │ │ 30×30 │ │ tiles │ │ molte tiles │ │ │ │ │ └────────────┘ └────────────────────┘ Meno dettaglio Più dettaglio Più veloce Più lento ``` #### Consigli - **10×10**: Test rapidi, PC lenti - **20×20**: Bilanciato (default) - **30×30**: Dettaglio alto - **50×50**: Molto dettagliato, richiede PC potente ### Dimensione Tile ```python TERRAIN = { 'tile_width': 30, # Larghezza in pixel 'tile_height': 30, # Altezza in pixel ... } ``` #### Effetti ``` tile_size = 20: tile_size = 40: Small tiles Big tiles ╱╲╱╲╱╲ ╱──╲╱──╲ ╱╲╱╲╱╲╱ ╱────╲──╱ ╱╲╱╲╱╲╱╲ ╱──────╲╱ ``` **Nota**: Se cambi tile_size, adatta anche la camera! ```python # tile_size piccole → camera più vicina CAMERA = { 'distance': 400, # Invece di 800 'height': 200, # Invece di 450 } ``` ## Modificare il Terreno ### Scala Perlin Noise ```python TERRAIN = { 'perlin_scale': 8.0, # IMPORTANTE! ... } ``` #### Effetti ``` scale = 3.0: scale = 15.0: Grandi formazioni Piccole colline ╱╲____╱╲ ╱╲╱╲╱╲╱╲ ╱ ──── ╲ ╱╲╱╲╱╲╱╲╱ ╱ ╲ ╱╲╱╲╱╲╱╲╱╲ Montagne ampie Terreno mosso ``` **Regola**: scale ≈ grid_size / 2.5 - Grid 10×10 → scale = 4.0 - Grid 20×20 → scale = 8.0 - Grid 30×30 → scale = 12.0 - Grid 50×50 → scale = 20.0 ### Moltiplicatore Altezza ```python TERRAIN = { 'height_multiplier': 80.0, ... } ``` #### Effetti ``` multiplier = 30: multiplier = 150: Colline basse Montagne alte ___╱╲___ ╱╲ ╱ ╲ ╱ ╲ ╱__________╲ ╱ ╲ ╱______╲ ``` **Consigli**: - 30-50: Terreno pianeggiante - 60-80: Colline (default) - 100-150: Montagne - 200+: Drammatico, picchi estremi ### Octaves (Dettaglio) ```python TERRAIN = { 'perlin_octaves': 4, ... } ``` #### Effetti ``` octaves = 1: octaves = 6: Forma base Molti dettagli ╱╲ ╱╲╱╲ ╱ ╲ ╱╲╱╲╱╲ ╱ ╲ ╱╲╱╲╱╲╱╲ Liscio Complesso Veloce Lento ``` **Consigli**: - 1-2: Forme grandi e semplici - 3-4: Bilanciato (default) - 5-6: Molto dettagliato - 7+: Estremo, rallenta ### Persistence (Influenza Dettagli) ```python TERRAIN = { 'perlin_persistence': 0.6, ... } ``` #### Effetti ``` persistence = 0.3: persistence = 0.8: Dettagli deboli Dettagli forti ╱╲____ ╱╲╱╲╱╲ ╱╲ ╱╲ ╱╲╱╲╱╲╱╲ ╱ ──── ╲ ╱╲╱╲╱╲╱╲╱ Forme larghe Texture ruvida ``` **Range**: 0.0 - 1.0 - 0.3-0.4: Liscio - 0.5-0.6: Bilanciato (default) - 0.7-0.8: Ruvido ### Lacunarity (Frequenza Dettagli) ```python TERRAIN = { 'perlin_lacunarity': 2.5, ... } ``` #### Effetti ``` lacunarity = 1.5: lacunarity = 3.0: Dettagli sparsi Dettagli densi ╱╲ ╱╲ ╱╲╱╲╱╲ ╱ ── ╲ ╱╲╱╲╱╲╱ ╱ ╲ ╱╲╱╲╱╲╱╲ ``` **Range**: 1.0 - 4.0 - 1.5-2.0: Dettagli distanziati - 2.0-2.5: Bilanciato (default) - 2.5-3.0: Dettagli fitti ### Smoothing (Levigatura) ```python TERRAIN = { 'enable_smoothing': False, # Default: disabilitato 'smoothing_iterations': 2, 'smoothing_factor': 0.5, ... } ``` #### Effetti ``` Smoothing OFF: Smoothing ON: ╱╲╱╲ ╱──╲ ╱╲╱╲╱╲ ╱ ╲ ╱╲╱╲╱╲╱ ╱ ╲ Originale Perlin Levigato ``` **Nota**: Lo smoothing riduce le caratteristiche uniche del Perlin noise! ## Configurare la Camera ### Distanza e Altezza ```python CAMERA = { 'distance': 800, 'height': 450, ... } ``` #### Visualizzazione ``` Distanza piccola (400): Distanza grande (1200): Camera Camera ● ● ╱│ ╱│ ╱ │ ╱ │ ╱ │ ╱ │ Terreno Terreno Vista vicina Vista lontana Dettaglio alto Panoramica ``` **Altezza**: Quanto "sopra" il terreno - Bassa (200): Vista laterale - Media (450): Vista isometrica (default) - Alta (800): Vista dall'alto ### Velocità Controlli ```python CAMERA = { 'zoom_speed': 10.0, # Velocità zoom (UP/DOWN) 'height_speed': 10.0, # Velocità altezza (LEFT/RIGHT) ... } ``` **Consigli**: - 5.0: Controlli lenti, precisi - 10.0: Bilanciato (default) - 20.0: Controlli veloci ### Field of View ```python CAMERA = { 'fov': 45, # Gradi ... } ``` #### Effetti ``` FOV = 30: FOV = 70: Zoom in Zoom out │╲ ╲___ │ ╲ │ ___ │ ╲ │ ___ Teleobiettivo Grandangolo ``` **Range**: 30-90 - 30-40: Zoom, distorsione minima - 45: Bilanciato (default) - 60-90: Grandangolo, più distorsione ### Clipping Planes ```python CAMERA = { 'near_clip': 0.1, 'far_clip': 5000.0, ... } ``` **near_clip**: Quanto vicino puoi avvicinarti **far_clip**: Quanto lontano puoi vedere ``` Far Plane │ ╱╲ │ ╱ ╲ │ ╱ ● ╲ │ Near Plane ``` **Nota**: Se oggetti scompaiono, aumenta far_clip! ### Limiti ```python CAMERA = { 'min_distance': 200, 'max_distance': 2000, ... } ``` Previene: - Zoom troppo vicino (camera dentro terreno) - Zoom troppo lontano (terreno invisibile) ## Modificare i Biomi ### Colori ```python BIOME_COLORS = { 'water': (65, 105, 225), # Blu 'sand': (238, 214, 175), # Beige 'grass_low': (34, 139, 34), # Verde scuro 'grass_mid': (107, 142, 35), # Verde oliva 'grass_high': (85, 107, 47), # Verde scuro oliva 'rock': (139, 137, 137), # Grigio 'snow': (255, 250, 250) # Bianco neve } ``` #### Sperimentare ```python # Terreno desertico BIOME_COLORS = { 'water': (139, 69, 19), # Marrone (oasi fangose) 'sand': (244, 164, 96), # Arancione sabbia 'grass_low': (218, 165, 32), # Oro (dune) 'grass_mid': (210, 180, 140), # Tan (roccia) 'grass_high': (160, 82, 45), # Sienna (roccia) 'rock': (139, 90, 43), # Marrone scuro 'snow': (255, 228, 181) # Crema (sale?) } ``` ```python # Terreno alieno BIOME_COLORS = { 'water': (255, 0, 255), # Magenta 'sand': (0, 255, 255), # Ciano 'grass_low': (255, 255, 0), # Giallo 'grass_mid': (0, 255, 0), # Verde brillante 'grass_high': (255, 128, 0), # Arancione 'rock': (128, 0, 255), # Viola 'snow': (255, 0, 0) # Rosso } ``` ### Soglie Biomi ```python BIOME_THRESHOLDS = { 'water': -10, 'sand': 0, 'grass_low': 10, 'grass_mid': 25, 'grass_high': 40, 'rock': 55, 'snow': 70 } ``` #### Logica ``` Altezza < -10 → Acqua -10 ≤ Altezza < 0 → Sabbia 0 ≤ Altezza < 10 → Erba bassa 10 ≤ Altezza < 25 → Erba media 25 ≤ Altezza < 40 → Erba alta 40 ≤ Altezza < 55 → Roccia 55 ≤ Altezza < 70 → Neve 70 ≤ Altezza → Neve ``` #### Modificare Distribuzione ```python # Più acqua, meno montagne BIOME_THRESHOLDS = { 'water': 0, # Era -10 'sand': 15, # Era 0 'grass_low': 30, # Era 10 'grass_mid': 45, # Era 25 'grass_high': 60, # Era 40 'rock': 80, # Era 55 'snow': 100 # Era 70 } ``` ``` Prima (default): Modificato: ███████ Snow ████ Snow ████████ Rock █████ Rock █████████ Grass High ███████ Grass High ██████████ Grass Mid ████████ Grass Mid ████████████ Grass Low █████████ Grass Low ████ Sand ███████ Sand ██ Water ████████ Water ``` ### Aggiungere Nuovi Biomi ```python # 1. Aggiungi colore BIOME_COLORS = { ... 'lava': (255, 69, 0), # Rosso-arancione 'ice': (173, 216, 230) # Azzurro ghiaccio } # 2. Aggiungi soglia BIOME_THRESHOLDS = { ... 'lava': -20, # Sotto acqua = lava 'ice': 85 # Sopra neve = ghiaccio } # 3. Modifica get_color_for_height in terrain_renderer.py def get_color_for_height(self, height): if height < BIOME_THRESHOLDS['lava']: return BIOME_COLORS['lava'] elif height < BIOME_THRESHOLDS['water']: return BIOME_COLORS['water'] # ... altri biomi ... elif height < BIOME_THRESHOLDS['ice']: return BIOME_COLORS['snow'] else: return BIOME_COLORS['ice'] ``` ## Rendering ### Bordi Griglia ```python RENDERING = { 'line_width': 5.0, # Spessore bordi tile ... } ``` #### Effetti ``` line_width = 1.0: line_width = 8.0: ╱─╲╱─╲ ╱══╲╱══╲ ╱─╲╱─╲╱ ╱══╲╱══╲╱ Bordi sottili Bordi spessi ``` **Range**: 1.0 - 10.0 ### Colore Griglia ```python RENDERING = { 'line_color': (0, 0, 0), # Nero (R, G, B) ... } ``` **Esempi**: - `(0, 0, 0)`: Nero (default) - `(255, 255, 255)`: Bianco - `(128, 128, 128)`: Grigio - `(255, 0, 0)`: Rosso ### Illuminazione ```python RENDERING = { 'light_position': (1.0, 1.0, 1.0, 0.0), 'light_ambient': (0.3, 0.3, 0.3, 1.0), 'light_diffuse': (0.8, 0.8, 0.8, 1.0), ... } ``` #### light_position ``` (1, 1, 1, 0) → Luce direzionale da alto-destra (x, y, z, w) w=0 → direzionale w=1 → punto luce ``` #### light_ambient Luce "di base" (ombre non completamente nere): ``` ambient = 0.1: ambient = 0.5: Ombre scure Ombre chiare ███ ▓▓▓ ██ ▓▓ ``` #### light_diffuse Luce "diretta" (quanto sono illuminate le superfici): ``` diffuse = 0.5: diffuse = 1.0: Illuminazione Illuminazione moderata piena ▓▓▓ ███ ▓▓ ██ ``` ## Preset Configurazioni ### Montagne Drammatiche ```python TERRAIN = { 'grid_size': 25, 'perlin_scale': 10.0, 'height_multiplier': 150.0, 'perlin_octaves': 5, 'perlin_persistence': 0.7, 'perlin_lacunarity': 2.8, } CAMERA = { 'distance': 1000, 'height': 600, } ``` ### Colline Dolci ```python TERRAIN = { 'grid_size': 20, 'perlin_scale': 5.0, 'height_multiplier': 40.0, 'perlin_octaves': 3, 'perlin_persistence': 0.4, 'perlin_lacunarity': 2.0, 'enable_smoothing': True, 'smoothing_iterations': 3, } CAMERA = { 'distance': 700, 'height': 400, } ``` ### Pianure con Dettaglio ```python TERRAIN = { 'grid_size': 30, 'perlin_scale': 12.0, 'height_multiplier': 30.0, 'perlin_octaves': 6, 'perlin_persistence': 0.6, 'perlin_lacunarity': 2.5, } CAMERA = { 'distance': 1200, 'height': 500, } ``` ### Isola Tropicale ```python TERRAIN = { 'grid_size': 20, 'perlin_scale': 6.0, 'height_multiplier': 60.0, } BIOME_THRESHOLDS = { 'water': 5, # Più acqua 'sand': 12, # Spiagge ampie 'grass_low': 20, 'grass_mid': 35, 'grass_high': 50, 'rock': 70, 'snow': 90, } BIOME_COLORS = { 'water': (0, 119, 190), # Blu oceano 'sand': (255, 233, 127), # Sabbia dorata 'grass_low': (0, 155, 119), # Verde tropicale 'grass_mid': (34, 139, 34), 'grass_high': (85, 107, 47), 'rock': (139, 137, 137), 'snow': (255, 250, 250), } ``` ## Funzionalità Avanzate ### Esportare Heightmap Aggiungi a `terrain_renderer.py`: ```python def export_heightmap(self, filename): """Salva heightmap come immagine PNG""" from PIL import Image import numpy as np # Normalizza altezze 0-255 heights = self.terrain_generator.heightmap normalized = ((heights - heights.min()) / (heights.max() - heights.min()) * 255) # Crea immagine img = Image.fromarray(normalized.astype('uint8')) img.save(filename) print(f"Heightmap salvata: {filename}") ``` Uso: ```python # In app.py, handle_events if event.type == pygame.KEYDOWN: if event.key == pygame.K_s: # Premi S per salvare self.terrain_renderer.export_heightmap('heightmap.png') ``` ### Salvare/Caricare Seed Aggiungi a `terrain_generator.py`: ```python def generate_with_seed(self, seed): """Genera terreno con seed specifico""" import random random.seed(seed) self.seed = seed self.generate() def get_seed(self): """Ottieni seed corrente""" return self.seed ``` Uso: ```python # Genera con seed generator.generate_with_seed(12345) # Salva seed current_seed = generator.get_seed() print(f"Seed corrente: {current_seed}") # Ricrea stesso terreno generator.generate_with_seed(current_seed) ``` ### Animazione (Terreno che Cambia) Aggiungi a `app.py`: ```python def __init__(self, ...): ... self.animation_enabled = False self.animation_offset = 0.0 def update(self): if self.animation_enabled: self.animation_offset += 0.01 # Rigenera con offset temporale for i in range(grid_size): for j in range(grid_size): x = i / scale y = j / scale height = noise.pnoise3( x, y, self.animation_offset, # 3D noise! octaves=octaves, ... ) ``` ### Minimap Aggiungi nuovo file `src/rendering/minimap.py`: ```python class Minimap: def __init__(self, terrain_generator, size=200): self.terrain = terrain_generator self.size = size def render(self, screen_width, screen_height): """Disegna minimap in angolo""" glMatrixMode(GL_PROJECTION) glPushMatrix() glLoadIdentity() glOrtho(0, screen_width, 0, screen_height, -1, 1) glMatrixMode(GL_MODELVIEW) glPushMatrix() glLoadIdentity() # Disegna minimap x = screen_width - self.size - 10 y = 10 # ... rendering heightmap 2D ... glPopMatrix() glMatrixMode(GL_PROJECTION) glPopMatrix() ``` ## Troubleshooting ### Terreno Troppo Piatto ✅ **Soluzione**: - Aumenta `height_multiplier` (da 80 a 120) - Riduci `perlin_scale` (da 8.0 a 5.0) - Aumenta `perlin_persistence` (da 0.6 a 0.7) ### Terreno Troppo Caotico ✅ **Soluzione**: - Riduci `height_multiplier` (da 80 a 50) - Aumenta `perlin_scale` (da 8.0 a 12.0) - Riduci `perlin_octaves` (da 4 a 2) - Abilita `enable_smoothing` ### Camera Troppo Lontana ✅ **Soluzione**: - Riduci `distance` (da 800 a 500) - Riduci `height` (da 450 a 300) ### Bordi Invisibili ✅ **Soluzione**: - Aumenta `line_width` (da 5.0 a 8.0) - Cambia `line_color` per contrasto ### Performance Basse ✅ **Soluzione**: - Riduci `grid_size` (da 20 a 15) - Riduci `perlin_octaves` (da 4 a 3) - Disabilita `enable_smoothing` - Riduci `far_clip` (da 5000 a 3000) ### Colori Strani ✅ **Soluzione**: - Verifica `BIOME_COLORS` (RGB 0-255) - Verifica `BIOME_THRESHOLDS` (ordine crescente) - Verifica `height_multiplier` (altezze compatibili con soglie) ## Checklist Personalizzazione Prima di modificare, salva il file originale! ```bash cp config/settings.py config/settings.py.backup ``` ### Cambio Dimensioni - [ ] Modifica `grid_size` - [ ] Adatta `perlin_scale` (≈ grid_size / 2.5) - [ ] Testa performance - [ ] Adatta `camera.distance` se necessario ### Cambio Stile Terreno - [ ] Modifica `height_multiplier` - [ ] Modifica `perlin_octaves` - [ ] Modifica `perlin_persistence` - [ ] Testa con R (rigenera) - [ ] Verifica distribuzione biomi ### Cambio Colori - [ ] Modifica `BIOME_COLORS` - [ ] Verifica valori RGB (0-255) - [ ] Testa con diversi terreni - [ ] Screenshot per confronto ### Cambio Soglie - [ ] Modifica `BIOME_THRESHOLDS` - [ ] Verifica ordine crescente - [ ] Testa rigenera più volte - [ ] Verifica copertura biomi ## Riepilogo ### File Principale **config/settings.py** contiene tutto! ### Sezioni Importanti 1. **TERRAIN**: Dimensioni, Perlin noise 2. **CAMERA**: Posizione, controlli, FOV 3. **RENDERING**: Bordi, colori, illuminazione 4. **BIOME_COLORS**: Colori biomi (RGB) 5. **BIOME_THRESHOLDS**: Soglie altezze ### Workflow Consigliato 1. Modifica `config/settings.py` 2. Salva file 3. Esegui `python main.py` 4. Premi `R` per rigenerare 5. Usa frecce per testare camera 6. Ripeti fino a soddisfazione! ### Backup Sempre fare backup prima di grandi modifiche: ```bash cp config/settings.py config/settings_backup_YYYYMMDD.py ``` --- **Congratulazioni!** Ora hai tutte le conoscenze per personalizzare completamente il tuo generatore di terreni isometrici! [← Capitolo Precedente](07-camera.md) | [Torna all'indice](README.md)