Saya ingin membuat sistem yang mengenali jenis bangunan dan ruangan tertentu yang dapat Anda buat dalam game, seperti bagaimana Terraria mendeteksi "tempat tinggal." Dalam permainan itu, sebuah rumah dapat dibangun di dunia berbasis ubin dengan membangun zona balok yang memenuhi serangkaian kondisi:
- Zona ini sepenuhnya terisolasi dari "luar" oleh blok yang ditempatkan pemain.
- Zona ini dapat memuat persegi panjang 5x7.
- setidaknya ada satu meja, satu sumber cahaya, dan kursi di area tertutup.
- Ada pintu keluar dari zona.
- Terraria memiliki lapisan ubin latar depan dan belakang. Seluruh latar belakang zona harus diisi dengan blok yang ditempatkan pemain.
Bagaimana saya bisa mendeteksi secara efisien ketika seorang pemain telah membangun area berukuran sesuai, dan bagaimana saya bisa secara efisien memeriksa bahwa area tersebut mengandung semua perabot / komponen yang diperlukan?
Contoh zona interior yang memenuhi semua persyaratan perumahan:
spatial-partitioning
Bernardo Becker
sumber
sumber
Jawaban:
Saya tidak terbiasa dengan Terraria, tapi itu bisa dengan mudah dilakukan menggunakan algoritma banjir-isi .
Alih-alih pixel, Anda memeriksa ubin, dan untuk setiap ubin diperiksa, Anda mengevaluasi apakah algoritma dapat melanjutkan memeriksa ubin lain, sambil menyimpan dalam array atau daftar objek mana yang ditemukan selama proses.
Algoritme dimulai dari ubin tempat karakter berada. Anda dapat memulai setiap 1 detik, 2 ... ini adalah masalah tweaker untuk menemukan interval terbaik.
Ini juga merupakan ide yang baik untuk mencegah algoritma berjalan terlalu lama, yang dapat dicapai dengan membatasi jumlah ubin yang dapat dijalankan oleh algoritma per run, jika tidak, algoritma Anda akan menyebabkan jeda panjang ketika karakter berada di area terbuka.
Edit
Seperti yang dinyatakan dalam komentar, Anda dapat menggunakan pendekatan lain tentang kapan harus memulai algoritma, seperti ketika pemain mengubah ubin, atau ubin memiliki
am I modified?
variabel yang, jikatrue
, memulai algoritma. Namun, Anda harus berhati-hati dengan pendekatan ini:Anda bisa menerapkan semacam pendekatan untuk mendeteksi modifikasi ini pada ubin yang tidak dimiliki karakter Anda, tetapi mengeksekusi algoritma pada interval adalah pendekatan yang paling sederhana, dan lebih sedikit rawan kesalahan. Pastikan untuk tidak melakukan pengisian banjir di setiap frame.
Akhir pengeditan
sumber
isRoom()
Seperti yang dikatakan @Ferreira da Selva, coba algoritma isi banjir. Padahal, Anda dapat menggunakan beberapa kriteria yang berbeda saat menjalankan algoritme untuk menentukan apakah itu terlampir.
Misalnya, untuk setiap ubin Anda memeriksa apakah ada ubin latar belakang, dan jika tidak ada, maka Anda tahu bahwa itu tidak tertutup. Atau Anda bisa membuatnya melakukan eksekusi yang ditangguhkan dengan memisahkannya di atas sejumlah bingkai, sehingga meringankan beban pada prosesor dan mengurangi jeda. Atau Anda bisa membuat batas ukuran ruangan yang harus dipatuhi pemain.
Menggunakan kombinasi ini akan memungkinkan Anda melakukannya dengan lebih efisien dan efektif.
sumber
Ada 2 masalah sulit dalam ilmu komputer. Memberi nama hal-hal, cacat cache dan kesalahan satu-per-satu.
Ini adalah masalah pembatalan cache.
Jika Anda memiliki catatan "apakah ini di dalam", setiap kali blok ditempatkan atau dihapus, cukup mudah untuk memperbaruinya dan wilayahnya melalui banjir.
Untuk mengoptimalkan ini, Anda mungkin ingin memiliki serangkaian tingkatan "insideness".
"Sel" adalah wilayah yang dikelilingi oleh blok yang ditempatkan pemain (hingga ukuran tertentu).
"Kamar" adalah sel dengan ubin latar belakang.
"Di dalam" adalah ruangan dengan pintu, lampu, dan kursi.
Saat Anda meletakkan blok latar depan yang ditempatkan pemain, lakukan gerakan searah jarum jam / berlawanan arah jarum jam untuk melihat apakah sel baru terbentuk. Saat Anda menghapus blok latar depan yang ditempatkan pemain, periksa apakah itu memecah sel - jika demikian, lihat apakah sel baru terbentuk dengan menggabungkan keduanya.
Ketika sel baru terbentuk atau tidak terbentuk, periksa apakah itu ruangan atau bagian dalam.
Sel dapat melacak berapa banyak ubin latar belakang yang mereka butuhkan untuk sebuah ruangan. Kemudian hitungan sederhana ketika sel terbentuk, ubin latar belakang ditambahkan atau dihapus dari sel, dapat menentukan apakah itu sebuah ruangan.
Demikian pula, Cell dapat melacak berapa banyak kursi dan sumber cahaya (dan sebenarnya objek dari semua jenis) di dalamnya. Kemudian cek di dalam adalah sepele.
Hitungan pintu masuk juga bisa dilakukan.
Jadi kami menambah peta dengan "sel". Ketika ubin ditambahkan atau dihapus, kami memeriksa sel lokasi, dan menambah / mengurangi jumlah dalam sel.
Gunakan berjalan searah jarum jam / berlawanan arah jarum jam untuk menentukan bagian dalam dan luar sel ketika blok latar depan ditambahkan atau dihapus. Karena ukuran sel terbatas, langkah ini akan mengambil sejumlah langkah terbatas.
Sebagai bonus, Anda sekarang memiliki cara yang murah untuk berbicara tentang kamar "mewah", atau "kamar diberkati oleh air mancur suci", atau apa pun tentang kamar, karena kamar memiliki jumlah setiap jenis objek di dalamnya. (Atau, karena ukuran kamar dibatasi, lakukan iterasi saja; ini akan menghapus cache).
Setiap lokasi paling banyak dalam satu sel, sehingga Anda dapat menyimpan id sel dari setiap lokasi di peta utama.
sumber
Saat menggunakan algoritme pengisian banjir, buat juga variabel, yang akan bertambah dengan setiap ubin yang dicentang, jadi jika lebih tinggi dari 35 (7 * 5, ukuran maksimal ruangan) itu hanya berhenti memeriksa!
sumber