Format file yang dapat diperpanjang khusus untuk peta ubin 2d

8

Saya telah mengimplementasikan banyak logika permainan saya saat ini, tetapi masih membuat peta saya dengan for-loop yang tidak menyenangkan sambil berjalan agar dapat bekerja dengan sesuatu. Sekarang saya ingin melanjutkan dan melakukan penelitian tentang cara (un) membuat serialisasi data ini. (Saya tidak mencari editor peta - Saya berbicara tentang file peta itu sendiri)

Untuk saat ini saya mencari saran dan sumber daya, cara menerapkan format file khusus untuk peta saya yang harus menyediakan fungsionalitas berikut (berdasarkan metode MoSCoW):

  • Harus punya
    • Ekstensibilitas dan kompatibilitas ke belakang
    • Penanganan lapisan yang berbeda
    • Metadata apakah ubin solid atau dapat dilewati
    • Serialisasi khusus entitas / pemicu dengan properti / metadata terkait
  • Bisa
    • Beberapa jenis tileset dimasukkan untuk mencegah tersebarnya file / tileset

Saya mengembangkan dengan C ++ (menggunakan SDL) dan hanya menargetkan Windows. Bantuan, tips, saran, ... yang bermanfaat apa pun akan dihargai!


Hasil pembahasan di bawah ini

Saya telah merancang format file peta saya beberapa jam terakhir dan muncul dengan kerangka (hanya berisi lapisan untuk saat ini - saya akan menyerahkan sisanya kepada semua orang yang mendesain formatnya sendiri) yang ingin saya bagikan dengan semua orang yang tertarik - jika Anda memiliki niat yang sama dengan Anda bisa mendapatkan semacam inspirasi. Tangkapan layar ukuran penuh dapat diunduh di Imgur .

Format File Peta Kore

Christian Ivicevic
sumber
2
XML adalah format hebat untuk memulai, dengan ekstensi, kompatibel dengan belakang, Anda dapat menambahkan informasi dan metadata yang Anda inginkan. Ada banyak dukungan untuk membaca, menulis, dan mengedit XML. Dukungan untuk serialisasi ke dan dari XML ada untuk hampir setiap bahasa. The downside adalah bahwa itu cukup tidak efisien ruang, ini dapat ditingkatkan dengan menggunakan versi biner atau menggunakan kompresi zip pada file itu sendiri. Tidak kurang, ini merupakan titik awal yang baik untuk membuat format file Anda sendiri
Daniel Carlsson
@DanielCarlsson: Seperti disebutkan dalam jawaban yang diterima di bawah, saya akan tetap pada XML pada awalnya untuk memiliki sesuatu yang berguna untuk debug dan bekerja dengan. Nanti saya akan beralih ke format biner kustom. Meskipun demikian upvoted karena XML mengagumkan dalam kombinasi dengan libs RapidXML di C ++.
Christian Ivicevic

Jawaban:

6

Secara pribadi, saya lebih menyukai format biner dengan bagian (seperti Windows PE, hanya lebih sederhana). Mereka juga lebih mudah diurai (tapi itu hanya pendapat saya .... Saya sudah bekerja dengan cukup XML untuk memberi saya sakit kepala, memeriksa apakah getElementByName telah mengembalikan nilai tunggal atau daftar nilai ... ugh). Jadi, jika saya adalah Anda, saya akan membuatnya menjadi seperti ini:

".MMF\0" // magic value at the start, null-terminated string. stands for My Map Format :)
    char header_length // useful when parsing. char is a byte, of course, an unsigned one
    char version // version of the map file. (you don't really need ints here, because you probably won't be needing more than 255 versions for example, but you can also use them)
    char* map_name // null terminated string describing the name of the level/map
    char* author_name // if you are going to have a map editor for the general public, it would be nice to credit the person who made the map
    int width // it's probably wise to plan ahead and expect an int here when you're parsing the file
    int height
    ".layer\0" // we begin another subsection
        char header_length
        char type // type of the layer. for example, you can put 1 there if you want this to be a layer describing different tiles/block in a Terraria like game
        ".data\0" // yet another subsection. this will hold the data for the tiles
                  // in a hypothetical terraria 2d game, you would lay down tiles from
                  // the top-right corner (0,0) and then begin writing row after row
                  // write(1,0); write(2,0); write(3,0); ... then write(0,1); write(1,1);
                  // write(2,1); write(3,1); and so on..
            char t1 // tile at (0,0). for example, value 0 is empty, or passable tile
            char t2 // tile at (1,0). this might be a dirt block - value 1
            char t3 // tile at (2,0). a rock, perhaps? value 3
            (...)
            char tn // tile at (width-1, height-1) or the bottom-left tile
    ".layer\0" // another layer.
        char header_length    
        char type // let this on be of value 2, and let it describe portals.
                  // putting portals in a game makes it instantly 20% cooler
        ".data\0"
            char t1  // 0, no portal here at tile (0,0)
            char t2  // still nothing
            char t3  // nope, try again
            (...)
            char t47 // at some location, you made a red portal. let's put 1 here so we can read it in our engine
            (...)
            char t86 // looke here, another 1! you can exit here from location corresponding to t47
            (...)
            char t99 // value 2. hm, a green portal?
            (...)
            char tn  // bottom-left tile, at (width-1, height-1)
    ".layer\0" // another layer
        char header_length
        char type // value 3, player&enemies spawn points
        char something // you don't have to have header len fixed. you can add stuff later
                       // and because you were smart enough to put header length 
                       // older versions can know where the stuff of interest lays
                       // i.e. version one of the parser can read only the type of layer
                       // in version two, you add more meta-data  and the old parser
                       // just skips it, and goes straight to the .data section
            ".data\0"
                char t1  // zero
                char t2  // zero
                char t3  // zero
                (...)
                char t42 // a 1 - maybe the player spawn point. 5 tiles to the right
                         // there's a red portal
                (...)
                char t77 // a 2: some enemy spawn point
                (...)
                char tn  // last tile

