Saya sedang mengembangkan platformer 2D dengan beberapa teman uni. Kami telah mendasarkannya pada XNA Platformer Starter Kit yang menggunakan file .txt untuk menyimpan peta ubin. Meskipun ini sederhana, itu tidak memberi kita kontrol dan fleksibilitas yang cukup dengan desain level. Beberapa contoh: untuk beberapa lapisan konten diperlukan beberapa file, setiap objek diperbaiki ke grid, tidak memungkinkan untuk rotasi objek, jumlah karakter yang terbatas, dll. Jadi saya sedang melakukan penelitian tentang cara menyimpan data level dan file peta.
Ini hanya menyangkut penyimpanan sistem file peta ubin, bukan struktur data yang akan digunakan oleh game saat sedang berjalan. Peta petak dimuat ke dalam array 2D, jadi pertanyaan ini adalah tentang sumber dari mana untuk mengisi array.
Alasan DB: Dari sudut pandang saya, saya melihat redundansi data yang lebih sedikit menggunakan database untuk menyimpan data ubin. Ubin dalam posisi x, y yang sama dengan karakteristik yang sama dapat digunakan kembali dari level ke level. Sepertinya cukup sederhana untuk menulis metode untuk mengambil semua ubin yang digunakan pada level tertentu dari database.
Alasan JSON / XML: File yang dapat diedit secara visual, perubahan dapat dilacak melalui SVN jauh lebih mudah. Tetapi ada konten berulang.
Apakah ada kekurangan (waktu buka, waktu akses, memori dll) dibandingkan dengan yang lain? Dan apa yang biasa digunakan di industri?
Saat ini file terlihat seperti ini:
....................
....................
....................
....................
....................
....................
....................
.........GGG........
.........###........
....................
....GGG.......GGG...
....###.......###...
....................
.1................X.
####################
1 - Titik awal pemain, X - Level Keluar,. - Ruang kosong, # - Platform, G - Gem
Jawaban:
Jadi membaca pertanyaan Anda yang diperbarui, tampaknya Anda paling khawatir tentang "data yang berlebihan" pada disk, dengan beberapa kekhawatiran sekunder tentang waktu muat dan apa yang digunakan industri.
Pertama, mengapa Anda khawatir tentang data yang berlebihan? Bahkan untuk format kembung seperti XML, akan sangat sepele untuk menerapkan kompresi dan menurunkan ukuran level Anda. Anda lebih cenderung menghabiskan ruang dengan tekstur atau suara daripada data level Anda.
Kedua, format biner lebih dari mungkin akan memuat lebih cepat daripada yang berbasis teks yang Anda harus parsing. Ragu jadi jika Anda hanya bisa menjatuhkannya di memori dan memiliki struktur data Anda di sana. Namun, ada beberapa kelemahannya. Untuk satu, file biner hampir tidak mungkin untuk debug (terutama untuk orang-orang pembuat konten). Anda tidak dapat membedakan atau membuat versinya. Tetapi mereka akan lebih kecil, dan memuat lebih cepat.
Apa yang dilakukan beberapa mesin (dan apa yang saya anggap sebagai situasi ideal) adalah menerapkan dua jalur pemuatan. Untuk pengembangan, Anda menggunakan semacam format teks. Tidak masalah format spesifik apa yang Anda gunakan, selama Anda menggunakan pustaka yang solid. Untuk rilis, Anda beralih ke memuat versi biner (lebih kecil, memuat lebih cepat, mungkin dilucuti dari entitas debug). Alat Anda untuk mengedit level memuntahkan keduanya. Ini lebih banyak pekerjaan daripada hanya satu format file, tetapi Anda bisa mendapatkan yang terbaik dari kedua dunia.
Semua yang dikatakan, saya pikir Anda sedikit melompat pistol.
Langkah pertama untuk masalah ini selalu menggambarkan masalah yang Anda hadapi secara menyeluruh. Jika Anda tahu data apa yang Anda butuhkan, maka Anda tahu data apa yang perlu Anda simpan. Dari sana itu pertanyaan optimasi yang dapat diuji.
Jika Anda memiliki use case untuk diuji, maka Anda dapat menguji beberapa metode berbeda untuk menyimpan / memuat data untuk mengukur apa pun yang Anda anggap penting (waktu pemuatan, penggunaan memori, ukuran disk, dll.). Tanpa mengetahui semua itu, sulit untuk lebih spesifik.
sumber
Rekomendasi saya adalah menggunakan format file biner khusus. Dengan permainan saya, saya hanya memiliki
SaveMap
metode yang melewati dan menyimpan setiap bidang menggunakan aBinaryWriter
. Ini juga memungkinkan Anda memilih untuk mengompresnya jika Anda mau dan memberi Anda kontrol lebih besar atas ukuran file. yaitu Hematshort
daripadaint
jika Anda tahu itu tidak akan lebih besar dari 32767. Dalam lingkaran besar, menyimpan sesuatu sebagaishort
gantiint
dapat berarti ukuran file yang jauh lebih kecil.Juga, jika Anda menggunakan rute ini, saya sarankan variabel pertama Anda dalam file menjadi nomor versi.
Pertimbangkan misalnya, kelas peta (sangat disederhanakan):
Sekarang, katakanlah Anda ingin menambahkan properti baru ke peta Anda, mengatakan
List
dariPlatform
objek. Saya memilih ini karena sedikit lebih terlibat.Pertama-tama, Anda menambahkan
MapVersion
dan menambahkanList
:Kemudian, perbarui metode penyimpanan:
Lalu, dan di sinilah Anda benar-benar melihat manfaatnya, perbarui metode memuat:
Seperti yang Anda lihat,
LoadMaps
metode ini tidak hanya dapat memuat versi terbaru dari peta, tetapi juga versi yang lebih lama! Saat memuat peta yang lebih lama, Anda memiliki kontrol atas nilai default yang digunakannya.sumber
Cerita pendek
Alternatif rapi untuk masalah ini adalah menyimpan level Anda dalam bitmap, satu piksel per ubin. Menggunakan RGBA ini dengan mudah memungkinkan empat dimensi yang berbeda (lapisan, id, rotasi, warna, dll.) Disimpan pada satu gambar.
Cerita panjang
Pertanyaan ini mengingatkan saya pada saat Notch menyiarkan entri Ludum Dare-nya beberapa bulan yang lalu, dan saya ingin berbagi jika Anda tidak tahu apa yang dia lakukan. Saya pikir itu sangat menarik.
Pada dasarnya, dia menggunakan bitmap untuk menyimpan levelnya. Setiap piksel dalam bitmap berhubungan dengan satu "ubin" di dunia (bukan benar-benar ubin dalam kasusnya karena itu adalah permainan raycast tetapi cukup dekat). Contoh salah satu levelnya:
Jadi jika Anda menggunakan RGBA (8-bit per saluran), Anda dapat menggunakan masing-masing saluran sebagai lapisan yang berbeda, dan hingga 256 jenis ubin untuk masing-masingnya. Apakah itu cukup? Atau misalnya, salah satu saluran dapat menahan rotasi ubin seperti yang Anda sebutkan. Selain itu, membuat editor level untuk bekerja dengan format ini juga harus cukup sepele.
Dan yang terbaik dari semuanya, Anda bahkan tidak memerlukan pengolah konten khusus karena Anda bisa memuatnya ke XNA seperti Texture2D lainnya dan membaca pikselnya kembali dalam satu lingkaran.
IIRC ia menggunakan titik merah murni pada peta untuk memberi sinyal musuh, dan tergantung pada nilai saluran alpha untuk piksel itu akan menentukan jenis musuh (misalnya nilai alpha 255 mungkin kelelawar sementara 254 akan menjadi zombie atau yang lainnya).
Gagasan lain adalah dengan membagi objek permainan Anda ke dalam objek yang diperbaiki dalam kotak, dan yang dapat bergerak "dengan halus" di antara ubin. Simpan ubin tetap dalam bitmap, dan objek dinamis dalam daftar.
Bahkan mungkin ada cara untuk menggandakan lebih banyak informasi ke dalam 4 saluran tersebut. Jika seseorang memiliki ide tentang ini, beri tahu saya. :)
sumber
Anda mungkin bisa lolos dengan hampir semua hal. Sayangnya komputer modern begitu cepat sehingga jumlah data yang relatif kecil ini mungkin tidak benar-benar membuat perbedaan waktu yang nyata, bahkan jika disimpan dalam format data yang kembung dan tidak dibangun dengan baik sehingga membutuhkan banyak sekali pemrosesan untuk dibaca.
Jika Anda ingin melakukan hal yang "benar", Anda membuat format biner seperti yang disarankan Drackir, tetapi jika Anda membuat pilihan lain karena alasan konyol, itu mungkin tidak akan kembali dan menggigit Anda (setidaknya tidak berdasarkan kinerja).
sumber
Lihat pertanyaan ini: 'Binary XML' untuk data game? Saya juga akan memilih JSON atau YAML atau bahkan XML, tetapi itu memiliki overhead yang cukup banyak. Adapun SQLite, saya tidak akan pernah menggunakannya untuk menyimpan level. Database relasional berguna jika Anda berharap untuk menyimpan banyak data yang terkait (misalnya memiliki tautan relasional / kunci asing) dan jika Anda berharap untuk mengajukan sejumlah besar pertanyaan yang berbeda, menyimpan tilemaps sepertinya tidak melakukan semacam ini. hal-hal dan akan menambah kompleksitas yang tidak perlu.
sumber
Masalah mendasar dengan pertanyaan ini adalah bahwa ia mengonfigurasi dua konsep yang tidak ada hubungannya dengan satu sama lain:
Anda dapat menyimpan file Anda sebagai teks biasa dalam format sewenang-wenang, JSON, skrip Lua, XML, format biner sewenang-wenang, dll. Dan tidak satu pun dari itu yang mengharuskan representasi dalam memori Anda dari data tersebut mengambil bentuk apa pun.
Ini adalah tugas kode pemuatan level Anda untuk mengubah paradigma penyimpanan file menjadi representasi di dalam memori Anda. Misalnya, Anda berkata, "Saya melihat redundansi data yang lebih sedikit menggunakan database untuk menyimpan data ubin." Jika Anda ingin redundansi lebih sedikit, itu adalah sesuatu yang harus dilihat oleh kode pemuatan level Anda. Itu adalah sesuatu yang harus bisa ditangani oleh representasi di memori Anda.
Ini bukan sesuatu yang perlu diperhatikan oleh format file Anda. Dan inilah alasannya: file-file itu harus berasal dari suatu tempat.
Entah Anda akan menulis ini dengan tangan, atau Anda akan menggunakan semacam alat yang membuat dan mengedit data level. Jika Anda menulisnya dengan tangan, maka hal terpenting yang Anda butuhkan adalah format yang mudah dibaca dan dimodifikasi. Redundansi data bukan sesuatu yang perlu dipertimbangkan oleh format Anda, karena Anda akan menghabiskan sebagian besar waktu Anda mengedit file. Apakah Anda ingin benar-benar harus menggunakan mekanisme apa pun yang Anda buat secara manual untuk menyediakan redundansi data? Bukankah lebih baik menggunakan waktu Anda untuk membuat loader level Anda menanganinya?
Jika Anda memiliki alat yang membuatnya, maka format yang sebenarnya hanya penting (paling-paling) demi keterbacaan. Anda dapat meletakkan apa pun di file ini. Jika Anda ingin menghilangkan data yang berlebihan dalam file, cukup desain format yang dapat melakukannya, dan buat alat Anda menggunakan kemampuan itu dengan benar. Format tilemap Anda dapat mencakup kompresi RLE (run-length encoding), kompresi duplikasi, teknik kompresi apa pun yang Anda inginkan, karena ini adalah format tilemap Anda .
Masalah terpecahkan.
Relational Databases (RDB) ada untuk menyelesaikan masalah melakukan pencarian kompleks pada dataset besar yang berisi banyak bidang data. Satu-satunya jenis pencarian yang pernah Anda lakukan di peta ubin adalah "dapatkan ubin di posisi X, Y". Setiap array dapat mengatasinya. Menggunakan database relasional untuk menyimpan dan memelihara data tilemap akan sangat berlebihan, dan tidak benar-benar bernilai apa pun.
Bahkan jika Anda membangun beberapa kompresi ke dalam representasi di dalam memori Anda, Anda masih dapat mengalahkan RDB dengan mudah dalam hal kinerja dan jejak memori. Ya, Anda harus benar-benar menerapkan kompresi itu. Tetapi jika ukuran data dalam memori sedemikian rupa sehingga Anda akan mempertimbangkan RDB, maka Anda mungkin ingin benar-benar menerapkan jenis kompresi tertentu. Anda akan lebih cepat daripada RDB dan lebih rendah di memori pada saat yang sama.
sumber
Untuk data yang sangat sederhana, saya mungkin hanya akan pergi rute XML, jika Anda sudah terbiasa dengan pemuatan dan penguraian XML.
sumber