Cara menangani Block World seperti Minecraft


9

Saya ingin menulis permainan sederhana dengan dunia blok seperti di Minecraft. Pertanyaan teoretis saya adalah apa cara terbaik untuk menangani informasi blok ini selama bermain. Ide pertama saya adalah array besar tetapi saya pikir ini akan menyebabkan kehabisan memori. Mungkin saya hanya perlu memuat blok di dekat pemain.

Bagaimana saya bisa menangani pemuatan informasi blok yang diperlukan dari file dan hanya menyimpan yang diperlukan dalam memori?


2
Minecraft memuat dunia dalam kubus yang cukup besar yang disebut Chunks, tidak sekaligus. Saya tidak yakin dengan detail pastinya. Sumber Minecraft cukup mudah didapat jika Anda ingin melihat bagaimana itu hilang.
ratbum

Lihatlah minecraft wiki: minecraftwiki.net/wiki/Chunk
tom van green

Saya sudah tahu tentang bongkahan di Minecraft, tapi tetap terima kasih.
danijar

Ini adalah pertanyaan kompleks yang tidak sesuai untuk ruang lingkup blog ini.

Jawaban:


9

Ada beberapa cara berbeda untuk menyimpan data untuk gim dengan blok seperti Minecraft.

Cara saya percaya Minecraft melakukannya adalah menghancurkan dunia dalam 16x16x256 Bongkahan. Potongan di sekitar pemain dimuat ke dalam memori saat pemain memulai permainan, lalu utas latar memuat lebih banyak saat Anda berjalan. Berikut adalah video yang menunjukkannya: http://www.youtube.com/watch?v=oR_ZdJH9eho .

Cara lain untuk melakukannya adalah memecah dunia menjadi sebuah Octree. Michael Goodfellow menulis sebuah blog tentang menerapkan dunia kubus dengan struktur data ini: http://www.sea-of-memes.com/LetsCode1/LetsCode1.html . Oktree itu bagus karena memberi Anda beberapa kompresi built-in, tetapi mungkin akan sedikit lebih sulit untuk bekerja dengan Array.

Tentang menjaga "yang hanya dibutuhkan dalam memori?" Ini sedikit lebih sulit karena Anda harus bertanya apa yang "dibutuhkan". Jika Anda memiliki NPC yang hidup di bagian lain dunia dengan AI yang berinteraksi dengan lingkungan maka Anda "perlu" lebih banyak dari dunia untuk berada dalam memori. Data dunia Voxel dapat menjadi sangat besar dengan sangat cepat, jadi yang terbaik adalah mencoba untuk menyimpan jumlah seminimal mungkin dalam memori. (IE, hanya memiliki NPC di dekat pemain).

Mesin grafis akan "membutuhkan" setiap blok yang tidak sepenuhnya dikelilingi oleh blok non-transparan lainnya. Cara yang biasa untuk membuat dunia adalah dengan membangun satu jala tunggal yang berisi simpul untuk setiap blok yang terlihat. Ini jauh lebih cepat untuk menggambar karena Anda hanya membuat 1 panggilan ke metode menggambar untuk 65.536 blok (dalam potongan ukuran Minecraft). Karena mesin grafis perlu membangun mesh ini, umumnya perlu mengetahui semua kubus dalam sebuah potongan. Perhatikan bahwa inilah sebabnya ketika Anda melihat melalui lantai di Minecraft, banyak dunia tidak terlihat. Ini karena setiap blok yang dikelilingi di keenam sisi dilewati. Saya percaya Minecraft juga mengurangi jumlah simpul dengan menggabungkan sisi horizontal dengan jenis tekstur yang sama ke dalam satu kotak dengan tekstur berulang.

Saran saya adalah untuk pergi dengan potongan 16x16x256. Menyimpannya dalam Array karena Anda akan membutuhkan iterasi dan pengeditan yang cepat karena membangun logika jala dan game (deteksi tabrakan, menambah / menghapus blok, dll). Kemudian muat sebanyak mungkin potongan dalam lingkaran di sekitar pemain yang Anda bisa. Skala jumlah potongan atas atau bawah untuk komputer yang lebih baik atau lebih buruk.

Memuat Chunks akan menjadi hit besar pada kinerja, jadi letakkan di utas yang menjalankannya dari waktu ke waktu. Buat agar Anda dapat memuat 3 Potongan baru selama waktu yang dibutuhkan pemain untuk berjalan dari satu ujung ke ujung lainnya.


