Saya memiliki sistem air berbasis jaringan 2D dalam game XNA saya, kami memiliki metode menggunakan automata seluler untuk mensimulasikan jatuh dan penyebaran air.
Contoh air yang mengalir menuruni lereng:
Setiap ubin dapat berisi massa 0 hingga 255 nilai cairan, disimpan dalam byte. Saya tidak menggunakan floats
, sistem air lama yang saya lakukan, tetapi menambah komplikasi dan memiliki kinerja yang baik.
Setiap ubin air memperbarui dirinya dengan seperangkat aturan sederhana:
- Jika ubin di bawah ini memiliki ruang di dalamnya, pindahkan sebanyak mungkin dari ubin saat ini ke ubin bawah (Aliran Turun)
- Jika 2 sisi tidak sama dan tidak nol dan keduanya bisa dilewati, kita mendapatkan jumlah dari 3 ubin (kiri + sekarang + kanan) dan membaginya dengan 3 meninggalkan sisanya di ubin tengah (saat ini)
- Jika aturan di atas memberikan angka 2 sebagai jumlah, kita harus membagi ubin menjadi dua sisi (1, 0, 1)
- Jika aturan 2 memberi 1 sebagai jumlah, pilih sisi acak untuk mengalir
- Jika aturan 2 gagal, kita harus memeriksa apakah satu sisi bisa dilewati dan yang lainnya tidak. Jika itu benar, kami membagi ubin saat ini menjadi dua untuk 2 ubin
Bagaimana saya bisa memperluas logika ini untuk memasukkan tekanan? Tekanan akan membuat cairan naik di atas "U-Bends" dan mengisi kantong udara.
Contoh tentang bagaimana ini gagal saat ini:
Air harus mengalir dan menyamakan di setiap sisi U-Bend. Selain itu, saya telah menciptakan metode untuk mengetahui seberapa jauh blok air itu, dan oleh karena itu seberapa banyak tekanan yang dialami. Sekarang saya harus bisa mengambil angka-angka ini dan menerapkannya ke area lain untuk menyamakan tekanan.
Jawaban:
Perhatikan bahwa saya belum pernah melakukan ini; ini hanya ide yang dapat membantu. Atau mungkin benar-benar palsu. Saya sudah ingin mengatasi masalah ini sejak Terraria tetapi saat ini saya tidak bekerja pada permainan seperti itu.
Salah satu cara yang saya pertimbangkan untuk mencoba adalah memberikan setiap blok air permukaan (setiap blok dengan air di dalamnya dan tanpa blok air di atasnya) nilai tekanan awal sama dengan (atau fungsi) ketinggiannya dari bagian bawah dunia. Nilai tekanan implisit dari setiap ubin yang tidak dapat dilewati adalah
MAX_PRESSURE
(katakanlah 255), dan untuk ubin udara terbuka adalahMIN_PRESSURE
(0).Tekanan kemudian menyebar ke atas / ke bawah / ke samping dari ubin mana pun dengan tekanan lebih tinggi ke ubin dengan tekanan lebih rendah selama setiap centang, gaya automata seluler. Saya harus mendapatkan simulasi yang sebenarnya untuk mencari tahu persis apa yang harus disamakan. Tekanan blok harus sama dengan tekanan implisit ditambah tekanan "kelebihan" dari sekitar yang disamakan (jadi Anda hanya perlu menyimpan tekanan berlebih ini, bukan tekanan implisit).
Jika ubin permukaan memiliki tekanan lebih besar daripada tekanan berbasis ketinggian implisitnya dan jika ubin di atas memiliki ruang bebas untuk air, sebagian kecil air dipindahkan ke atas. Air hanya mengalir turun jika ubin keduanya memiliki ruang karena memiliki tekanan lebih rendah dari yang diharapkan.
Ini secara kasar mensimulasikan gagasan bahwa semakin dalam "titik" air semakin banyak tekanan yang dimilikinya, meskipun nilai tekanan mewakili lebih tinggi daripada tekanan aktual (karena ubin yang lebih tinggi diharapkan memiliki "tekanan" yang lebih tinggi). Ini membuat tekanan agak seperti
h
istilah dalam persamaan (tapi tidak terlalu):Hasilnya adalah bahwa jika tekanan air lebih tinggi dari yang seharusnya untuk kedalamannya, itu akan didorong ke atas. Itu harus berarti bahwa level air dalam sistem tertutup akan menyamakan tekanan di semua level ketinggian seiring waktu.
Saya tidak yakin bagaimana cara menghadapinya atau apakah seseorang bahkan perlu berurusan dengan "gelembung udara" yang akan dibuat (di mana ubin non-permukaan akan memiliki jumlah air yang tidak penuh saat air didorong ke atas). Saya juga masih tidak yakin bagaimana Anda akan menghindari loop tekanan air yang tidak setara di satu sisi dan kemudian setelah berdetak tidak sama di sisi lain, bolak-balik.
sumber
Saya membuat sistem yang mirip dengan yang Anda kejar dalam 3D. Saya punya video pendek yang menunjukkan mekanisme sederhana di sini dan posting blog di sini .
Inilah sedikit gif yang saya buat dari mekanik tekanan di balik dinding yang tidak terlihat (dimainkan dengan kecepatan tinggi):
Biarkan saya menjelaskan data yang terlibat, untuk memberikan gambaran tentang beberapa fitur sistem. Dalam sistem saat ini, setiap blok air berisi yang berikut dalam 2 Bytes:
Height
adalah jumlah air dalam kubus, mirip dengan tekanan Anda, tetapi sistem saya hanya memiliki 8 level.Direction
adalah arah aliran menuju. Ketika memutuskan di mana air akan mengalir selanjutnya, itu lebih cenderung untuk melanjutkan ke arah saat ini. Ini juga digunakan untuk dengan cepat melacak kembali aliran kembali ke kubus sumbernya ketika dibutuhkan.IsSource
menunjukkan jika kubus ini adalah kubus sumber, artinya kubus tidak pernah kehabisan air. Digunakan untuk sumber sungai, mata air, dll. Kubus di sebelah kiri dalam gif di atas adalah kubus sumber, misalnya.HasSource
menunjukkan apakah kubus ini terhubung ke kubus sumber. Ketika terhubung ke sumber, kubus akan mencoba untuk menyadap sumber air lebih banyak sebelum mencari kubus non-sumber "lebih penuh" lainnya.Largest
memberi tahu kubus ini apa aliran terbesar antara itu dan kubus sumbernya. Ini berarti jika air mengalir melalui celah sempit, itu membatasi aliran ke kubus ini.Active
adalah sebuah counter. Ketika kubus ini memiliki aliran aktif melewatinya, ke sana, atau dari situ, aktif akan bertambah. Jika tidak aktif akan dikurangi secara acak. Setelah aktif mencapai nol (artinya tidak aktif), jumlah air akan mulai berkurang di kubus ini. Tindakan semacam ini seperti penguapan atau meresap ke dalam tanah. ( Jika Anda memiliki aliran, Anda harus mengalami pasang surut! )FlowOut
menunjukkan jika kubus ini terhubung ke kubus yang ada di ujung dunia. Begitu jalan menuju ujung dunia dibuat, air cenderung memilih jalan itu daripada yang lain.Extra
adalah bit ekstra untuk penggunaan di masa depan.Sekarang kita tahu datanya, mari kita lihat ikhtisar algoritma tingkat tinggi. Ide dasar dari sistem ini adalah memprioritaskan mengalir turun dan keluar. Seperti yang saya jelaskan di video, saya bekerja dari bawah ke atas. Setiap lapisan air diproses satu tingkat pada satu waktu dalam sumbu y. Kubus untuk setiap level diproses secara acak, setiap kubus akan berusaha menarik air dari sumbernya pada setiap iterasi.
Kubus aliran menarik air dari sumbernya dengan mengikuti arah alirannya kembali hingga mencapai kubus sumber atau kubus aliran tanpa induk. Menyimpan arah aliran di setiap kubus membuat mengikuti jalur ke sumber semudah melintasi daftar tertaut.
Kode pseudo untuk algoritma adalah sebagai berikut:
Aturan dasar untuk memperluas aliran di mana (dipesan berdasarkan prioritas):
Saya tahu, itu level yang cukup tinggi. Tapi sulit untuk masuk ke detail lebih tanpa mendapatkan cara ke detail.
Sistem ini bekerja dengan cukup baik. Saya dapat dengan mudah mengisi lubang-lubang air, yang meluap untuk terus keluar. Saya bisa mengisi terowongan berbentuk U seperti yang Anda lihat di gif di atas. Namun, seperti yang saya katakan, sistemnya tidak lengkap dan saya belum menyelesaikan semuanya. Saya belum bekerja pada sistem aliran dalam waktu yang lama (saya memutuskan itu tidak diperlukan untuk alpha dan saya akan menahannya). Namun, masalah yang saya hadapi ketika saya tunda dimana:
Kolam renang . Ketika mendapatkan genangan air yang besar, petunjuk dari anak ke orang tua seperti kekacauan gila dari kubus acak apa pun yang dipilih untuk mengalir ke arah mana pun. Seperti mengisi bathtub dengan tali konyol. Saat Anda ingin mengalirkan bak mandi, haruskah Anda mengikuti jalur benang konyol kembali ke sumbernya? Atau haruskah Anda mengambil apa pun yang terdekat? Jadi dalam situasi di mana kubus berada di kolam besar, mereka mungkin seharusnya mengabaikan arus induknya dan menarik dari apa pun yang ada di atas mereka. Saya datang dengan beberapa kode kerja dasar untuk ini, tetapi tidak pernah memiliki solusi elegan yang bisa saya senangi.
Banyak orang tua . Aliran anak dapat dengan mudah diberi makan oleh lebih dari satu aliran induk. Tetapi anak yang memiliki pointer ke orang tua tunggal tidak akan membiarkan itu. Ini dapat diperbaiki dengan menggunakan bit yang cukup untuk memungkinkan bit untuk setiap arah induk yang mungkin. Dan kemungkinan mengubah algoritma untuk secara acak memilih jalur dalam kasus beberapa orang tua. Tapi, saya tidak pernah sempat untuk menguji dan melihat masalah apa yang mungkin terungkap.
sumber
Saya agak setuju dengan Sean tapi saya akan melakukannya sedikit berbeda:
Blok menghasilkan tekanan yang sama dengan beratnya sendiri (berapa banyak air di dalamnya) dan menerapkannya pada blok di bawah dan di sebelahnya. Saya tidak melihat alasan mengapa posisinya di dunia relevan.
Pada setiap kutu, gerakkan air dari tekanan tinggi ke tekanan rendah, tetapi gerakkan hanya sebagian kecil dari air yang dibutuhkan untuk menyamakan kedudukan. Air juga dapat didorong ke atas jika tekanan di blok terlalu besar untuk tekanan yang diterapkan di alun-alun.
Anda akan mendapatkan loop di mana tekanan air mengalir terlalu jauh satu arah dan kemudian harus memperbaiki tetapi karena Anda tidak memindahkan seluruh jumlah air per kutu ini akan teredam. Saya pikir itu sebenarnya hal yang baik karena Anda akan mendapatkan efek gelombang ketika air membanjiri area seperti yang Anda bayangkan.
sumber
Anda dapat menambahkan aturan yang mencoba untuk pergi ke kiri atau kanan (melalui dinding) dengan ubin sampai Anda menemukan tempat gratis, dimulai dengan lapisan di bagian bawah. Jika Anda tidak dapat menemukan, maka ubin tetap pada posisi saat ini. Jika Anda menemukan, maka aturan lain akan menjamin penggantian ubin yang dipindahkan (jika perlu).
sumber
mengapa Anda tidak bisa mendefinisikan jenis blok lain yang bertindak sebagai jumlah tekanan tidak bergerak? Karena itu ketika Anda menggunakan cara Anda biasanya memindahkan balok air dan memeriksa apakah itu bisa naik, itu tidak bisa.
Yang lebih baik adalah menambahkan definisi lain pada blok-blok yang memungkinkan pengguna untuk memasukkan jumlah tekanan per blok, meningkatkan tekanan sesuai dengan jumlah blok air yang menambahkannya.
sumber