Karo haritası oluşturma


25

Döşeme temelli bir oyun programlıyorum ve bazı temel döşemelerim (çimen, kir vb.) Var, ancak iyi rastgele harita oluşturma işlemlerini nasıl yapacağımı çözemiyorum, çünkü eğer gerçekten rastgele seçimler yapıyorsam çim / kir olmalı, şunu anlıyorum:

Oyun içi resim

Bunun neden olduğunu anlıyorum, ancak istediğim bazı rasgele sürekli çim veya toprak alanları oluşturmak. Daha mantıklı olacak bir şey, şöyle:

İstenen sonuç


1
Önerilen cevaplara ek olarak, bu haritaları oluşturmak için kendi hücresel otomat motorunuzu yazabilirsiniz. Otomatın kurallarını değiştirmek, çok farklı harita türlerine yol açan çok farklı davranışlar üretebilir. Örneğin, Hayat'a benzer bir 2d otomatı olarak, sel kuralları "okyanus ve adalara" (yukarıdaki resimdeki gibi) ve 1267/17 gibi bir kural da güzel labirentlere yol açabilir.
Manu343726

Yanıtlar:


19

Yapabilecekleriniz rastgele şöyle bir Voronoi haritası oluşturmaktır:

  1. Rastgele toplama center points(siyah noktalara bakın) ve rastgele ot veya kir olup olmadıklarına karar verin.
  2. Daha sonra tüm döşemeler için center pointkir veya çime en yakın olup olmadığını kontrol edin .
  3. Bitti!

Daha önce yaptığınız her bir karo (para) için "yazı tura atmak" ise, bir Voronoi diyagramı oluşturmak çok daha iyi bir sonuç sağlayacaktır.

Sen bölerek bu getirebileceği center pointsINTO islandsbir algoritma buna:

  1. Küçük bir grup seçer centers pointsve bunları olarak tanımlar leaders.
  2. Yinelemeli olarak her dönüşe rastgele bitişik kararsız bir merkez noktası ekler.
  3. Bitti!

görüntü tanımını buraya girin


1
Teşekkürler, ama çok zor bir çözüm gibi görünüyor.
Vilda

2
Bu çok zor bir çözüm değil. İlk olarak rasgele seç center points. O zaman çimen mi yoksa kir mi olduğuna karar ver Şimdi dizinin üzerinden geçin ve her döşemenin bir kir noktasına veya bir çim noktasına en yakın olup olmadığına karar verin. Belki hangi bölümün zorlu olduğunu bana söyler misin?
wolfdawn

Mesafenin ölçülmesi. Neyse, deneyip size bildireceğim.
Vilda

Tamam, başarılı bir şekilde bazı noktalar oluşturdum. ( dropbox.com/s/dlx9uxz8kkid3kc/random_tile_map2.png ) ve böylece, üretme sınıfım şöyle görünüyor: dropbox.com/s/pxhn902xqrhtli4/gen.java . Ama yine de çalışmıyor.
Vilda

3
@ViliX bağlantılarınız koptu
Artur Czajka

24

Heightmap üretimi için normalde kullanılan perlin gürültüsünü kullanabilirsiniz. Oyunlarda Perlin gürültüsü

Daha sonra yükseklikleri danışman olarak, haritanın bir bölgesinde çimlerin / kirlerin oluşma şansının ne kadar yüksek olduğunu kullanabilirsiniz.

Örnek (0-256 arası perlin gürültü değerleri): Değer 200'den fazlaysa çimlerin yerleştirilme şansı% 80'dir (kir% 20). Değer 100 ile 200 arasındaysa çimlerin yerleştirilme şansı% 50'dir (kir ayrıca% 50). Değer 100'ün altındaysa çimlerin yerleştirilme şansı% 20'dir (kir% 80).


Tamam, diyelim ki [] [] bir yüzerlik (0-1 olasılık) dizisi var ve onu olasılıkla döşemek için kullanabilirim. Fakat bu olasılık dizisini nasıl doldurabilirim? Dizi (diyelim) 400x200, olasılık değerleriyle nasıl doldurulacak?
Vilda

Perlin gürültüsü ile doldurmasını öneriyor (bozuk para gibi beyaz sesler yerine).
wolfdawn

Evet, ama bunu nasıl başarabilirim?
Vilda

Gönderdiğim bağlantı bu soruyu temizleyebilir. Önce bir ses çıkar ve sonra bu gürültüyü yumuşat. Sonuç, tilemap'ın daha sonraki neslinde kullanabileceğin 2 boyutlu bir dizi olacak. link
Klitz

Bu gerçekten iyi bir cevap ama nadiren sunduğunuza benzer sonuçlar elde edecek.
wolfdawn

8

görüntü tanımını buraya girin

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

işte hücresel otomat metodu benim versiyonumdur, ızgarayı rastgele doldurarak başlar, sonra bu o hücresel otomat kurallarını birkaç kez çalıştırın

  • Bir canlı hücrenin ikiden az yaşayan komşusu varsa, ölür.
  • Bir canlı hücrenin iki veya üç yaşayan komşusu varsa, canlı kalır.
  • Eğer yaşayan bir hücrede üçten fazla yaşayan komşu varsa, ölür.
  • Ölü bir hücrenin tam olarak üç yaşayan komşusu varsa, canlanır.

ve bir mağara gibi görünmekle bitiyor

endeks bu kodla x & y pozisyonuna dönüştürülebilir ve geri döndürülebilir

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

sadece bir booller listesi döndürüyorum çünkü bu listeyi birçok şey için kullanıyorum: mağaralar, ağaçlar, çiçekler, çimen, sis, su bile birden fazla listeyi farklı şekillerde birleştirebilirsin;

görüntü tanımını buraya girin

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
Lütfen ne yaptığını, bir bağlantıyı ve kodun kendisini yayınlamak yerine kodunuzun ne yaptığını açıklayın. Cevabınız kendi kendine yeten olmalıdır, böylece bağlantılar kopsa bile, yine de kullanılabilir.
Fon Monica'nın Davası,

6

Haritada bir nokta seçin. İstediğiniz döşeme türünü 40 gibi bir temel değere yerleştirin. Yeni istediğiniz döşemeyi nereye yerleştirdiğinizi takip edin. Bir listeye başlangıç ​​noktasını ekleyin.

Bu listedeki her nokta için, tüm komşuları ziyaret edersiniz. Yeterli güce sahip olduğunuzda (40'tan başlayarak) istediğiniz bir karo ekleyin ve ziyaret edilecek listeye ekleyin. Yeni karo sizin tarafınızdan belirlenen, daha az güç verin. En kolay = rasgele düşürme. Döşemeyi listeden ziyaret ettikten sonra kaldırın. Görünmeyen ancak oluşturulmuş fayansları ziyaret ederek tekrar başlayın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.