Membuat roguelike di Unity dari awal: generator penjara bawah tanah

gambar

Kali ini kita akan terjun ke dalam penerapan algoritma generator penjara bawah tanah. Di artikel terakhir, kami menciptakan ruang pertama, dan sekarang kami akan menghasilkan sisa tingkat bawah tanah.

Tetapi sebelum kita mulai, saya ingin memperbaiki kesalahan dari posting sebelumnya. Bahkan, dalam beberapa minggu terakhir saya telah belajar sesuatu yang baru, itulah sebabnya beberapa pekerjaan yang saya lakukan sudah ketinggalan zaman, dan saya ingin membicarakannya.

Ingat kelas Posisi yang kita buat? Faktanya, Unity sudah memiliki kelas bawaan yang melakukan fungsi yang persis sama, tetapi dengan kontrol yang sedikit lebih baik - lebih mudah untuk mendeklarasikan dan memproses. Kelas ini disebut Vector2Int. Oleh karena itu, sebelum memulai, kami akan menghapus kelas Posisi dari MapManager.cs dan mengganti setiap variabel Posisi dengan variabel Vector2Int.


Hal yang sama perlu dilakukan di beberapa tempat di skrip DungeonGenerator.cs. Sekarang mari kita lanjutkan ke sisa algoritma.

Tahap 7 - generasi kamar / aula


Kami akan mulai dengan perubahan kecil ke fungsi FirstRoom () dibuat terakhir kali. Alih-alih membuat fungsi lain untuk menghasilkan semua elemen lain dari peta dan menduplikasi banyak kode, kami hanya mengubah fungsi ini, mengubahnya menjadi GenerateFeature umum (). Oleh karena itu, ubah nama dari FirstRoom ke GenerateFeature.

Sekarang kita perlu memberikan parameter ke fungsi ini. Pertama-tama, Anda perlu tahu fungsi apa yang dihasilkannya - ruangan atau koridor. Kami hanya bisa meneruskan string yang disebut tipe. Selanjutnya, fungsi perlu mengetahui titik awal elemen, yaitu darimana dinding itu berasal (karena kita selalu membuat elemen baru dari dinding elemen yang lebih lama), dan untuk ini, lewat karena argumen Dinding sudah cukup. Akhirnya, ruang pertama yang akan dibuat memiliki karakteristik khusus, jadi kita memerlukan variabel bool opsional yang memberi tahu apakah item tersebut adalah ruang pertama. Secara default, itu salah: bool isFirst = false. Jadi judul fungsi akan berubah dari ini:


hal ini:


Baik. Langkah selanjutnya adalah mengubah cara Anda menghitung lebar dan tinggi elemen. Sementara kami menghitungnya, mendapatkan nilai acak antara nilai minimum dan tinggi dari tinggi dan lebar kamar - ini ideal untuk kamar, tetapi tidak akan berfungsi untuk koridor. Sejauh ini, kami memiliki yang berikut:


Tetapi koridor akan memiliki ukuran konstan 3 lebar atau tinggi, tergantung pada orientasinya. Karena itu, kita perlu memeriksa apa elemennya - ruangan atau koridor, dan kemudian melakukan perhitungan yang sesuai.


Begitu. kami memeriksa apakah barang itu sebuah ruangan. Jika ya, maka kita melakukan hal yang sama seperti sebelumnya
- kita mendapatkan angka acak dalam interval antara min dan max tinggi dan lebar. Tetapi sekarang di tempat lain yang sama jika Anda perlu melakukan sesuatu yang sedikit berbeda. Kita perlu memeriksa orientasi koridor. Untungnya, ketika membuat dinding, kami menyimpan informasi tentang arah mana yang diarahkan, jadi kami menggunakannya untuk mendapatkan orientasi koridor.


Tapi kami belum mendeklarasikan minCorridorLength variabel. Anda harus kembali ke deklarasi variabel dan mendeklarasikannya, tepat di atas maxCorridorLength.


Sekarang kembali ke pernyataan peralihan bersyarat kami. Apa yang kita lakukan di sini: kita mendapatkan nilai dari arah dinding, yaitu, di mana dinding itu memandang, dari mana koridor akan pergi. Arah hanya dapat memiliki empat nilai yang mungkin: Selatan, Utara, Barat dan Timur. Dalam kasus Selatan dan Utara, koridor akan memiliki lebar 3 (dua dinding dan lantai di tengah) dan tinggi variabel (panjang). Untuk Barat dan Timur, semuanya akan sebaliknya: tingginya akan sama dengan 3, dan lebarnya akan memiliki panjang variabel. Jadi mari kita lakukan.


