Bagaimana saya bisa mendeteksi "kamar" di game gulir sisi 2D?


24

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:

  1. Zona ini sepenuhnya terisolasi dari "luar" oleh blok yang ditempatkan pemain.
  2. Zona ini dapat memuat persegi panjang 5x7.
  3. setidaknya ada satu meja, satu sumber cahaya, dan kursi di area tertutup.
  4. Ada pintu keluar dari zona.
  5. 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:

masukkan deskripsi gambar di sini


5
Bisakah Anda menguraikan? Apa yang Anda maksud dengan "tipe bangunan" dan apa itu "tempat tinggal" di Terraria? Ingatlah bahwa tidak semua orang pernah memainkan game itu, juga fokus pada satu pertanyaan jika Anda ingin orang lain membantu, dan pastikan pertanyaan itu memiliki jawaban yang pasti (bukan pendapat)
TomTsagk

1
Dengan tipe yang saya maksud berbeda komponen / ubin yang digunakan. Pertanyaan saya terpecahkan di bawah ini. Saya akan mencoba menjelaskan lebih banyak dan lebih spesifik pada pertanyaan di masa depan, terima kasih atas bantuannya.
Bernardo Becker

1
Selain itu, pastikan ada perbedaan antara kamar dan tempat tinggal . Daftar peluru Anda menunjukkan bahwa Anda melihatnya sebagai definisi yang sama. Menggunakan Terraria sebagai contoh, musuh tidak bertelur di kamar, bahkan jika mereka tidak memenuhi syarat sebagai tempat tinggal (mis. Hilang meja, atau hanya berukuran 5x5)
Flater

Jawaban:


37

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, jika true, memulai algoritma. Namun, Anda harus berhati-hati dengan pendekatan ini:

  • Bagaimana jika ubin yang merupakan bagian dari ruangan, tetapi bukan ubin tempat karakter Anda, dimodifikasi? Mungkin ubin diubah oleh pemain lain, atau peristiwa lingkungan, atau masa pakai ubin berakhir. Karakter Anda tidak akan mengetahui modifikasi dan tidak akan menjalankan algoritma untuk mendeteksi ruang yang diperbarui, situasi yang rawan kesalahan.

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


9
Mengapa tidak mengisi hanya di antara ubin "yang ditempatkan pemain"? Hal ini dapat mencegah atau mengurangi pengisian banjir yang tak terbatas di area terbuka (selama gua / rumah mewah tidak diisi dengan "blok yang ditempatkan pemain").
jimbo1qaz

20
Mengapa Anda menjalankan ini pada interval tetap? Tentunya Anda bisa menjalankannya ketika sebuah blok ditempatkan (atau dihancurkan, jika berlaku, dan kedua kasus tersebut mungkin dapat dilakukan dalam waktu konstan yang diamortisasi per blok) atau ketika memuat bagian tertentu dari peta, dan kemudian menyimpan hasilnya dari sana.
NotThatGuy

3
@ Imibis: Saya cukup yakin bahwa Terraria tidak mengharuskan Anda untuk mengganti lantai. Saya juga tidak akan mengharapkan game untuk mengubah perilaku mengenali kamar berdasarkan siapa yang menempatkan ubin. Bagaimana jika saya misalnya membangun kamar yang berdekatan dengan tebing?
Flater

3
Terraria mengharuskan seseorang untuk meletakkan dinding latar belakang dan tidak akan membentuk rumah dengan latar belakang tanah / batu yang alami. Itu benar-benar hanya memeriksa blok yang ditempatkan pemain.
loa_in_

3
Untuk menghemat CPU, saya hanya akan menjalankan algoritma perubahan blok dan kemudian menyimpan negara untuk setiap blok. Dengan ini, ini sederhanaisRoom()
Herr Derb

3

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.


3

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.


0

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!


7 * 5 adalah persegi panjang ukuran minimum yang harus pas di dalam ruangan
Rick
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.