Generazione della mappa delle tessere


25

Sto programmando un gioco basato su tessere e ho alcune tessere di base (erba, terra, ecc.), Ma non riesco a capire come creare una buona generazione di mappe casuali, perché quando faccio una selezione davvero casuale, se la tessera dovrebbe essere erba / terra, ottengo questo:

Foto di gioco

Capisco perché questo sta accadendo, ma quello che voglio è creare alcune aree continue casuali di erba o terra. Qualcosa che avrebbe più senso, in questo modo:

Risultato desiderato


1
Oltre alle risposte proposte, è possibile scrivere il proprio motore automa cellulare per generare tali mappe. Modificando le regole dell'automa potresti generare comportamenti molto diversi, portando a tipi di mappe molto diversi. Ad esempio, ottenendo un automa 2d simile alla Vita, le regole di inondazione potrebbero portare a "oceano e isole" (come la tua foto sopra) e una regola come 1267/17 potrebbe portare a splendidi labirinti.
Manu343726,

Risposte:


19

Quello che potresti fare è generare in modo casuale una mappa Voronoi come questa:

  1. Scegli casuale center points(vedi i punti neri) e decidi a caso se sono erba o terra.
  2. Quindi per tutte le piastrelle, controlla se è più vicino a uno center pointdi terra o erba.
  3. Fatto!

Se ciò che hai fatto in precedenza è "lanciare una moneta" per ogni tessera (rumore), la generazione di un diagramma Voronoi fornirà un risultato molto migliore.

Puoi migliorare su questo dividendo center pointsin in islandsun algoritmo che:

  1. Seleziona un piccolo gruppo di centers pointse li designa come leaders.
  2. Aggiunge iterativamente un punto centrale indeciso adiacente casuale ogni turno.
  3. Fatto!

inserisci qui la descrizione dell'immagine


1
Grazie, ma sembra una soluzione molto difficile.
Vilda,

2
Questa non è una soluzione molto difficile. Prima scegli casualmente il file center points. Quindi decidere se sono erba o terra. Ora passa sopra l'array e decidi se ogni tessera è più vicina a un punto sporco o un punto erba. Forse dimmi quale parte è impegnativa?
Wolfdawn,

Misurare la distanza. Comunque, proverò a farti sapere.
Vilda,

Ok, quindi ho generato con successo alcuni punti. ( dropbox.com/s/dlx9uxz8kkid3kc/random_tile_map2.png ) e quindi tutta la mia classe per la generazione è simile alla seguente: dropbox.com/s/pxhn902xqrhtli4/gen.java . Ma non funziona ancora.
Vilda,

3
@ViliX i tuoi collegamenti sono interrotti
Artur Czajka,

24

È possibile utilizzare il rumore perlin, che viene normalmente utilizzato per la generazione di heightmap. Rumore di Perlin nei giochi

Quindi potresti usare le altezze come consulente, quanto è alta la possibilità che si verifichino erba / sporcizia in una regione della mappa.

Esempio (valori di rumore Perlin da 0-256): se il valore è superiore a 200, la possibilità che l'erba venga posizionata è dell'80% (sporco 20%). Se il valore è compreso tra 100 e 200, la probabilità che l'erba venga posizionata è del 50% (sporcizia anche del 50%). Se il valore è inferiore a 100, la probabilità che l'erba venga posizionata è del 20% (sporco 80%).


Ok, diciamo che ho un array [] [] di float (0-1 di probabilità) e posso usarlo per generare tessere con probabilità. Ma come posso riempire questo array di probabilità? L'array è (diciamo) 400x200, come riempirlo con i valori di probabilità?
Vilda,

Sta suggerendo di riempirlo con il rumore del perlin (invece del rumore bianco come il lancio di monete).
Wolfdawn,

Sì, ma come posso farlo?
Vilda,

Il link che ho pubblicato potrebbe chiarire questa domanda. In primo luogo generare un rumore e quindi attenuare questo rumore. Il risultato sarà un array bidimensionale che è possibile utilizzare per l'ulteriore generazione della tilemap. link
Klitz,

È una risposta davvero buona, ma raramente otterrà risultati simili a quelli che hai presentato.
Wolfdawn,

