Saya memiliki platformer 2D yang saat ini dapat menangani potongan dengan 100 kali 100 ubin, dengan koordinat potongan disimpan sepanjang, jadi ini adalah satu-satunya batas peta (maxlong * maxlong). Semua posisi entitas dll, semuanya relevan dan tidak ada batasan di sana.
Masalah yang saya alami adalah bagaimana menyimpan dan mengakses potongan-potongan ini tanpa memiliki ribuan file. Adakah ide untuk format arsip biaya HD yang cepat & murah yang tidak perlu membuka semuanya sekaligus?
long
yang 64-bit (jadi maxlong adalahInt64.MaxValue
).Jawaban:
Buat format peta khusus untuk gim Anda. Ini lebih mudah dari yang Anda kira. Cukup gunakan kelas BinaryWriter. Pertama, tulis tajuknya dalam beberapa int atau uint. Informasi untuk dimasukkan dalam header:
dan juga (dan inilah bagian penting kinerja
Dengan metode di atas, Anda dapat (dan seharusnya) membuat indeks isi file Anda, berisi semacam deskripsi (nama yang ditentukan pengguna untuk wilayah / chunk, atau hanya koordinat) dan sebagai nilai kedua posisi dalam file.
Kemudian, ketika Anda ingin memuat potongan tertentu, Anda hanya perlu mencari di dalam indeks. Ketika Anda mendapat posisi, atur saja fileStream.Position = PositionOfChunkFromIndex dan Anda dapat memuatnya.
Ini semua tentang desain format file dengan header yang menjelaskan konten file paling efisien.
Simpan saja file dengan ekstensi khusus yang Anda buat dan mulai lagi.
BONUS: Tambahkan kompresi BZip2 ke wilayah tertentu dari file / seluruh konten (bukan header !!), sehingga Anda dapat membongkar potongan tertentu dari file, untuk jejak memori yang sangat kecil.
sumber
Saya mengalami masalah yang sama dan memutuskan untuk membuat struktur sendiri untuk menangani data. Ini didasarkan longgar pada quadtree, tetapi memiliki ekspansi yang tak terbatas (setidaknya sebesar Int) di semua arah. Itu dirancang untuk menangani data berbasis grid yang diperluas dari titik pusat, seperti Minecraft sekarang. Ini adalah ruang yang efisien dalam memori, dan sangat cepat.
Anda dapat menentukan besaran minimum untuk setiap node (besarnya 7 akan menjadi 128x128) dan sekali setiap node memiliki persentase tertentu dari subnode yang dihuni, ia secara otomatis meratakan dirinya sendiri ke dalam array dua dimensi. Ini berarti bahwa bagian yang sangat padat (mis., Benua yang sepenuhnya dieksplorasi) akan memiliki kinerja array (sangat cepat) tetapi bagian yang jarang penduduknya (misalnya, garis pantai seseorang berkeliaran ke atas dan ke bawah tetapi tidak menjelajahi pedalaman) akan memiliki kinerja yang baik dan penggunaan memori yang rendah.
Kode saya dapat ditemukan di sini . Kode lengkap, teruji (tes unit dan beban), dan cukup optimal. Namun, cara kerja bagian dalam belum terdokumentasi dengan baik, tetapi semua metode publik harus digunakan. Jika ada yang memutuskan untuk mencobanya, jangan ragu untuk menghubungi saya dengan pertanyaan atau komentar.
Saya belum menggunakannya untuk menyimpan data ke file, tapi ini masalah yang menarik dan saya mungkin akan mengatasinya nanti.
sumber
Anda dapat menggunakan database sebagai gantinya - PostgreSQL memiliki beberapa kemampuan pengindeksan khusus yang dioptimalkan untuk jenis data yang terletak oleh koordinat X dan Y. Anda juga dapat menentukan bahwa data yang dikembalikan berada dalam radius tertentu daripada di daerah berbentuk persegi atau bujur.
PostgreSQL (sumber gratis dan terbuka)
http://www.postgresql.org/
Ada juga basis data lain, dan untuk sisi klien Anda mungkin menemukan tipe tertentu lebih cocok untuk ini karena mereka dapat berjalan sendiri (diprakarsai oleh aplikasi klien game Anda) atau dapat dimasukkan sebagai bagian dari perpustakaan kode Anda bisa "gunakan saja." Keuntungannya adalah Anda tidak perlu merancang skema pengindeksan karena sebagian besar mesin database SQL sudah melakukan ini dengan cukup baik.
Keuntungan dengan pendekatan database adalah bahwa Anda dapat membuat potongan Anda lebih kecil (atau menyingkirkan potongan sepenuhnya dan hanya menggunakan ubin langsung, tetapi penggunaan setidaknya potongan kecil / kelompok banyak ubin mungkin lebih efisien tergantung pada desain Anda), dan kemudian menggunakan kueri SQL untuk membawa area yang lebih besar daripada yang dapat dilihat. Dengan pra-pemuatan untuk tumpang tindih dengan area yang tidak dapat dilihat di dekatnya, ubin dapat disiapkan sebelum pemain memindahkan karakter mereka, menghasilkan pengalaman bermain game yang lebih baik (semoga lebih mulus).
Saya perhatikan bahwa beberapa game menyimpan "cache" dari data peta pada hard drive lokal setelah mendapatkannya pertama kali (ini tidak diragukan lagi untuk mengurangi I / O jaringan), seperti Ashen Empires:
Ashen Empires (gratis untuk bermain, implementasi 2D yang indah)
http://www.ashenempires.com/
Melacak stempel waktu "terakhir diperbarui" dengan setiap potongan / ubin juga akan membantu karena, untuk tempat data yang disimpan secara lokal tersedia, kueri SQL dapat menyertakan klausa "WHERE timestamp_column> $ local_timestamp" tambahan sehingga hanya potongan / ubin yang diperbarui yang mendapatkan diunduh (dua manfaat dari menghemat bandwidth seperti ini adalah biaya konektivitas yang lebih rendah, dan sedikit lag untuk pemain Anda, yang akan menjadi lebih jelas ketika permainan Anda menjadi populer).
Tangkapan layar dari Ashen Empires (beberapa karakter ada di bank lokal, dan dari penampilan tulang-tulang itu di lantai, sepertinya beberapa monster kerangka pasti telah mengembara dan kemungkinan dibantai oleh penjaga kota setempat):
sumber
Jangan menyimpan dan mengaksesnya, simpan hanya benih acak yang diperlukan serta perubahan pemain ke peta. Kemudian hasilkan porsi yang diperlukan saat run-time (jalankan algoritme pembuatan Anda, lalu terapkan perubahan pemain). Dengan prosedur pembuatan yang benar dan konsisten, peta yang dihasilkan akan selalu sama untuk seed awal yang sama.
Secara teoritis Anda dapat melakukan peta yang benar-benar tak terbatas yang akan menyimpan ke file yang sangat kecil dengan cara ini.
sumber
Apakah ada cara Anda dapat mempartisi potongan (semacam 'subkontinen / negara' di dunia Anda)? Jadi mungkin Anda dapat memiliki beberapa jenis file indeks yang memungkinkan Anda dengan cepat menemukan sub-file / bagian mana dari file yang lebih besar yang perlu Anda muat untuk memiliki sebagian dalam memori ...
sumber
Anda bisa mengambil ide dari Minecraft. Awalnya mereka memiliki file per chunk. Sekarang mereka menggunakan format MCRegion, yang mengelompokkan potongan menjadi area 32x32 dan menyimpan salah satu dari mereka per file.
sumber