Wow. Dan di situlah kami berakhir dengan mengukur item baru. Sekarang Anda harus memutuskan di mana harus meletakkannya. Kami menempatkan ruangan pertama di tempat acak di dalam nilai ambang relatif terhadap pusat peta.


Tetapi untuk semua elemen lain, ini tidak akan berhasil. Mereka harus mulai di sebelah titik acak di dinding dari mana elemen dihasilkan. Jadi mari kita ubah kodenya. Pertama, kita perlu memeriksa apakah elemennya adalah ruang pertama. Jika ini adalah ruang pertama, maka kita mendefinisikan titik awal dengan cara yang sama seperti sebelumnya - setengah dari lebar dan tinggi peta.


Di tempat lain, jika elemen tersebut bukan ruangan pertama, maka kita mendapatkan titik acak di dinding dari mana elemen tersebut dihasilkan. Pertama, kita perlu memeriksa apakah dinding memiliki ukuran 3 (ini berarti bahwa itu adalah titik akhir koridor), dan jika demikian, maka titik tengah akan selalu dipilih, yaitu, indeks 1 dari susunan dinding (dengan 3 elemen, array memiliki indeks 0, 1, 2). Tetapi jika ukurannya tidak sama dengan 3 (dinding bukanlah titik akhir koridor), maka kita mengambil titik acak antara titik 1 dan panjang dinding minus 2. Ini diperlukan untuk menghindari lorong yang dibuat di sudut. Misalnya, pada dinding dengan panjang 6, kami mengecualikan indeks 0 dan 5 (pertama dan terakhir), dan memilih titik acak di antara titik 1, 2, 3 dan 4.


Sekarang kita memiliki posisi titik di dinding di mana elemen baru akan dibuat. Tapi kita tidak bisa mulai membuat elemen dari sana, karena cara ini akan terhalang oleh dinding yang sudah ditempatkan. Penting juga untuk dicatat bahwa elemen mulai dihasilkan dari sudut kiri bawahnya, dan kemudian kenaikan dilakukan ke kanan dan atas, jadi kita harus mengatur posisi awal di tempat yang berbeda, tergantung pada arah di mana dinding terlihat. Selain itu, kolom pertama x dan baris pertama y akan menjadi dinding, dan jika kita memulai elemen baru tepat di sebelah titik di dinding, kita dapat membuat koridor yang berakhir di sudut ruangan, dan bukan di tempat yang cocok di dinding.

Jadi, jika dinding diarahkan ke utara, maka elemen tersebut perlu dimulai pada satu posisi utara pada sumbu y, tetapi dalam jumlah acak posisi barat pada sumbu x, dalam kisaran dari 1 hingga lebar ruangan-2. Di arah selatan, sumbu x bertindak sama, tetapi posisi awal pada sumbu y adalah posisi titik di dinding dikurangi ketinggian ruangan. Dinding barat dan timur mengikuti logika yang sama, hanya dengan sumbu terbalik.

Tetapi sebelum melakukan semua ini, kita perlu menyimpan posisi titik dinding dalam variabel Vector2Int sehingga kita dapat memanipulasinya nanti.


Bagus. Ayo lakukan itu.


Jadi, kami membuat elemen dengan ukuran dan posisi, dan langkah selanjutnya adalah menempatkan elemen di peta. Tapi pertama-tama, kita perlu mencari tahu apakah memang ada ruang di peta untuk elemen ini di posisi ini. Untuk saat ini, kami hanya memanggil fungsi CheckIfHasSpace (). Ini akan disorot dengan warna merah, karena kami belum mengimplementasikannya. Kami akan melakukan ini dengan benar setelah kami menyelesaikan apa yang perlu dilakukan di sini di fungsi GenerateFeature (). Oleh karena itu, abaikan garis bawah merah dan lanjutkan.


Pada bagian selanjutnya, dinding dibuat. Sampai kita menyentuhnya, dengan pengecualian fragmen di kedua untuk loop .


Saat menulis posting ini, saya perhatikan bahwa konstruksi if-else ini benar-benar salah. Misalnya, beberapa dinding di dalamnya akan menerima panjang 1. Ini terjadi karena ketika posisi akan ditambahkan, katakanlah, ke dinding utara, maka jika berada di sudut dengan dinding timur, itu tidak akan ditambahkan ke dinding timur, sebagaimana mestinya. Ini menyebabkan bug yang mengganggu dalam algoritma pembuatan. Mari kita hilangkan mereka.