8

inserisci qui la descrizione dell'immagine

http://gamedevelopment.tutsplus.com/tutorials/generate-random-cave-levels-using-cellular-automata--gamedev-9664

ecco la mia versione del metodo degli automi cellulari inizia riempiendo la griglia di casuali quindi esegui queste regole di automi cullulari su di essa un paio di volte

  • Se una cellula vivente ha meno di due vicini viventi, muore.
  • Se una cellula vivente ha due o tre vicini viventi, rimane viva.
  • Se una cellula vivente ha più di tre vicini viventi, muore.
  • Se una cellula morta ha esattamente tre vicini viventi, diventa viva.

e finisce per sembrare una grotta

l'indice può essere convertito nella posizione x & y e viceversa con questo codice

public int TileIndex(int x, int y)
{
    return y * Generator.Instance.Width + x;
}
public Vector2 TilePosition(int index)
{
    float y = index / Generator.Instance.Width;
    float x = index - Generator.Instance.Width * y;
    return new Vector2(x, y);
}

ho appena restituito un elenco di bool perché uso questo elenco per molte cose: grotte, alberi, fiori, erba, nebbia, acqua puoi anche combinare più elenchi in diversi modi qui prima rimuovo tutte le grotte più piccole quindi unisco due elenchi casuali

inserisci qui la descrizione dell'immagine

private int GetAdjacentCount(List<bool> list, Vector2 p)
{
    int count = 0;
    for (int y = -1; y <= 1; y++)
    {
        for (int x = -1; x <= 1; x++)
        {
            if (!((x == 0) && (y == 0)))
            {
                Vector2 point = new Vector2(p.x + x, p.y + y);
                if (PathFinder.Instance.InsideMap(point))
                {
                    int index = PathFinder.Instance.TileIndex(point);
                    if (list[index])
                    {
                        count++;
                    }
                }
                else
                {
                    count++;
                }
            }
        }
    }
    return count;
}
private List<bool> GetCellularList(int steps, float chance, int birth, int death)
{
    int count = _width * _height;
    List<bool> list = Enumerable.Repeat(false, count).ToList();
    for (int y = 0; y < _height; y++)
    {
        for (int x = 0; x < _width; x++)
        {
            Vector2 p = new Vector2(x, y);
            int index = PathFinder.Instance.TileIndex(p);
            list[index] = Utility.RandomPercent(chance);
        }
    }
    for (int i = 0; i < steps; i++)
    {
        var temp = Enumerable.Repeat(false, count).ToList();
        for (int y = 0; y < _height; y++)
        {
            for (int x = 0; x < _width; x++)
            {
                Vector2 p = new Vector2(x, y);
                int index = PathFinder.Instance.TileIndex(p);
                if (index == -1) Debug.Log(index);
                int adjacent = GetAdjacentCount(list, p);
                bool set = list[index];
                if (set)
                {
                    if (adjacent < death)
                        set = false;
                }
                else
                {
                    if (adjacent > birth)
                        set = true;
                }
                temp[index] = set;
            }
        }
        list = temp;
    }
    if ((steps > 0) && Utility.RandomBool())
        RemoveSmall(list);
    return list;
}

2
Spiega cosa fa il tuo codice, piuttosto che pubblicare un esempio di ciò che fa, un link e il codice stesso. La tua risposta dovrebbe essere autonoma, in modo che anche se i collegamenti si interrompono, è ancora utilizzabile.
Finanzia la causa di Monica il

6

Seleziona un punto sulla mappa. Posiziona il tipo di tessera desiderato con un valore base come 40. Tieni traccia di dove hai posizionato la piastrella appena desiderata. Aggiungi il punto iniziale a un elenco.

Per ogni punto in questo elenco, visiti tutti i vicini. Mentre ti rimane abbastanza energia (iniziata da 40) aggiungi una tessera desiderata e aggiungila all'elenco da visitare. Dai alla nuova tessera meno energia, determinata da te. Più semplice = abbassamento casuale. Dopo aver visitato il riquadro dall'elenco, rimuoverlo. Ricominciare visitando tutte le tessere non visitate ma create.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.