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?
c++
voxels
minecraft-modding
data
danijar
sumber
sumber
Jawaban:
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.
sumber
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
sumber
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.
sumber