#3 Membangun penjara dengan mouse, dan ruangan yang menemukan dirinya sendiri
· Nick
Tonggak kedua sudah selesai, dan untuk pertama kalinya ada sesuatu yang bisa dilihat. Klien Godot kini berdiri di atas inti simulasi, dan kamu bisa membangun penjara satu lantai dengan mouse: memasang lantai, menarik dinding, menaruh pintu, menandai ruangan, membongkar. Semuanya kubus polos dan warna datar, dan belum ada orang di dalamnya. Tapi ini sebuah tempat, dan tempat yang bisa kamu kelilingi dengan kamera.
Yang bisa dilakukan sekarang
Kamu memulai permainan baru, memilih ukuran peta (64, 128, atau 256 ubin persegi) dan seed opsional, lalu mendapat kisi kosong. Kameranya ortografis dengan kemiringan tetap. Ia berputar dalam langkah tegas 90°, memperbesar ke arah kursor, bergeser dengan tombol atau tombol tengah mouse, dan punya mode tampak atas untuk membangun. Dinding akan menutupi ruangan dari kamera yang bisa berputar bebas, jadi kameranya tidak berputar bebas.
Lantai dan pembongkaran memakai persegi panjang. Dinding mengikuti garis luar (atau garis lurus jika kamu menahan Shift). Pintu cukup satu klik, dan arahnya dipilih dari dinding di sebelahnya, dengan tombol untuk memutarnya. Selagi kamu menyeret, area di bawah kursor ditampilkan sebagai bayangan: ubin hijau akan dibangun, ubin merah akan dilewati, dan sebuah label menyebutkan berapa banyak dan alasannya. Tidak ada yang dikirim ke dunia sampai kamu melepas tombol, dan jika inti mengatakan tidak ada satu ubin pun yang akan berubah, tidak ada yang dikirim sama sekali. Klik kanan atau Escape membatalkan.
Model dunia punya beberapa lantai, jadi ada pemilih lantai, dan lantai di atas lantai yang sedang aktif disembunyikan. Ruangan punya alatnya sendiri, dibahas di bawah. Overlay debug menampilkan batas chunk, ubin yang bisa dilalui, ubin di bawah kursor, dan panel waktu. Setiap kata di antarmuka berbahasa Inggris.
Pratinjaunya adalah hasil sebenarnya
Bayangan yang berbeda dari hasilnya lebih buruk daripada tanpa bayangan. Jadi klien tidak menebak apa yang akan dilakukan sebuah perintah pembangunan. Inti bisa menjawab “apa yang akan terjadi jika kamu menjalankan ini” untuk area yang sama, ubin demi ubin, dengan alasan untuk setiap ubin yang akan ditolaknya. Pemeriksaan yang mengisi pratinjau adalah aturan yang sama yang dipakai perintah saat benar-benar dijalankan, sehingga keduanya tidak bisa menyimpang. Klien hanya menggambar jawabannya. Ia bertanya lagi ke inti hanya ketika sesuatu yang memengaruhi jawaban berubah: alat, area yang diseret, lantai, atau peta itu sendiri.
Prinsip yang sama membentuk sisa klien: ia membaca keadaan dunia dan mengirim perintah, tanpa logika simulasi sendiri. Untuk saat ini inti berjalan di thread utama, dan perintah dari sebuah klik diterapkan di awal frame berikutnya, sebelum dunia melakukan tick. Jika waktu tick suatu saat mulai melonjak begitu dunia penuh orang, rencananya adalah memindahkan inti ke thread-nya sendiri, dengan ambang yang terukur kapan harus melakukannya.
Ruangan yang menemukan dirinya sendiri
Saya melihat dua cara membuat ruangan. Prison Architect membiarkanmu menggambar zona, yang kemudian menjadi objek tersendiri dengan ubin-ubinnya sendiri. Itu mudah dipahami, tetapi bermasalah di penjara: satu blok sel utuh akan menjadi satu zona, dan setelah kamu membangun ulang sebuah dinding, kamu harus mengecatnya lagi. Cara lainnya adalah menemukan area tertutup secara otomatis, tetapi dengan begitu kamu tidak bisa menandai halaman yang tidak dikelilingi dinding.
Yang saya pilih adalah campuran. Satu-satunya yang disimpan adalah tipe ruangan pada setiap ubin: sel, kantin, kamar mandi, klinik, ruang kunjungan, halaman olahraga, dan seterusnya. Semua yang lain dihitung dari dinding. Sebuah ruang adalah kelompok ubin terbuka yang terhubung lewat sisi, pada satu tingkat, dan ruang itu tertutup jika tidak menyentuh tepi peta atau jurang kosong. Ruangan adalah semua ubin dengan satu tipe dalam satu ruang. Dinding dan pintu adalah batas, dan tipe yang dicat di bawah dinding tetap disimpan tetapi diabaikan, sehingga ia kembali jika kamu merobohkan dindingnya.
Hasilnya adalah perilaku yang terasa benar tanpa perlu dijelaskan. Pasang dinding membelah sebuah ruangan dan ia menjadi dua ruangan bertipe sama. Singkirkan dindingnya dan keduanya menyatu. Pasang pintu di tempat dinding tadi dan tidak ada yang berubah. Ruangan yang tidak valid tidak dihapus, karena itu kebalikan dari “tanpa repot”; ia ditampilkan merah beserta alasannya: tidak tertutup, berbagi dengan tipe lain, terlalu kecil, atau tidak ada pintu. Kamu bisa mengecat persegi panjang, mengisi seluruh ruang tertutup dengan satu klik, atau mengosongkannya.
Daftar ruangan adalah data turunan, jadi tidak disimpan dan bukan bagian dari hash dunia; hanya tipe pada setiap ubin yang termasuk. Daftar itu dibangun ulang setelah perintah dan setelah sistem, dan memeriksa dunia yang tidak berubah tidak memakan biaya apa pun. Di tonggak ini, tingkat yang berubah dihitung ulang secara utuh, yang memakan sekitar setengah milidetik pada peta 256×256; menghitung per chunk bisa menunggu sampai region jalur membutuhkan mekanisme yang sama. Aturan yang saya pegang: pembangunan ulang inkremental harus memberi hasil yang sama dengan pembangunan ulang penuh.
Bangun ulang hanya yang berubah, potong lantai tanpa biaya
Peta digambar sebagai satu mesh per chunk per tingkat, bukan satu objek per dinding. Setiap chunk punya penghitung versi di inti, dan renderer mengingat versi mana yang terakhir digambarnya. Saat dunia berubah, hanya chunk dengan versi lebih baru yang masuk antrean, dan antrean itu dikerjakan dengan anggaran waktu per frame, sehingga perubahan besar tersebar ke beberapa frame alih-alih membekukan satu frame. Mengecat tipe ruangan tidak menaikkan versi peta, jadi tidak pernah membangunkan pembuat mesh sama sekali.
Pemotongan lantai mengikuti gagasan yang sama untuk bekerja lebih sedikit. Lantai di atas lantai aktif cukup disembunyikan. Dinding lantai aktif dipendekkan menjadi satu meter oleh sebuah shader, dengan satu material bersama dan satu nilai tinggi, sehingga berganti lantai atau menyalakan dinding penuh tidak membangun ulang apa pun. Berpindah melalui empat tingkat tidak memicu satu pun pembangunan ulang mesh.
Celah sepuluh sentimeter
Ketika saya mencoba penjara satu lantai pertama pada pemeriksaan akhir, ada lantai di tingkat atas, dan dari samping terlihat garis terang tipis antara puncak dinding dan pelat di atasnya. Di sebuah sudut, lantainya tampak melayang di udara. Saya mencurigai pemotongan lantai, lalu z-fighting, lalu penghalusan tepi.
Ternyata bukan semuanya. Lantainya adalah satu bidang datar tanpa ketebalan, digambar pada tinggi tingkatnya ditambah sepuluh sentimeter. Dinding tingkat di bawahnya naik tepat sampai tiga meter. Lantai tingkat berikutnya mulai pada tiga meter sepuluh. Celahnya selebar sepuluh sentimeter, dan lewat celah itu kamu bisa melihat sisi atas dinding yang terkena cahaya. Secara horizontal semuanya pas sempurna, itulah sebabnya butuh waktu untuk melihatnya.
Perbaikannya: lantai kini berupa pelat dengan ketebalan nyata, menjulur ke bawah sampai awal tingkatnya. Bagian atasnya tetap di ketinggian yang sama, jadi pemilihan ubin dengan mouse dan semua overlay tidak berubah. Sisi samping dilewati di tempat lantai atau dinding bersentuhan dalam chunk yang sama dan digambar di batas chunk, sehingga mesh sebuah chunk tidak pernah bergantung pada tetangganya. Itu menyisakan tepi gelap sepuluh sentimeter di ujung pelat. Saya melihat tangkapan layar sebelum dan sesudah, lalu memutuskan untuk mempertahankannya. Ia terbaca sebagai tepi lantai, dan memang itulah ia.
Apakah ini bertahan?
Tugas terakhir tonggak ini adalah membangun penjara satu lantai dengan mouse dan melihat apakah terasa menyiksa. Sebagian besar tidak. Yang ditemukan selain celah tadi kecil dan menjengkelkan: tombol alat tidak kehilangan sorotannya ketika kamu memilih alat lain dengan mouse, dan tidak ada cara keluar dari dialog New Game dengan Escape. Keduanya sudah diperbaiki. Menu jeda ada di daftar ide untuk nanti.
Berikutnya
Berikutnya adalah M2, pergerakan dan rutinitas harian. Dunia mendapat region dan keterjangkauan, pencarian jalur yang bekerja lintas lantai, dan flow field untuk kerumunan. Inti akhirnya punya pekerjaan nyata di setiap tick, jadi gerbang benchmark akan berhenti tertidur. Lihat peta jalan.