Kachelkarte erstellen

25

Ich programmiere ein auf Kacheln basierendes Spiel und habe einige Grundkacheln (Gras, Dreck usw.), aber ich kann nicht herausfinden, wie ich eine gute Zufallskartengenerierung machen kann, weil ich bei der Auswahl der Kacheln wirklich zufällig bin Sollte Gras / Dreck sein, bekomme ich folgendes:

Bild im Spiel

Ich verstehe, warum dies geschieht, aber ich möchte zufällig zusammenhängende Gras- oder Schmutzflächen schaffen. Etwas, das sinnvoller wäre:

Erwünschtes Ergebnis

Vilda
quelle
1
Zusätzlich zu den vorgeschlagenen Antworten können Sie Ihr eigenes zellulares Automatenmodul schreiben, um solche Karten zu erstellen. Wenn Sie die Regeln des Automaten ändern, können Sie sehr unterschiedliche Verhalten erzeugen, was zu sehr unterschiedlichen Kartentypen führt. Wenn Sie zum Beispiel einen 2-D-Automaten ähnlich dem Leben erhalten, können Überschwemmungsregeln zu "Ozean und Inseln" führen (wie in Ihrem Bild oben), und eine Regel wie 1267/17 kann zu schönen Laberynths führen.
Manu343726

Antworten:

19

Was Sie tun könnten, ist zufällig eine Voronoi-Karte wie diese zu generieren:

  1. Wählen Sie nach dem Zufallsprinzip center points(siehe die schwarzen Punkte) und entscheiden Sie nach dem Zufallsprinzip, ob es sich um Gras oder Schmutz handelt.
  2. Prüfen Sie dann für alle Fliesen, ob sie am nächsten an center pointSchmutz oder Gras liegen.
  3. Getan!

Wenn Sie zuvor für jedes Plättchen (Rauschen) eine Münze geworfen haben, liefert die Erstellung eines Voronoi-Diagramms ein viel besseres Ergebnis.

Sie könnten durch Division des auf diese Verbesserung center pointsin islandseinem Algorithmus , dass:

  1. Wählt eine kleine Gruppe aus centers pointsund bezeichnet sie als leaders.
  2. Fügt iterativ in jeder Runde einen zufälligen benachbarten unentschlossenen Mittelpunkt hinzu.
  3. Getan!

Bildbeschreibung hier eingeben

wolfdawn
quelle
1
Danke, aber es scheint eine sehr schwierige Lösung zu sein.
Vilda
2
Dies ist keine sehr schwierige Lösung. Zuerst die zufällig auswählen center points. Dann entscheiden Sie, ob es sich um Gras oder Schmutz handelt. Überfliege nun das Array und entscheide, ob jedes Plättchen einem Schmutzpunkt oder einem Graspunkt am nächsten liegt. Vielleicht sag mir welcher Teil herausfordernd?
Wolfdawn
Distanz messen. Wie auch immer, ich werde versuchen, Sie zu informieren.
Vilda
Ok, also ich habe einige Punkte erfolgreich generiert. ( dropbox.com/s/dlx9uxz8kkid3kc/random_tile_map2.png ) und so sieht meine gesamte Klasse zum Generieren so aus: dropbox.com/s/pxhn902xqrhtli4/gen.java . Aber es geht immer noch nicht.
Vilda
3
@ViliX Ihre Links sind defekt
Artur Czajka
24

Sie können Perlin-Rauschen verwenden, das normalerweise zur Erzeugung von Höhenkarten verwendet wird. Perlin-Rauschen in Spielen

Dann könnten Sie die Höhen als Ratgeber verwenden, wie hoch die Wahrscheinlichkeit ist, dass Gras / Schmutz in einer Region der Karte auftritt.

Beispiel (Perlin-Rauschwerte von 0 bis 256): Wenn der Wert über 200 liegt, beträgt die Chance, dass Gras platziert wird, 80% (Schmutz 20%). Wenn der Wert zwischen 100 und 200 liegt, beträgt die Chance, dass Gras platziert wird, 50% (Schmutz ebenfalls 50%). Wenn der Wert unter 100 liegt, beträgt die Chance, dass Gras platziert wird, 20% (Schmutz 80%).

Klitz
quelle
Angenommen, ich habe ein Array [] [] von float (0-1 von Wahrscheinlichkeit) und kann es verwenden, um Kacheln mit der Wahrscheinlichkeit zu erzeugen. Aber wie fülle ich dieses Wahrscheinlichkeitsarray? Das Array ist (sagen wir mal) 400x200, wie füllt man es mit Wahrscheinlichkeitswerten?
Vilda
Er schlägt vor, es mit Perlinrauschen zu füllen (anstelle von weißem Rauschen wie Münzwurf).
Wolfdawn
Ja, aber wie kann ich das erreichen?
Vilda
Der Link, den ich gepostet habe, könnte diese Frage klären. Erzeugen Sie zuerst ein Rauschen und glätten Sie dieses dann. Das Ergebnis ist ein zweidimensionales Array, das Sie für die weitere Generierung der Tilemap verwenden können. link
Klitz
Es ist eine wirklich gute Antwort, aber es werden selten ähnliche Ergebnisse wie die von Ihnen präsentierten erzielt.
Wolfdawn
8

Bildbeschreibung hier eingeben

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

Hier ist meine Version der zellularen Automatenmethode: Fülle das Gitter mit Zufallszahlen und führe diese kullularen Automatenregeln ein paar Mal aus

  • Wenn eine lebende Zelle weniger als zwei lebende Nachbarn hat, stirbt sie.
  • Wenn eine lebende Zelle zwei oder drei lebende Nachbarn hat, bleibt sie am Leben.
  • Wenn eine lebende Zelle mehr als drei lebende Nachbarn hat, stirbt sie.
  • Wenn eine tote Zelle genau drei lebende Nachbarn hat, wird sie lebendig.

und es sieht aus wie eine Höhle

Mit diesem Code kann der Index in die X & Y-Position und zurück konvertiert werden

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

Ich gebe nur eine Liste von Bools zurück, weil ich diese Liste für viele Dinge benutze: Höhlen, Bäume, Blumen, Gras, Nebel, Wasser. Du kannst sogar mehrere Listen auf verschiedene Arten kombinieren. Hier entferne ich zuerst alle kleineren Höhlen und verbinde dann zwei zufällige Listen

Bildbeschreibung hier eingeben

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 Wut
quelle
2
Erläutern Sie bitte die Funktionsweise Ihres Codes, anstatt ein Beispiel für die Funktionsweise, einen Link und den Code selbst zu veröffentlichen. Ihre Antwort sollte in sich geschlossen sein, damit sie auch dann verwendet werden kann, wenn die Links nicht funktionieren.
Fund Monicas Klage am
6

Wählen Sie einen Punkt auf der Karte. Platzieren Sie den gewünschten Kacheltyp mit einem Basiswert wie 40. Verfolgen Sie, wo Sie die neu gewünschte Kachel platziert haben. Fügen Sie den Startpunkt zu einer Liste hinzu.

Für jeden Punkt in dieser Liste besuchen Sie alle Nachbarn. Solange Sie noch genügend Energie haben (ab 40), fügen Sie ein gewünschtes Plättchen hinzu und fügen Sie es der Liste hinzu, die Sie besuchen möchten. Geben Sie der neuen Kachel weniger Kraft, die Sie bestimmen. Am einfachsten = zufälliges Absenken. Nachdem Sie die Kachel aus der Liste besucht haben, entfernen Sie sie. Beginnen Sie erneut, indem Sie nicht besuchte, aber erstellte Kacheln besuchen.

Jaapjan
quelle