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:
//Data2 Data
//______________________________ _____________________________________
//|0 |0 |000 |000 | |0 |0 |000 |000 |
//|Extra|FlowOut|Active|Largest| |HasSource|IsSource|Direction|Height|
//------------------------------ -------------------------------------
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:
for i = 0 to topOfWorld //from the bottom to the top
while flowouts[i].hasitems() //while this layer has flow outs
flowout = removeRandom(flowouts[i]) //select one randomly
srcpath = getPathToParent(flowout) //get the path to its parent
//set cubes as active and update their "largest" value
//also removes flow from the source for this flow cycle
srcpath.setActiveAndFlux()
//now we deal with regular flow
for i = 0 to topOfWorld //from the bottom to the top
while activeflows[i].hasitems() //while this layer has water
flowcube = removeRandom(activeflows[i]) //select one randomly
//if the current cube is already full, try to distribute to immediate neighbors
flowamt = 0
if flowcube.isfull
flowamt = flowcube.settleToSurrounding
else
srcpath = getPathToParent(flowcube) //get the path to its parent
flowamt = srcpath.setActiveAndFlux()
flowcube.addflow(flowamt)
//if we didn't end up moving any flow this iteration, reduce the activity
//if activity is 0 already, use a small random chance of removing flow
if flowamt == 0
flowcube.reduceActive()
refillSourceCubes()
Aturan dasar untuk memperluas aliran di mana (dipesan berdasarkan prioritas):
- Jika kubus di bawah memiliki lebih sedikit air, mengalirlah ke bawah
- Jika kubus yang berdekatan pada tingkat yang sama memiliki lebih sedikit air, mengalirlah secara lateral.
- Jika kubus di atas memiliki lebih sedikit air DAN kubus sumber lebih tinggi dari kubus di atas, mengalirlah ke atas.
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.