Membuat peta ubin

25

Saya memprogram permainan berbasis ubin dan saya memiliki beberapa ubin dasar (rumput, kotoran, dll.), Tapi saya tidak tahu cara membuat generasi peta acak yang baik, karena ketika saya melakukan beberapa pemilihan acak, jika ubin harus rumput / kotoran, saya mendapatkan ini:

Gambar dalam game

Saya mengerti mengapa ini terjadi, tetapi yang saya inginkan adalah membuat beberapa area rumput atau tanah yang acak dan terus menerus. Sesuatu yang lebih masuk akal, seperti ini:

Hasil yang diinginkan

Vilda
sumber
1
Selain jawaban yang diajukan, Anda dapat menulis mesin otomat seluler Anda sendiri untuk menghasilkan peta tersebut. Memodifikasi aturan automaton yang dapat Anda hasilkan dengan perilaku yang sangat berbeda, memimpin dalam berbagai jenis peta. Misalnya, mendapatkan otomat 2d yang mirip dengan Life, aturan banjir dapat mengarah ke "lautan dan pulau" (Seperti gambar Anda di atas), dan aturan seperti 1267/17 dapat mengarah ke laberynths yang indah.
Manu343726

Jawaban:

19

Yang bisa Anda lakukan adalah membuat peta Voronoi secara acak seperti ini:

  1. Memilih secara acak center points(lihat titik-titik hitam) dan secara acak memutuskan apakah itu rumput atau tanah.
  2. Kemudian untuk semua ubin, periksa apakah itu paling dekat dengan center pointtanah atau rumput.
  3. Selesai!

Jika yang Anda lakukan sebelumnya adalah "melempar koin" untuk setiap ubin (noise), membuat diagram Voronoi akan memberikan hasil yang jauh lebih baik.

Anda dapat meningkatkan ini dengan membagi ke center pointsdalam islandsdengan algoritma yang:

  1. Pilih grup kecil centers pointsdan tunjuk sebagai leaders.
  2. Secara bergantian menambahkan titik pusat bimbang acak yang berdekatan setiap belokan.
  3. Selesai!

masukkan deskripsi gambar di sini

wolfdawn
sumber
1
Terima kasih, tetapi sepertinya ini solusi yang sangat sulit.
Vilda
2
Ini bukan solusi yang sangat sulit. Pertama secara acak memilih center points. Kemudian putuskan apakah itu rumput atau kotoran. Sekarang lewati array dan putuskan apakah setiap ubin paling dekat dengan titik tanah atau titik rumput. Mungkin beritahu saya bagian mana yang menantang?
wolfdawn
Mengukur jarak. Bagaimanapun, saya akan mencoba dan memberi tahu Anda.
Vilda
Ok, jadi saya berhasil membuat beberapa poin. ( dropbox.com/s/dlx9uxz8kkid3kc/random_tile_map2.png ) dan seluruh kelas saya untuk menghasilkan terlihat seperti ini: dropbox.com/s/pxhn902xqrhtli4/gen.java . Tapi itu masih tidak berhasil.
Vilda
3
@ViliX tautan Anda rusak
Artur Czajka
24

Anda bisa menggunakan perlin noise, yang biasanya digunakan untuk pembuatan peta ketinggian. Perlin noise dalam game

Kemudian Anda bisa menggunakan ketinggian sebagai penasihat, seberapa tinggi kemungkinan rumput / kotoran terjadi di satu wilayah peta.

Contoh (Nilai kebisingan Perlin dari 0-256): Jika nilainya lebih dari 200 kemungkinan rumput ditempatkan adalah 80% (kotoran 20%). Jika nilainya antara 100 dan 200 kemungkinan rumput ditempatkan adalah 50% (kotoran juga 50%). Jika nilainya di bawah 100 kemungkinan rumput ditempatkan adalah 20% (kotoran 80%).

Klitz
sumber
Ok, katakanlah saya memiliki array [] [] float (probabilitas 0-1) dan saya dapat menggunakannya untuk memunculkan ubin dengan probabilitas. Tetapi bagaimana cara saya mengisi array probabilitas ini? Array adalah (katakanlah) 400x200, bagaimana cara mengisinya dengan nilai probabilitas?
Vilda
Dia menyarankan untuk mengisinya dengan perlin noise (bukan white noise seperti koin terbalik).
wolfdawn
Ya, tetapi bagaimana saya bisa mencapainya?
Vilda
Tautan yang saya poskan dapat menghapus pertanyaan ini. Pertama menghasilkan suara dan kemudian menghaluskan suara ini. Hasilnya akan menjadi array 2 dimensi yang dapat Anda gunakan untuk pembuatan tilemap selanjutnya. tautan
Klitz
Ini adalah jawaban yang sangat bagus tetapi jarang akan mendapatkan hasil yang mirip dengan yang Anda sajikan.
wolfdawn
8

masukkan deskripsi gambar di sini

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

di sini adalah versi saya dari metode automata seluler mulai dengan mengisi grid dengan acak kemudian jalankan aturan automata cullular ini beberapa kali

  • Jika sel hidup memiliki kurang dari dua tetangga yang hidup, ia mati.
  • Jika sel hidup memiliki dua atau tiga tetangga yang hidup, ia tetap hidup.
  • Jika sel hidup memiliki lebih dari tiga tetangga yang hidup, ia mati.
  • Jika sel mati memiliki tiga tetangga yang hidup, itu menjadi hidup.

dan akhirnya tampak seperti gua

indeks dapat dikonversi ke posisi x & y dan kembali dengan kode ini

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

saya baru saja mengembalikan daftar bools karena saya menggunakan daftar ini untuk banyak hal: gua, pohon, bunga, rumput, kabut, air Anda bahkan dapat menggabungkan beberapa daftar dengan cara yang berbeda di sini saya pertama-tama menghapus semua gua yang lebih kecil kemudian menyatukan dua daftar acak

masukkan deskripsi gambar di sini

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
sumber
2
Tolong jelaskan apa yang kode Anda lakukan, daripada memposting sampel tentang apa yang dilakukannya, sebuah tautan, dan kode itu sendiri. Jawaban Anda harus lengkap, sehingga meskipun tautan putus, tetap dapat digunakan.
Dana Gugatan Monica
6

Pilih satu titik di peta. Tempatkan jenis ubin yang diinginkan dengan nilai dasar seperti 40. Melacak di mana Anda menempatkan ubin yang baru Anda inginkan. Tambahkan titik awal ke daftar.

Untuk setiap titik dalam daftar ini, Anda mengunjungi semua tetangga. Meskipun Anda memiliki sisa daya yang cukup (mulai dari 40) tambahkan ubin yang diinginkan dan tambahkan ke daftar yang akan dikunjungi. Berikan daya ubin yang baru lebih sedikit, ditentukan oleh Anda. Paling mudah = penurunan acak. Setelah Anda mengunjungi ubin dari daftar, hapus. Mulai lagi dengan mengunjungi ubin yang belum dikunjungi tetapi dibuat.

Jaapjan
sumber