✚ Sviluppo videogiochi

Generazione procedurale di livelli: seed, rumore e dungeon

Come generare livelli in modo procedurale: generatori pseudocasuali con seed, rumore di Perlin, automi cellulari per caverne e dungeon a stanze e corridoi.

La generazione procedurale permette a un gioco di creare livelli, mappe o oggetti tramite algoritmi invece che a mano. È ciò che rende ogni partita di un roguelike diversa dalla precedente e che consente a certi giochi di offrire mondi enormi senza che qualcuno li abbia disegnati cella per cella. Non è però una scorciatoia per evitare il level design: è un modo diverso di farlo, in cui si progettano le regole invece del risultato.

Il seed: casuale ma riproducibile

Il cuore di ogni generatore è un generatore di numeri pseudocasuali (PRNG). Partendo da un valore iniziale, il seed, produce una sequenza che sembra casuale ma è completamente determinata: lo stesso seed genera sempre la stessa sequenza.

Questa proprietà è preziosa:

  • i giocatori possono condividere un seed per giocare lo stesso mondo;
  • un errore in un livello generato si può riprodurre esattamente;
  • in multiplayer basta trasmettere il seed, non l'intera mappa;
  • un salvataggio può memorizzare il seed invece dell'intero livello.

Per mantenere la riproducibilità bisogna usare un generatore dedicato alla generazione, separato da quello usato per eventi di gioco come i colpi critici. Altrimenti, un nemico che spara un colpo in più cambia la sequenza e il livello successivo diventa diverso.

Rumore per terreni e paesaggi

I numeri casuali puri producono un risultato simile al rumore di un televisore: ogni punto è indipendente dai vicini. Per terreni, nuvole o distribuzione della vegetazione servono valori che variano in modo continuo. È il ruolo delle funzioni di rumore coerente, come il rumore di Perlin, sviluppato da Ken Perlin negli anni Ottanta, e le sue varianti.

Una funzione di rumore riceve coordinate e restituisce un valore, per esempio tra −1 e 1, che cambia gradualmente al variare delle coordinate. Sommando più strati, o ottave, a frequenze crescenti e ampiezze decrescenti si ottengono forme più naturali:

altezza = 0
ampiezza = 1
frequenza = 1
per ottava da 1 a 5:
    altezza += rumore(x * frequenza, y * frequenza) * ampiezza
    ampiezza *= 0.5
    frequenza *= 2

Le ottave basse definiscono le grandi forme, colline e valli; quelle alte aggiungono i dettagli. Con soglie sull'altezza si assegnano i tipi di terreno: acqua sotto un certo valore, sabbia appena sopra, poi erba, roccia, neve.

Caverne con gli automi cellulari

Per caverne dall'aspetto organico funziona molto bene un automa cellulare, una griglia in cui ogni cella cambia stato in base ai vicini:

  1. si riempie la griglia a caso, con circa il 45% di celle solide;
  2. per alcune iterazioni, ogni cella diventa solida se ha almeno cinque vicini solidi su otto, altrimenti diventa vuota;
  3. dopo quattro o cinque passaggi il rumore iniziale si è trasformato in caverne con pareti arrotondate.

Un passaggio successivo è indispensabile: verificare la connettività. Con un riempimento a macchia d'olio si individuano le zone vuote separate; si tengono solo le più grandi o si scavano corridoi per collegarle.

Dungeon a stanze e corridoi

Per livelli più strutturati, con stanze rettangolari, esistono diversi metodi.

Posizionamento casuale

Si generano stanze di dimensioni casuali in posizioni casuali, scartando quelle che si sovrappongono, e si collegano in ordine con corridoi a «L». È semplice e funziona bene per mappe piccole.

Partizione binaria dello spazio

Si divide ricorsivamente la mappa in due parti, alternando tagli orizzontali e verticali, fino a ottenere aree della dimensione desiderata. In ciascuna foglia si colloca una stanza, poi si collegano le stanze sorelle risalendo l'albero. Il risultato è una distribuzione uniforme senza sovrapposizioni.

Grafi di stanze

Si posizionano le stanze, si costruisce un grafo che le collega, per esempio tutte le coppie vicine, e si ricava un albero ricoprente minimo per garantire che tutto sia raggiungibile con il minor numero di corridoi. Aggiungendo poi qualche arco scartato si creano cicli, che rendono l'esplorazione meno lineare.

Generare livelli giocabili

Un livello generato può essere tecnicamente valido e comunque pessimo da giocare. Alcune regole aiutano:

Problema Contromisura
Uscita irraggiungibile Verifica con pathfinding dopo la generazione
Difficoltà casuale Collocare nemici in base alla distanza dall'ingresso
Livelli monotoni Mescolare pezzi disegnati a mano con parti generate
Risultati estremi Rigenerare con un altro seed se certi criteri non sono soddisfatti

L'approccio misto è molto diffuso: stanze o blocchi progettati a mano, assemblati da un algoritmo. Si unisce la qualità del design umano alla varietà della generazione.

In sintesi

  • La generazione procedurale progetta regole invece di singoli livelli.
  • Un PRNG con seed dedicato rende i risultati casuali ma riproducibili.
  • Il rumore coerente a più ottave produce terreni e paesaggi naturali.
  • Automi cellulari, partizione binaria e grafi di stanze generano caverne e dungeon.
  • Verifiche di connettività, difficoltà e pezzi fatti a mano rendono i livelli davvero giocabili.
MM
Marco Marzaduri

Marco Marzaduri si occupa di cybersecurity, informatica forense e sviluppo web. Laureato in informatica, unisce il rigore dell'analisi tecnica all'attenzione per le persone che usano la tecnologia.

Leggi anche