Terima kasih! Tidak ada tentang AI karena saya menulis klien untuk MMO. Menghitung NPC dilakukan oleh server. Satu tambahan: Tidak "setiap blok tidak sepenuhnya dikelilingi oleh blok non-transparan lainnya" diperlukan oleh mesin grafis. Jika ada gua pemain tidak bisa melihat mereka tidak penting. ;-)
danijar

2
Tentang gua yang tidak bisa dilihat pemain ... Saya pikir itu menggunakan kinerja yang lebih sedikit untuk hanya menggambar gua daripada menentukan apakah gua itu benar-benar diblokir. Dan jika Anda tidak menggambar gua maka jika Anda menghapus blok Anda berpotensi harus menghasilkan kembali mesh untuk beberapa potongan, bukan hanya satu. Akan lebih keren untuk menemukan cara untuk mengecualikan gua, saya hanya tidak bisa memikirkan cara untuk melakukannya secara efisien: D.
Thomas Marnell

3

Saya mungkin tidak memiliki cara terbaik untuk menjelaskannya tetapi saya akan mencoba.

Saya pikir cara terbaik untuk memahami cara membuatnya lebih efisien adalah dengan memahami Voxels. Minecraft berbasis voxel, hanya menggunakan kubus, bukan bola, dll., Dll.

Pada dasarnya voxel adalah bentuk 3D yang dapat memiliki volume yang berubah secara dinamis dan ketika volume berubah, demikian juga bentuknya. Chunk adalah X dengan X oleh X set voxels. Jadi misalnya, Anda dapat memiliki bongkahan yang memiliki 16x16x16 voxels dan kemudian Anda dapat memiliki bilangan X. Anda akan memiliki jarak yang ditetapkan, bahwa jika pemain lebih jauh dari N jauh dari potongan apa pun, jangan memasukkannya dalam perhitungan Anda. Ini agak mirip dengan jarak kliping tetapi perlu diterapkan pada setiap bidak juga. Dengan cara ini, Anda dapat memilikinya sehingga Anda selalu dapat memiliki pemain Anda di bagian tengah dari, katakanlah, 3x3 set Chunks.

Jadi yang akan Anda miliki adalah kelas untuk menangani Voxels individu. Kami akan menyebutnya Voxel_cl. Dan kemudian Anda akan memiliki kelas untuk menangani potongan voxels, yang disebut Chunk_cl. Dan kemudian Anda akan memiliki beberapa kelas dunia yang menghasilkan semua potongan yang akan menghasilkan voxels, yang disebut World_cl.

Jadi sekarang, alih-alih array yang besar dari semuanya, Anda akan memiliki array 9 Bongkahan kapan saja dan di kelas chunk, Anda akan memiliki array 4096 voxels.

Harap dicatat bahwa ini adalah penjelasan yang cukup sederhana. Saat ini saya sedang mengerjakan sesuatu menggunakan voxels jadi saya pikir saya akan memasukkan input saya = -)

Untuk info lebih lanjut tentang voxels, periksa http://en.wikipedia.org/wiki/Marching_cubes


3
Marching Cubes adalah tentang memvisualisasikan voxel. Dan Minecraft bahkan tidak menggunakannya; itu hanya menarik kubus, yang persis apa yang tentang Marching Cubes tidak melakukan.
Nicol Bolas

Terima kasih atas penjelasan anda! Saya tidak pernah mendengar Voxels sebelumnya dan sepertinya sangat penting untuk proyek saya. Tapi saya masih punya pertanyaan.
danijar

Saya mengerti membuat array potongan dekat di mana setiap elemen berisi array voxels dari chunk ini. Tapi kemudian saya perlu menangani mengubah array chunk ketika pemain bergerak di dunia. Apakah saya harus membaca potongan yang diperlukan dari file simpan? Atau adakah cara yang baik untuk menyimpannya dalam ingatan?
danijar

2
@danijar Hanya beberapa hal sepele, piksel adalah kependekan dari "elemen gambar", voxel dibentuk dengan cara yang sama dari "elemen volume". Bukan berarti itu penting untuk apa pun, tetapi karena Anda belum pernah mendengar istilah voxel sebelum saya pikir itu mungkin menarik bagi Anda.
Daniel Carlsson

1

Anda bisa mencoba membuat permukaan yang terlihat menjadi render, komputer menangani blok data di latar belakang, sementara renderer hanya bekerja dengan apa yang Anda lihat. Potongan 8x8 akan lebih mudah untuk ditangani.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.