Memperbaikinya cukup sederhana. Cukup menghapus semua yang lain sehingga posisi melewati semua konstruksi if , dan tidak berhenti pada awalnya jika itu mengembalikan true . Kemudian yang terakhir lain (salah satu yang tidak lain jika ) berubah menjadi jika, yang memeriksa bahwa posisi telah ditambahkan sebagai Wall, dan jika tidak, tambahkan sebagai Floor.


Luar biasa, kita hampir selesai di sini. Sekarang kita memiliki elemen yang sama sekali baru, dibuat di tempat yang tepat, tetapi itu sama dengan ruangan pertama kita: itu benar-benar tertutup oleh dinding. Ini berarti bahwa pemain tidak akan dapat mencapai tempat baru ini. Artinya, kita perlu mengkonversi titik di dinding (yang, seingat kita, disimpan dalam variabel tipe Vector2Int) dan titik yang sesuai di dinding elemen baru di Lantai. Tapi hanya saat elemennya bukan ruangan pertama.


Potongan kode ini memeriksa apakah item baru adalah ruang pertama. Jika tidak, itu mengubah posisi terakhir dinding ke lantai, dan kemudian memeriksa arah dinding mencari untuk memeriksa ubin elemen mana yang harus berubah menjadi lantai.

Kami telah mencapai bagian terakhir dari fungsi GenerateFeature (). Itu sudah memiliki garis yang menambahkan informasi tentang elemen yang membuat fungsi.


Di sini kita perlu mengubah sesuatu. Pertama, tipe elemen tidak selalu sama dengan Kamar. Untungnya, variabel yang diperlukan diteruskan ke fungsi sebagai parameter, yaitu tipe string. Jadi mari kita ganti "Kamar" di sini dengan tipe.


Baik. Sekarang, agar algoritme menghasilkan semua elemen permainan agar berfungsi dengan benar, kita perlu menambahkan data baru di sini. Yaitu, int yang menghitung jumlah item yang dibuat dan daftar semua item yang dibuat. Kami pergi ke tempat di mana kami mendeklarasikan semua variabel dan mendeklarasikan int dengan nama countFeatures, serta Daftar elemen dengan nama allFeatures. Daftar semua elemen harus publik, dan penghitung int bisa bersifat pribadi.


Sekarang kembali ke fungsi GenerateFeature () dan tambahkan beberapa baris ke akhir: menambah variabel countFeatures dan menambahkan elemen baru ke daftar allFeatures.


Jadi, GenerateFeature () kami hampir selesai. Nanti kita harus kembali ke sana untuk mengisi fungsi CheckIfHasSpace yang kosong, tetapi pertama-tama kita harus membuatnya. Itu yang akan kita lakukan sekarang.

Tahap 8 - periksa apakah ada tempat


Sekarang mari kita membuat fungsi baru tepat setelah fungsi GenerateFeature () selesai. Dia membutuhkan dua argumen: posisi di mana elemen dimulai, dan posisi di mana elemen itu berakhir. Anda dapat menggunakan dua variabel Vector2Int sebagai mereka. Fungsi harus mengembalikan nilai bool sehingga dapat digunakan jika memeriksa ruang.


Itu digarisbawahi dalam warna merah, karena sejauh ini belum mengembalikan apa pun. Kami akan segera memperbaikinya, tetapi untuk saat ini kami tidak akan memperhatikannya. Dalam fungsi ini, kita akan mengulang semua posisi antara awal dan akhir elemen, dan memeriksa apakah posisi saat ini di MapManager.map adalah nol atau sesuatu sudah ada di sana. Jika ada sesuatu di sana, maka kita menghentikan fungsinya dan mengembalikan false. Jika tidak, maka lanjutkan. Jika fungsi mencapai akhir loop tanpa memenuhi tempat yang diisi, maka kembalikan true.

Selain itu, sebelum memeriksa posisi untuk null, kita perlu garis untuk memeriksa apakah posisi itu di dalam peta. Karena jika tidak, kita mungkin mendapatkan kesalahan indeks array dan crash game.


Baik. Sekarang kembali ke tempat kita memasukkan fungsi ini di dalam fungsi GenerateFeature (). Kami perlu memperbaiki panggilan ini karena tidak melewati argumen yang diperlukan.

Di sini kita ingin menyisipkan pernyataan if untuk memeriksa apakah ada cukup ruang untuk elemen. Jika hasilnya salah, maka kita mengakhiri fungsi tanpa memasukkan elemen baru ke MapManager.map.


Kita perlu memberikan argumen yang diperlukan, yaitu dua variabel Vector2Int. Dengan yang pertama, semuanya sederhana, ini adalah posisi dengan koordinat x dan y dari titik awal elemen.


Yang kedua lebih sulit, tetapi tidak banyak. Ini adalah titik awal plus tinggi untuk y dan lebar untuk x, mengurangi 1 dari keduanya (karena awal sudah diperhitungkan).


Sekarang mari kita beralih ke langkah berikutnya - membuat algoritma untuk memanggil fungsi GenerateFeature ().

Tahap 9 - panggilan elemen yang dihasilkan


Kembali ke fungsi GenerateDungeon () yang dibuat di bagian artikel sebelumnya. Sekarang akan terlihat seperti ini:


Panggilan ke FirstRoom () digarisbawahi dengan warna merah karena kami mengubah nama fungsi ini. Jadi mari kita panggil generasi kamar pertama.


Kami melewati argumen yang diperlukan: "Kamar" sebagai tipe, karena ruangan pertama akan selalu menjadi Kamar, Dinding baru (), karena ruangan pertama tidak akan dibuat dari yang lain, jadi kami hanya melewati nol, dan ini cukup normal. Alih-alih Wall baru (), Anda dapat mengganti nol , ini adalah masalah preferensi pribadi. Argumen terakhir menentukan apakah elemen baru adalah ruang pertama, jadi dalam kasus kami, kami benar .

Sekarang kita sampai pada poin utama. Kami menggunakan loop for yang akan berjalan 500 kali - ya, kami akan mencoba menambahkan elemen 500 kali. Tetapi jika jumlah elemen yang dibuat (variabel countFeatures) sama dengan jumlah maksimum elemen yang ditentukan (variabel maxFeatures), maka kami menghentikan siklus ini.


Langkah pertama dalam loop ini adalah mendeklarasikan elemen dari mana elemen baru akan dibuat. Jika kita hanya membuat satu elemen (ruang pertama), maka itu akan menjadi yang asli. Jika tidak, kami secara acak memilih salah satu elemen yang sudah dibuat.


Sekarang kita akan memilih dinding elemen mana yang akan digunakan untuk membuat elemen baru.


Harap perhatikan bahwa kami belum memiliki fungsi ChoseWall () ini. Mari kita menulisnya dengan cepat. Turun ke akhir fungsi dan buat itu. Ini harus mengembalikan dinding, dan menggunakan elemen sebagai argumen, sehingga fungsinya dapat memilih dinding elemen ini.


Saya membuatnya antara fungsi CheckIfHasSpace () dan DrawMap (). Perhatikan bahwa jika Anda bekerja di Visual Studio, yang diinstal dengan Unity, Anda dapat menggunakan bidang - / + di sebelah kiri untuk menutup / memperluas bagian kode untuk menyederhanakan pekerjaan.

Dalam fungsi ini kita akan menemukan dinding dari mana elemen belum dibuat. Kadang-kadang kita akan mendapatkan elemen dengan satu atau lebih dinding yang elemen lainnya sudah terpasang, jadi kita perlu memeriksa lagi dan lagi apakah ada dinding acak yang bebas. Untuk melakukan ini, kami menggunakan loop for diulang sepuluh kali - jika setelah sepuluh kali ini dinding bebas tidak ditemukan, maka fungsi mengembalikan nol.


Sekarang kembali ke fungsi GenerateDungeon () dan meneruskan elemen asli sebagai parameter ke fungsi ChoseWall ().


Garis if (wall == null) continue;berarti bahwa jika fungsi pencarian dinding mengembalikan false, maka elemen asli tidak dapat menghasilkan elemen baru, oleh karena itu fungsi akan melanjutkan siklus, yaitu, ia tidak dapat membuat elemen baru dan melanjutkan ke iterasi siklus berikutnya.

Sekarang kita perlu memilih jenis untuk item selanjutnya. Jika elemen sumbernya adalah sebuah ruangan, maka yang berikutnya haruslah koridor (kita tidak ingin ruangan mengarah langsung ke ruangan lain tanpa koridor di antara mereka). Tetapi jika ini adalah koridor, maka kita perlu membuat kemungkinan bahwa koridor atau ruangan lain akan menjadi yang berikutnya.


Baik. Sekarang kita hanya perlu memanggil fungsi GenerateFeature (), melewatinya dinding dan ketik sebagai parameter.


Terakhir, buka inspektur Persatuan, pilih objek GameManager dan ubah nilainya sebagai berikut:


Jika sekarang Anda mengklik tombol putar, maka Anda sudah akan melihat hasilnya!


Seperti yang saya katakan, ini bukan penjara bawah tanah terbaik. Kami punya banyak jalan buntu. Tapi itu berfungsi penuh, dan itu menjamin bahwa Anda tidak akan memiliki ruangan yang tidak terhubung ke yang lain.

Saya harap Anda menikmatinya! Di posting berikutnya, kita akan membuat pemain yang akan bergerak melalui ruang bawah tanah, dan kemudian kita akan mengubah peta dari ASCII menjadi sprite.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Post3 : MonoBehaviour {
    public int mapWidth;
    public int mapHeight;

    public int widthMinRoom;
    public int widthMaxRoom;
    public int heightMinRoom;
    public int heightMaxRoom;

    public int minCorridorLength;
    public int maxCorridorLength;
    public int maxFeatures;
    int countFeatures;

    public bool isASCII;

    public List<Feature> allFeatures;

    public void InitializeDungeon() {
        MapManager.map = new Tile[mapWidth, mapHeight];
    }

    public void GenerateDungeon() {
        GenerateFeature("Room", new Wall(), true);

        for (int i = 0; i < 500; i++) {
            Feature originFeature;

            if (allFeatures.Count == 1) {
                originFeature = allFeatures[0];
            }
            else {
                originFeature = allFeatures[Random.Range(0, allFeatures.Count - 1)];
            }

            Wall wall = ChoseWall(originFeature);
            if (wall == null) continue;

            string type;

            if (originFeature.type == "Room") {
                type = "Corridor";
            }
            else {
                if (Random.Range(0, 100) < 90) {
                    type = "Room";
                }
                else {
                    type = "Corridor";
                }
            }

            GenerateFeature(type, wall);

            if (countFeatures >= maxFeatures) break;
        }

        DrawMap(isASCII);
    }

    void GenerateFeature(string type, Wall wall, bool isFirst = false) {
        Feature room = new Feature();
        room.positions = new List<Vector2Int>();

        int roomWidth = 0;
        int roomHeight = 0;

        if (type == "Room") {
            roomWidth = Random.Range(widthMinRoom, widthMaxRoom);
            roomHeight = Random.Range(heightMinRoom, heightMaxRoom);
        }
        else {
            switch (wall.direction) {
                case "South":
                    roomWidth = 3;
                    roomHeight = Random.Range(minCorridorLength, maxCorridorLength);
                    break;
                case "North":
                    roomWidth = 3;
                    roomHeight = Random.Range(minCorridorLength, maxCorridorLength);
                    break;
                case "West":
                    roomWidth = Random.Range(minCorridorLength, maxCorridorLength);
                    roomHeight = 3;
                    break;
                case "East":
                    roomWidth = Random.Range(minCorridorLength, maxCorridorLength);
                    roomHeight = 3;
                    break;

            }
        }

        int xStartingPoint;
        int yStartingPoint;

        if (isFirst) {
            xStartingPoint = mapWidth / 2;
            yStartingPoint = mapHeight / 2;
        }
        else {
            int id;
            if (wall.positions.Count == 3) id = 1;
            else id = Random.Range(1, wall.positions.Count - 2);

            xStartingPoint = wall.positions[id].x;
            yStartingPoint = wall.positions[id].y;
        }

        Vector2Int lastWallPosition = new Vector2Int(xStartingPoint, yStartingPoint);

        if (isFirst) {
            xStartingPoint -= Random.Range(1, roomWidth);
            yStartingPoint -= Random.Range(1, roomHeight);
        }
        else {
            switch (wall.direction) {
                case "South":
                    if (type == "Room") xStartingPoint -= Random.Range(1, roomWidth - 2);
                    else xStartingPoint--;
                    yStartingPoint -= Random.Range(1, roomHeight - 2);
                    break;
                case "North":
                    if (type == "Room") xStartingPoint -= Random.Range(1, roomWidth - 2);
                    else xStartingPoint--;
                    yStartingPoint ++;
                    break;
                case "West":
                    xStartingPoint -= roomWidth;
                    if (type == "Room") yStartingPoint -= Random.Range(1, roomHeight - 2);
                    else yStartingPoint--;
                    break;
                case "East":
                    xStartingPoint++;
                    if (type == "Room") yStartingPoint -= Random.Range(1, roomHeight - 2);
                    else yStartingPoint--;
                    break;
            }
        }

         if (!CheckIfHasSpace(new Vector2Int(xStartingPoint, yStartingPoint), new Vector2Int(xStartingPoint + roomWidth - 1, yStartingPoint + roomHeight - 1))) {
            return;
        }

        room.walls = new Wall[4];

        for (int i = 0; i < room.walls.Length; i++) {
            room.walls[i] = new Wall();
            room.walls[i].positions = new List<Vector2Int>();
            room.walls[i].length = 0;

            switch (i) {
                case 0:
                    room.walls[i].direction = "South";
                    break;
                case 1:
                    room.walls[i].direction = "North";
                    break;
                case 2:
                    room.walls[i].direction = "West";
                    break;
                case 3:
                    room.walls[i].direction = "East";
                    break;
            }
        }

        for (int y = 0; y < roomHeight; y++) {
            for (int x = 0; x < roomWidth; x++) {
                Vector2Int position = new Vector2Int();
                position.x = xStartingPoint + x;
                position.y = yStartingPoint + y;

                room.positions.Add(position);

                MapManager.map[position.x, position.y] = new Tile();
                MapManager.map[position.x, position.y].xPosition = position.x;
                MapManager.map[position.x, position.y].yPosition = position.y;

                if (y == 0) {
                    room.walls[0].positions.Add(position);
                    room.walls[0].length++;
                    MapManager.map[position.x, position.y].type = "Wall";
                }
                if (y == (roomHeight - 1)) {
                    room.walls[1].positions.Add(position);
                    room.walls[1].length++;
                    MapManager.map[position.x, position.y].type = "Wall";
                }
                if (x == 0) {
                    room.walls[2].positions.Add(position);
                    room.walls[2].length++;
                    MapManager.map[position.x, position.y].type = "Wall";
                }
                if (x == (roomWidth - 1)) {
                    room.walls[3].positions.Add(position);
                    room.walls[3].length++;
                    MapManager.map[position.x, position.y].type = "Wall";
                }
                if (MapManager.map[position.x, position.y].type != "Wall") {
                    MapManager.map[position.x, position.y].type = "Floor";
                }
            }
        }

        if (!isFirst) {
            MapManager.map[lastWallPosition.x, lastWallPosition.y].type = "Floor";
            switch (wall.direction) {
                case "South":
                    MapManager.map[lastWallPosition.x, lastWallPosition.y - 1].type = "Floor";
                    break;
                case "North":
                    MapManager.map[lastWallPosition.x, lastWallPosition.y + 1].type = "Floor";
                    break;
                case "West":
                    MapManager.map[lastWallPosition.x - 1, lastWallPosition.y].type = "Floor";
                    break;
                case "East":
                    MapManager.map[lastWallPosition.x + 1, lastWallPosition.y].type = "Floor";
                    break;
            }
        }

        room.width = roomWidth;
        room.height = roomHeight;
        room.type = type;
        allFeatures.Add(room);
        countFeatures++;
    }

    bool CheckIfHasSpace(Vector2Int start, Vector2Int end) {
        for (int y = start.y; y <= end.y; y++) {
            for (int x = start.x; x <= end.x; x++) {
                if (x < 0 || y < 0 || x >= mapWidth || y >= mapHeight) return false;
                if (MapManager.map != null) return false;
            }
        }

        return true;
    }

    Wall ChoseWall(Feature feature) {
        for (int i = 0; i < 10; i++) {
            int id = Random.Range(0, 100) / 25;
            if (!feature.walls[id].hasFeature) {
                return feature.walls[id];
            }
        }
        return null;
    }

    void DrawMap(bool isASCII) {
        if (isASCII) {
            Text screen = GameObject.Find("ASCIITest").GetComponent<Text>();

            string asciiMap = "";

            for (int y = (mapHeight - 1); y >= 0; y--) {
                for (int x = 0; x < mapWidth; x++) {
                    if (MapManager.map[x, y] != null) {
                        switch (MapManager.map[x, y].type) {
                            case "Wall":
                                asciiMap += "#";
                                break;
                            case "Floor":
                                asciiMap += ".";
                                break;
                        }
                    }
                    else {
                        asciiMap += " ";
                    }

                    if (x == (mapWidth - 1)) {
                        asciiMap += "\n";
                    }
                }
            }

            screen.text = asciiMap;
        }
    }
}

All Articles