,

Keuntungan:

  • Terlihat keren.
  • Membuat Anda berpikir Anda tahu sesuatu tentang pemrograman, melakukan hal-hal dengan cara lama.
  • Anda dapat menulis level Anda secara manual dalam hex editor:
  • Secara umum lebih cepat daripada INI dan XML, baik dari perspektif menulis dan membaca
  • Ini adalah aliran data byte yang panjang, sungguh. Tidak perlu menghabiskan waktu untuk membuatnya terlihat cantik, indentasi bijaksana (seperti apa yang ingin Anda lakukan dengan XML).
  • Sangat mudah untuk menambahkan hal-hal di header. Jika sepotong data ada di bagian bawah header, versi parser lama dapat diinstruksikan untuk menghindarinya dan melompat ke bagian file yang mereka pahami.

Kekurangan:

  • Anda harus merawat penempatan data dengan baik.
    • Bidang data harus dipesan.
    • Anda harus tahu jenisnya di parser - seperti saya katakan, itu hanya aliran byte yang panjang.
    • Memindahkan data berdasarkan satu lokasi (misalnya, Anda lupa menulis jenis layer; parser mengharapkan byte di sana dan ia menemukan nilai '.' - itu tidak baik) mengacaukan seluruh array data dari titik itu dan seterusnya.
  • Sulit untuk melompat langsung ke - tidak ada API, tidak ada fungsi seperti getLayerWidth () - Anda harus mengimplementasikan semua itu sendiri.
  • Ada potensi banyak ruang terbuang. Ambil layer ketiga sebagai contoh. Itu pasti akan dikemas dengan banyak nol. Ini bisa dielakkan jika Anda menggunakan semacam kompresi. Tapi sekali lagi, itu mengacaukan hal-hal tingkat rendah lagi ...

Tetapi hal terbaik dalam pendekatan ini menurut saya adalah - Anda bisa melakukan semuanya sendiri. Banyak sekali coba-coba, tetapi pada akhirnya, Anda akhirnya banyak belajar.

Vladimir Mitrovic
sumber
Anda hanya menyimpan ... katakanlah ID untuk ubin, tetapi bagaimana dengan metadata mereka? Bagaimana saya harus menyimpan apakah ubin lumayan atau tidak? Bagaimana dengan pemicu dan bahkan panggilan skrip / kode / fungsi yang dikaitkan dengannya?
Christian Ivicevic
@ChristianIvicevic: Ada sejumlah cara untuk melakukan itu:
Vladimir Mitrovic
@ChristianIvicevic: 1. Kemas metadata dalam satu byte. Anda hanya memiliki delapan kemungkinan ubin? Hebat, simpan sisanya lima bit untuk sesuatu yang lain. Dalam kasus Anda, Anda bertanya tentang ubin yang lumayan. Anda dapat meminta bit pertama (bit ke-0) menyimpan informasi itu. Sedikit manipulasi sedikit :) akan melakukan trik ( codepad.org/Q6zfTV44 ). 2. Gunakan layer untuk itu. Memiliki lapisan dengan jenis yang unik dan membuatnya diisi dengan nol dan satu, satu untuk lumayan dan nol untuk ubin dilewati. 3. Gunakan lebih dari satu byte per ubin. Satu byte untuk nilai, yang lain untuk metadata.
Vladimir Mitrovic
@ChristianIvicevic: Adapun skrip, saya kira Anda telah mengimplementasikan parser skrip yang berfungsi. Anda dapat menambahkan bagian ke file peta Anda dan meletakkannya di sana: pastebin.com/yUKncz19 ATAU Anda dapat menempatkannya di file terpisah, dan menyimpan nama file di bagian ".scripts". Anda kemudian menambahkan bagian ".layer" yang menggambarkan ubin mana yang mem-skrip script: pastebin.com/BgPCR2xQ
Vladimir Mitrovic
Cukup banyak contoh - TOP! Sekarang saya akan tetap berpegang pada XML untuk membuat beberapa level dasar untuk di-debug / bekerja dengan dan akhirnya saya akan beralih ke format biner seperti yang Anda gambarkan untuk mapfile mentah yang menyimpan data dan kemas file ini dengan kedua tileset (png dll.) Dan file script ke dalam zip untuk memiliki segalanya terstruktur dengan cara yang lebih baik. Terserah menulis kode, yang sebenarnya membaca data biner seperti itu - tapi itu adalah topik lain dalam cerita saya ... terima kasih!
Christian Ivicevic
9

Anda dapat menggunakan format peta TMX yang digunakan oleh editor Tiled (serta beberapa editor peta lainnya).

Bahkan jika Anda tidak menggunakan Ubin sendiri, format TMX mendukung semua fungsi yang Anda sebutkan dan memiliki beberapa pemuat / pengurai yang ada untuk berbagai bahasa. Ini juga sangat mudah untuk memahami format dan memperluasnya untuk gim Anda sendiri.

Firas Assaad
sumber
Saya akan memiliki konsep XML saya saat ini berdasarkan sedikit pada format peta TMX dan kemudian membaca semua file dengan RapidXML - nanti saya akan beralih ke beberapa format file biner kustom.
Christian Ivicevic