Génération d'une carte de tuiles

25

Je programme un jeu basé sur des tuiles et j'ai quelques tuiles de base (herbe, terre, etc.), mais je ne sais pas comment faire une bonne génération de carte aléatoire, parce que quand je fais une sélection vraiment aléatoire, si la tuile devrait être de l'herbe / de la saleté, je reçois ceci:

Image en jeu

Je comprends pourquoi cela se produit, mais ce que je veux, c'est créer des zones continues aléatoires d'herbe ou de saleté. Quelque chose qui aurait plus de sens, comme ceci:

Résultat désiré

Vilda
la source
1
En plus des réponses proposées, vous pouvez écrire votre propre moteur d'automate cellulaire pour générer de telles cartes. En modifiant les règles de l'automate, vous pourriez générer des comportements très différents, conduisant à des types de cartes très différents. Par exemple, avec un automate 2D similaire à Life, les règles d'inondation pourraient conduire à "l'océan et les îles" (comme votre photo ci-dessus), et une règle comme 1267/17 pourrait conduire à de magnifiques laberynths.
Manu343726

Réponses:

19

Ce que vous pourriez faire, c'est générer aléatoirement une carte Voronoi comme ceci:

  1. Cueillir au hasard center points(voir les points noirs) et décider au hasard s'il s'agit d'herbe ou de saleté.
  2. Ensuite, pour toutes les tuiles, vérifiez si elle est la plus proche d'une center pointterre ou d'une herbe.
  3. Terminé!

Si ce que vous avez fait précédemment est de «lancer une pièce» pour chaque tuile (bruit), la génération d'un diagramme de Voronoi fournira un bien meilleur résultat.

Vous pouvez améliorer cela en divisant le center pointsen islandsun algorithme qui:

  1. Choisit un petit groupe de centers pointset les désigne comme leaders.
  2. Ajoute itérativement un point central adjacent indécis aléatoire à chaque tour.
  3. Terminé!

entrez la description de l'image ici

Wolfdawn
la source
1
Merci, mais cela semble être une solution très difficile.
Vilda
2
Ce n'est pas une solution très difficile. Choisissez d'abord au hasard center points. Décidez ensuite s'il s'agit d'herbe ou de terre. Faites maintenant une boucle sur le tableau et décidez si chaque tuile est la plus proche d'un point de saleté ou d'un point d'herbe. Peut-être me dire quelle partie difficile?
wolfdawn
Mesurer la distance. Quoi qu'il en soit, je vais essayer de vous le faire savoir.
Vilda
Ok, j'ai donc réussi à générer quelques points. ( dropbox.com/s/dlx9uxz8kkid3kc/random_tile_map2.png ) et donc toute ma classe de génération ressemble à ceci: dropbox.com/s/pxhn902xqrhtli4/gen.java . Mais ça ne marche toujours pas.
Vilda
3
@ViliX vos liens sont rompus
Artur Czajka
24

Vous pouvez utiliser le bruit perlin, qui est normalement utilisé pour la génération de la carte de hauteur. Bruit de Perlin dans les jeux

Ensuite, vous pouvez utiliser les hauteurs en tant que conseiller, à quel point le risque d'herbe / saleté se produisant dans une région de la carte est élevé.

Exemple (valeurs de bruit Perlin de 0 à 256): Si la valeur est supérieure à 200, la probabilité que l'herbe soit placée est de 80% (saleté 20%). Si la valeur est comprise entre 100 et 200, la probabilité que l'herbe soit placée est de 50% (la saleté aussi 50%). Si la valeur est inférieure à 100, la probabilité que l'herbe soit placée est de 20% (saleté 80%).

Klitz
la source
Ok, disons que j'ai un tableau [] [] de float (0-1 de probabilité) et je peux l'utiliser pour faire apparaître des tuiles avec la probabilité. Mais comment remplir ce tableau de probabilité? Le tableau est (disons) 400x200, comment le remplir de valeurs de probabilité?
Vilda
Il suggère de le remplir de bruit perlin (au lieu d'un bruit blanc comme des pièces de monnaie).
wolfdawn
Oui, mais comment y parvenir?
Vilda
Le lien que j'ai publié pourrait effacer cette question. Générez d'abord un bruit, puis lissez ce bruit. Le résultat sera un tableau bidimensionnel que vous pouvez utiliser pour la génération ultérieure du tilemap. link
Klitz
C'est une très bonne réponse, mais elle obtiendra rarement des résultats similaires à ceux que vous avez présentés.
wolfdawn
8

entrez la description de l'image ici

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

voici ma version de la méthode des automates cellulaires commencez par remplir la grille avec aléatoire puis exécutez ces règles d'automates cullular dessus quelques fois

  • Si une cellule vivante a moins de deux voisins vivants, elle meurt.
  • Si une cellule vivante a deux ou trois voisins vivants, elle reste en vie.
  • Si une cellule vivante a plus de trois voisins vivants, elle meurt.
  • Si une cellule morte a exactement trois voisins vivants, elle devient vivante.

et ça finit par ressembler à une grotte

l'index peut être converti en position x & y et inversement avec ce code

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);
}

Je retourne juste une liste de bools parce que j'utilise cette liste pour beaucoup de choses: grottes, arbres, fleurs, herbe, brouillard, eau, vous pouvez même combiner plusieurs listes de différentes manières ici, je supprime d'abord toutes les grottes plus petites, puis réunissez deux listes aléatoires

entrez la description de l'image ici

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;
}
Rakka Rage
la source
2
Veuillez expliquer ce que fait votre code, plutôt que de publier un échantillon de ce qu'il fait, un lien et le code lui-même. Votre réponse doit être autonome, de sorte que même si les liens se brisent, elle est toujours utilisable.
Fund Monica's Lawsuit
6

Sélectionnez un point sur la carte. Placez le type de tuile souhaité avec une valeur de base telle que 40. Gardez une trace de l'endroit où vous avez placé votre nouvelle tuile désirée. Ajoutez le point de départ à une liste.

Pour chaque point de cette liste, vous visitez tous les voisins. Tant qu'il vous reste assez de puissance (à partir de 40), ajoutez la tuile souhaitée et ajoutez-la à la liste à visiter. Donnez moins de puissance à la nouvelle tuile, déterminée par vous. Plus facile = abaissement aléatoire. Après avoir visité la vignette de la liste, supprimez-la. Recommencez en visitant toutes les tuiles non visitées mais créées.

Jaapjan
la source