Eccoci giunti alla terza parte della nostra serie di articoli su come creare proceduralmente una mappa giocabile tramite il modello matematico del “Cellular Automata” ed in particolare utilizzando le regole del “Gioco della vita” di John Conway. Nei precedenti articoli abbiamo impostato la classe che genera la mappa e definito i metodi per crearla e rappresentarla. Tuttavia ci siamo resi conto che le regole del gioco della vita, così come sono, non sono sufficienti a creare una mappa giocabile per cui hanno bisogno di un paio di variazioni.  Quello che faremo sarà semplificarle in questo modo:

  • Una cella viva rimane viva se ha x o più vicini vivi altrimenti muore
  • Una cella morta ritorna in vita se ha più di x vicini vivi, resta morta altrimenti

Definiamo quindi due variabili private per la nostra classe che chiameremo lifeNumber e deathNumber e modifichiamo il costruttore


int lifeNumber, deathnumber;

public MapGenerator(int width, int height, int percentageOfLife, int lifeNumber, int deathNumber)
{
    this.width = width;
    this.height = height;
    this.lifeNumber = lifeNumber;
    this.deathnumber = deathNumber;
    this.percentageOfLife = percentageOfLife;
    this.map = new bool[width, height];
    generateMap();
}

 

Non ci resta ora altro da fare che modificare il nostro metodo ExecuteTransaction per far seguire alla transazione di stato della mappa le nuove regole

public void ExecuteTransaction(int iterations)
{
    bool[,] newmap = new bool[width, height];
    for (int iteration = 0; iteration <= iterations; iteration++)
    {
       for (int x = 0; x < width; x++)
       {
          for (int y = 0; y < height; y++)
          {
             int neighbours = getNeighboursCount(x, y);
             if (map[x, y])
             {
                if (neighbours < lifeNumber)
                   newmap[x, y] = false;
                else
                   newmap[x, y] = true;
             }
             else
             {
                if (neighbours > deathnumber)
                   newmap[x, y] = true;
                else
                   newmap[x, y] = false;
             } 
          }
       }
    }
    map = newmap;
 }

Mettiamo alla prova il nostro nuovo modello. Lanciamo la nostra windowsform application modificando la chiamata la costruttore della classe MapGenerator e passando il valore 4 ad entrambe le variabili lifeNumber e deathNumber. Come output avremo qualcosa di molto simile a questo:

Ancora molto caotica come situazione...

Ancora molto caotica come situazione…

Il caos che ci aspettavamo dato che non abbiamo modificato per niente il nostro codice di generazione della mappa. Eseguiamo però le transazioni e vediamo cosa accade:

Ed eccola finalmente la nostra mappa!!!

Ed eccola finalmente la nostra mappa!!!

Molto molto meglio. Siamo finalmente riusciti ad ottenere una mappa casuale ma ordinata. Con questa potremmo tranquillamente rappresentare un continente circondato dalle acque all’interno del quale sono distinguibili laghi o in alternativa montagne. Potremmo facilmente aggiungere, ancora in maniera procedurale, degli spot per l’ingresso a dei dungeon o per delle città. Insomma può essere tranquillamente questa la base per la mappa di un gdr. Ma possiamo fare di più: semplicemente giocando con le variabili di ingresso del costruttore del MapGenerator potremmo ottenere configurazioni totalmente diverse. Ecco cosa accade semplicemente impostando a 3 la variabile lifeNumber

Diminuendo di uno il valore di lifeNumber otteniamo qualcosa di molto simile alla mappa di un dungeon

Diminuendo di uno il valore di lifeNumber otteniamo qualcosa di molto simile alla mappa di un dungeon

E se quindi decidessimo di inserire nella nostra mappa uno spot per un dungeon potremmo tranquillamente riutilizzare il nostro MapGenerator per averne la mappa.

Altre modifiche al codice possono essere apportate ma direi che è tempo di abbandonare la rappresentazione testuale della mappa e di spostarci su Unity per avere qualcosa di più gradevole da vedere. E il tutto sarà oggetto dei prossimi articoli

 

 

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *