Menyimpan dinding yang berada di antara ubin

8

Saya menulis mesin isometrik di c ++. Saya memutuskan untuk mengambil pendekatan yang lebih realistis dan membuat dinding menempati ruang antara dua ubin, bukan satu ubin utuh, seperti yang ditunjukkan pada gambar di bawah ini (seperti di The Sims).

grafik konseptual dari apa yang ingin saya capai

Masalah saya adalah bahwa saya tidak tahu bagaimana cara menyimpan data terkait peta ubin dalam sesuatu yang bukan kisi. Dalam situasi ini, saya kira saya harus membuatnya menjadi A * friendly, sehingga akan ada node dan tepi antara ubin yang tidak dibagi oleh dinding. Berikut adalah gambar lain yang menunjukkan apa yang ingin saya capai:

Jadi inilah pertanyaannya:

Bagaimana seharusnya saya:

  • menyimpan seluruh peta, baik ubin dan dinding
  • mengoptimalkannya untuk rendering
  • menggunakannya untuk A * dan algoritma lain yang agak mudah diterapkan pada grid sederhana tetapi sekarang menggunakan dinding (tepi) untuk menentukan visibilitas, tabrakan dll?
Tchayen
sumber
Apakah Anda harus dapat melihatnya dari sudut yang berbeda? Jika demikian, apakah Anda ingin menerapkan tekstur yang berbeda pada sisi berlawanan dari dinding yang sama? Misalnya wallpaper merah muda di satu sisi, biru di sisi lain?
jzx
Saya membutuhkan kemampuan untuk memutar peta dan menggunakan berbagai jenis cat dan material di kedua sisi dinding. Sekarang saya berpikir bahwa bagian atas tembok juga harus menunjukkan bahan di dalam dinding (misalnya, beton, batu bata, kayu)
Tchayen

Jawaban:

7

Saya mulai dengan sistem koordinat - koordinat untuk lokasi grid adalah (x, y) tetapi sebagai Krom disebutkan dalam jawaban yang berbeda, untuk dinding bisa ada dua dinding untuk setiap lokasi grid. Itu mengarah ke sistem koordinat kedua, untuk tepi antara ubin . Dalam artikel ini saya menggunakan Barat dan Selatan sehingga ujungnya bisa (x, y, Barat) atau (x, y, Selatan), tetapi Anda bisa memilih dua selama Anda konsisten.

Koordinat tepi untuk kotak persegi

Kedua sistem koordinat (ubin kotak dan tepi) saling terkait. Anda ingin bertanya: empat sisi mana yang mengelilingi ubin?

Tepi yang mengelilingi ubin

Untuk merintis jalan, A * ingin tahu ubin mana yang bertetangga (B) dari ubin saat ini (A). Alih-alih mengembalikan keempat ubin yang berdekatan, Anda dapat memeriksa keempat tepi. Anda menyertakan ubin B sebagai tetangga hanya jika tidak ada dinding antara A dan B.

Alih-alih menyimpan dua dinding untuk setiap ubin, seperti yang disarankan Krom, saya biasanya menyimpan dinding dalam struktur data yang terpisah: seperangkat koordinat tepi. Ketika A * ingin tahu apakah B adalah tetangga dari A, saya akan memeriksa apakah edge itu ada di set. Jika ya, maka saya tidak mengembalikan B.

Anda mungkin tidak membutuhkan ini untuk A *, tetapi untuk hal-hal lain Anda mungkin ingin tahu untuk setiap sisi, yang menghubungkan dua ubin:

Ubin yang mengelilingi tepi

Lihat bagian “Algoritma” halaman untuk perhitungan untuk dua operasi ini.

Perhatikan juga: untuk beberapa jenis peta, Anda sebenarnya ingin menyimpan empat sisi per kotak petak, sehingga Anda dapat mendukung gerakan satu arah.

amitp
sumber
4

Di setiap ubin Anda dapat menyimpan dinding yang ada di Utara dan Timur. Dengan begitu setiap ubin hanya perlu menyimpan 2 boolean (atau int, jika Anda ingin menyimpan jenis dinding). Kekurangannya adalah bahwa ubin di sepanjang tepi Selatan dan Barat tidak dapat memiliki dinding di Selatan dan Barat kecuali jika Anda menambahkan satu baris lagi ubin tersembunyi yang akan memilikinya.

Kromster
sumber
2

Di setiap ubin, itu bisa menyimpan tetangga (atau konektivitas) yang memiliki akses. Mungkin sebagai bitmap. Dindingnya adalah tempat dua ubin yang berdekatan tidak terhubung. Ini sangat ramah dengan A *.

Pendekatan kedua adalah menyimpan konektivitas ubin sebagai enumerasi. Misalnya, ubin yang sepenuhnya terbuka adalah 0, ubin dengan dinding ke utara dan sisanya terbuka adalah 1, ubin dengan dinding di selatan dan sisanya terbuka adalah 2, dan seterusnya hingga Anda menutup semua kombinasi yang mungkin.

pengguna55564
sumber
Saya tidak berpikir komentar Anda "ramah dengan A *" benar-benar berlaku, karena mengasumsikan antarmuka ("ubin mana yang berdekatan?") Harus cocok dengan implementasi ("ubin toko tetangga"). Keduanya bisa berbeda, misalnya jika Anda menggunakan struktur data terpisah untuk dinding seperti yang disarankan amitp.
congusbongus
1

Semoga C # ini cocok untuk Anda - c ++ saya sangat berkarat:

abstract class MapFeature
{
    public void Draw();
    public bool IsWall();
}
enum Direction
{
    North, South, East, West
}
class Wall : MapFeature
{
    public bool IsWall() { return true; }
    public Tile Front, Back; // Tiles on either side of the wall, otherwise null.

    #region Implementation of MapFeature

    public void Draw()
    {
        // Wall specific drawing code...
    }

    #endregion
}
class Tile : MapFeature
{
    public bool IsWall() { return false; }

    public MapFeature North, South, East, West; // Tiles/Walls on each side, otherwise null

    public bool CanGo(Direction direction)
    {
        switch (direction)
        {
            case Direction.North:
                return !North.IsWall();
            case Direction.South:
                return !South.IsWall();
            case Direction.East:
                return !East.IsWall();
            case Direction.West:
                return !West.IsWall();
            default:
                throw new ArgumentOutOfRangeException("direction");
        }
    }

    #region Implementation of MapFeature

    public void Draw()
    {
        // Tile specific drawing code...
    }

    #endregion
}

Anda dapat menambahkan informasi khusus dinding ke kelas Dinding, informasi khusus ubin ke kelas Tile, dan selanjutnya memperbaiki kondisi dalam metode "CanGo". Misalnya, ketika dinding sebenarnya adalah pintu yang terkunci - katakanlah, kelas Pintu.

Untuk menggambar ini, Anda akan mulai dengan ubin sewenang-wenang - katakan ubin di tengah posisi kamera saat ini. Kemudian bergerak ke arah dan ke kiri kamera sesuai dengan ukuran ubin. Kemudian lakukan lintasan pertama dari node IMapFeature, gambar setiap dinding / ubin sesuai urutan.

A * akan bekerja pada struktur ini, meskipun Anda jelas membutuhkan beberapa modifikasi untuk menangani sesuatu seperti pintu yang terkunci.

Jika Anda mau, Anda juga bisa mempertahankan indeks spasial ubin, yang secara implisit akan mencakup dinding, untuk mengetahui ubin mana yang berada dalam batas kamera.

Anda masih hanya perlu memilih ubin awal dan jarak untuk melintasi berdasarkan ukuran ubin.

jzx
sumber