Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Programming
Gamedevelopment

Buat Splash Dengan Kesan Air 2D Dinamik

by
Difficulty:IntermediateLength:LongLanguages:

Malay (Melayu) translation by Meyria (you can also view the original English article)

Sploosh! Dalam tutorial ini, saya akan menunjukkan kepada anda bagaimana anda boleh menggunakan kesan matematik, fizik dan zarah mudah untuk mensimulasikan ombak dan titisan air 2D yang hebat.



Nota: Walaupun tutorial ini ditulis menggunakan C# dan XNA, anda harus dapat menggunakan teknik dan konsep yang sama dalam hampir semua persekitaran pembangunan permainan.


Preview Keputusan Akhir

Sekiranya anda mempunyai XNA, anda boleh memuat turun fail sumber dan menyusun demo itu sendiri. Jika tidak, lihat video demo di bawah:

Terdapat dua bahagian yang paling bebas untuk simulasi air. Pertama, kita akan membuat gelombang menggunakan model musim bunga. Kedua, kami akan menggunakan kesan zarah untuk menambah percikan.


Membuat Gelombang

Untuk membuat gelombang, kita akan memodelkan permukaan air sebagai satu siri mata menegak, seperti yang ditunjukkan dalam rajah ini:

Ini akan membolehkan gelombang turun ke bawah dan ke bawah. Kami kemudiannya akan membuat zarah air menarik zarah-zarah jiran mereka untuk membolehkan gelombangnya tersebar.

Springs dan Hooke's Law

Satu perkara yang hebat tentang mata air ialah mereka mudah untuk meniru. Mata air mempunyai panjang semula jadi tertentu; jika anda meregangkan atau memampatkan mata air, ia akan cuba kembali kepada panjang semulajadi itu.

Gaya yang disediakan oleh musim bunga diberikan oleh Hooke's Law:

\[
F = -kx
\]

F adalah daya yang dihasilkan oleh pegas, k adalah pemalar pegas, dan x adalah anjakan musim bunga dari panjang semula jadi. Tanda negatif menandakan daya berada dalam arah yang bertentangan di mana musim bunga dipindahkan; jika anda menolak musim bunga, ia akan menolak kembali, dan sebaliknya.

Pemangkasan musim bunga, k, menentukan kekakuan musim bunga.

Untuk meniru mata air, kita mesti memikirkan bagaimana menggerakkan zarah-zarah di sekeliling berdasarkan Hukum Hooke. Untuk melakukan ini, kami memerlukan beberapa formula lagi dari fizik. Pertama, Hukum Undang-undang Kedua Newton:

\[
F = ma
\]

Di sini, F adalah daya, m adalah jisim dan a adalah pecutan. Ini bererti kekuatan yang lebih kuat menolak pada sesuatu objek, dan objek yang lebih ringan itu semakin meningkat.

Menggabungkan kedua-dua formula dan menyusun semula memberikan kami:

\[
a = -\frac{k}{m} x
\]

Ini memberikan kita pecutan untuk zarah kita. Kami akan mengandaikan bahawa semua zarah kita akan mempunyai jisim yang sama, jadi kita boleh menggabungkan k/m ke dalam pemalar tunggal.

Untuk menentukan kedudukan dari pecutan, kita perlu melakukan integrasi berangka. Kami akan menggunakan bentuk integrasi numerik yang paling mudah - setiap bingkai kami hanya melakukan perkara berikut:

Ini dipanggil kaedah Euler. Ia bukan jenis integrasi numerik yang paling tepat, tetapi ia pantas, mudah dan mencukupi untuk tujuan kami.

Meletakkannya bersama-sama, zarah permukaan air kami akan melakukan perkara berikut setiap bingkai:

Di sini, TargetHeight adalah kedudukan semula jadi di bahagian atas musim bunga apabila ia tidak diregangkan atau dimampatkan. Anda harus menetapkan nilai ini ke tempat yang anda inginkan permukaan air. Untuk demo itu, saya tetapkan pada separuh skrin, pada 240 piksel.

Ketegangan dan Lembap

Saya telah menyebut sebelum ini bahawa musim bunga tetap, k, mengawal kekakuan musim bunga. Anda boleh menyesuaikan nilai ini untuk menukar sifat-sifat air. Pemalar pegas yang rendah akan menjadikan pegas longgar. Ini bermakna daya akan menyebabkan ombak besar yang berayun perlahan-lahan. Sebaliknya, pegas pegas yang tinggi akan meningkatkan ketegangan pada musim bunga. Angkatan akan menghasilkan gelombang kecil yang berayun dengan cepat. Satu pemancaran musim bunga yang tinggi akan membuat air kelihatan seperti jiggling Jello.

Kata peringatan: jangan tetapkan musim bunga tetap terlalu tinggi. Mata air yang sangat kaku memaksa tentera yang sangat kuat yang banyak berubah dalam masa yang sangat kecil. Ini tidak berfungsi dengan baik dengan integrasi berangka, yang menyimulasikan mata air sebagai satu siri melompat diskret pada selang masa yang tetap. Musim bunga yang sangat sengit juga boleh mempunyai tempoh ayunan yang lebih pendek daripada langkah masa anda. Lebih teruk lagi, kaedah integrasi Euler cenderung untuk mendapatkan tenaga kerana simulasi menjadi kurang tepat, menyebabkan mata kaku meletup.

Terdapat masalah dengan model musim bunga kami setakat ini. Apabila musim bunga mula berayun, ia tidak akan berhenti. Untuk menyelesaikannya kita mesti menggunakan beberapa kelembapan. Idea ini adalah untuk memohon kuasa ke arah yang bertentangan bahawa musim bunga kita bergerak untuk melambatkannya. Ini memerlukan pelarasan kecil untuk formula musim bunga kami:

\[
a = -\frac{k}{m} x - dv
\]

Di sini, v adalah halaju dan d ialah faktor pelembab - satu lagi pemalar yang anda boleh tweak untuk menyesuaikan rasa air. Ia sepatutnya agak kecil jika anda mahu ombak anda berayun. Demo menggunakan faktor penyaman 0.025. Faktor pelembab yang tinggi akan menjadikan air kelihatan tebal seperti molase, manakala nilai yang rendah akan membolehkan gelombang berayun untuk masa yang lama.

Membuat Gelombang Berayun

Sekarang kita boleh membuat musim bunga, mari kita gunakan mereka untuk model air. Seperti yang ditunjukkan dalam gambarajah pertama, kami memodelkan air menggunakan satu siri selari, mata menegak. Sudah tentu, jika mata air adalah bebas, gelombang tidak akan tersebar seperti gelombang sebenar.

Saya akan menunjukkan kod itu dahulu, dan kemudian pergi ke sana:

Kod ini akan dipanggil setiap bingkai dari kaedah Kemas Kini() anda. Di sini, mata air adalah pelbagai mata air, diletakkan dari kiri ke kanan. leftDeltas adalah pelbagai terapung yang menyimpan perbezaan ketinggian antara setiap musim bunga dan jiran kiri. rightDeltas adalah setara untuk jiran yang betul. Kami menyimpan semua perbezaan ketinggian ini dalam array kerana dua terakhir if pernyataan mengubah ketinggian mata air. Kita perlu mengukur perbezaan ketinggian sebelum mana-mana ketinggian diubahsuai.

Kod bermula dengan menjalankan Undang-undang Hooke pada setiap musim bunga seperti yang dijelaskan sebelumnya. Ia kemudian melihat perbezaan ketinggian antara setiap musim bunga dan jirannya, dan setiap musim bunga menarik mata air jirannya ke arah dirinya dengan mengubah jawatan dan halaju jiran. Langkah menarik jiran diulang lapan kali untuk membolehkan gelombang untuk menyebarkan lebih cepat.

Terdapat satu lagi nilai tweakable di sini dipanggil Spread. Ia mengawal seberapa cepat gelombang merebak. Ia boleh mengambil nilai antara 0 dan 0.5, dengan nilai yang lebih besar menjadikan gelombang lebih cepat menyebar.

Untuk memulakan gelombang bergerak, kami akan menambah kaedah mudah yang dipanggil Splash().

Pada bila-bila masa anda ingin membuat gelombang, panggil Splash(). Parameter indeks menentukan pada musim bunga percikan harus berasal, dan parameter laju menentukan seberapa besar gelombang akan.

Rendering

Kami akan menggunakan kelas XNA PrimitiveBatch dari XNA PrimitivesSample. Kelas PrimitiveBatch membantu kami melukis garis dan segitiga terus dengan GPU. Anda menggunakannya seperti itu:

Satu perkara yang harus diperhatikan ialah, secara lalai, anda mesti menentukan simpul segitiga dalam urutan mengikut arah jam. Sekiranya anda menambahnya dalam urutan mengikut arah jam, segitiga akan dimusnahkan dan anda tidak akan melihatnya.

Ia tidak perlu mempunyai mata air bagi setiap piksel lebar. Dalam demo saya menggunakan mata air 201 yang tersebar di tingkap lebar 800 piksel. Itu memberikan tepat 4 piksel antara setiap musim bunga, dengan mata pertama pada 0 dan yang terakhir pada 800 piksel. Anda mungkin boleh menggunakan mata air walaupun lebih sedikit dan masih mempunyai air yang kelihatan lancar.

Apa yang kita mahu lakukan ialah menarik trapezoid yang nipis, tinggi dari bahagian bawah skrin ke permukaan air dan sambungkan mata air seperti yang ditunjukkan dalam rajah ini:

Oleh kerana kad grafik tidak mencipta trapezoid secara langsung, kita perlu menarik setiap trapezoid sebagai dua segi tiga. Untuk menjadikannya kelihatan lebih baik, kami juga akan menjadikan air lebih gelap kerana ia semakin mendalam dengan mewarnakan bahagian bawah garis biru gelap. GPU secara automatik akan menyerupai warna di antara simpang.

Inilah hasilnya:


Membuat Splashes

Ombak kelihatan cukup bagus, tetapi saya ingin melihat percikan ketika batu melanda air. Kesan zarah sempurna untuk ini.

Kesan zarah

Kesan zarah menggunakan sejumlah besar zarah kecil untuk menghasilkan beberapa kesan visual. Mereka kadang-kadang digunakan untuk perkara-perkara seperti asap atau bunga api. Kami akan menggunakan zarah untuk titisan air di percikan.

Perkara pertama yang kita perlukan adalah kelas zarah kita:

Kelas ini hanya memegang sifat zarah yang boleh dimiliki. Seterusnya, kami membuat senarai zarah.

Setiap bingkai, kita mesti mengemaskini dan melukis zarah.

Kami mengemas kini zarah-zarah itu untuk jatuh di bawah graviti dan menetapkan orientasi zarah agar sesuai dengan arah yang sedang berlaku. Kami kemudian menyingkirkan sebarang zarah yang berada di luar skrin atau di bawah air dengan menyalin semua zarah yang ingin kami simpan ke dalam senarai baru dan menyerahkannya kepada zarah. Seterusnya kita menarik zarah.

Berikut adalah tekstur yang saya gunakan untuk zarah.

Sekarang, apabila kita membuat percikan, kita membuat sekumpulan zarah.

Anda boleh memanggil kaedah ini daripada kaedah Splash () yang kami gunakan untuk membuat gelombang. Kelajuan parameter adalah berapa cepat batu melanda air. Kami akan membuat percikan yang lebih besar jika batuan bergerak lebih cepat.

GetRandomVector2 (40) mengembalikan vektor dengan arah rawak dan panjang rawak antara 0 dan 40. Kami mahu menambah sedikit rawak ke kedudukan supaya zarah tidak semua muncul pada satu titik. FromPolar() mengembalikan sebuah Vector2 dengan arah dan panjang yang diberikan.

Inilah hasilnya:

Menggunakan Metaballs sebagai Zarah

Percikan kami kelihatan cukup baik, dan beberapa permainan hebat, seperti World of Goo, mempunyai percikan kesan zarah yang kelihatan seperti kita. Walau bagaimanapun, saya akan menunjukkan teknik untuk membuat percikan kelihatan lebih cair. Teknik ini menggunakan metaballs, gumpalan organik yang saya telah menulis tutorial tentang itu sebelum ini. Jika anda berminat dengan butiran tentang metaballs dan cara mereka berfungsi, baca tutorial itu. Sekiranya anda hanya ingin tahu bagaimana untuk memaksanya ke percikan kita, baca terus.

Metaballs kelihatan seperti cecair dalam cara mereka menggabungkan bersama, menjadikannya perlawanan yang baik untuk percikan cecair kami. Untuk membuat metaballs, kita perlu menambah pembolehubah kelas baru:

Yang kita mulakan begini:

Kemudian kita menarik metaballs:

Kesan metaball bergantung kepada mempunyai tekstur zarah yang memudar apabila anda mendapat lebih jauh dari pusat. Inilah yang saya gunakan, tetapkan latar belakang hitam untuk menjadikannya kelihatan:

Inilah yang kelihatan seperti:

Titisan air kini bersatu ketika mereka rapat. Walau bagaimanapun, mereka tidak bersatu dengan permukaan air. Kita boleh membetulkannya dengan menambah kecerunan ke permukaan air yang menjadikannya secara beransur-ansur memudar, dan menjadikannya menjadi sasaran sasaran metaball kami.

Tambah kod berikut kepada kaedah di atas sebelum baris GrafikDevice.SetRendertarget (null):

Sekarang zarah akan bersatu dengan permukaan air.

Menambah Kesan Beveling

Zarah air kelihatan agak rata, dan ia akan menjadi lebih baik untuk memberi mereka teduhan. Idealnya, anda akan melakukan ini dalam shader. Walau bagaimanapun, demi menjaga tutorial ini mudah, kita akan menggunakan helah yang cepat dan mudah: kita hanya akan melukis zarah sebanyak tiga kali dengan warna dan warna yang berbeza, seperti yang digambarkan dalam rajah di bawah.

Untuk melakukan ini, kami ingin menangkap zarah metaball dalam sasaran baru. Kami kemudiannya akan menarik sasaran sekali untuk setiap warna.

Pertama, mengumumkan RenderTarget2D baru seperti yang kita lakukan untuk metaballs:

Kemudian, daripada melukis metaballsTarget terus ke backbinder, kami mahu menariknya ke partikelTarget. Untuk melakukan ini, pergi ke kaedah di mana kita melukis metaballs dan hanya mengubah baris ini:

...juga:

Kemudian gunakan kod berikut untuk melukis zarah sebanyak tiga kali dengan warna dan warna yang berbeza:


Kesimpulan

Itulah untuk  asas air 2D. Untuk demo, saya menambahkan batu yang boleh anda jatuhkan ke dalam air. Saya menarik air dengan ketelusan di atas batu untuk menjadikannya kelihatan seperti di bawah air, dan menjadikannya perlahan apabila ia berada di bawah air disebabkan oleh ketahanan air.

Untuk membuat demo kelihatan sedikit lebih baik, saya pergi ke opengameart.org dan mendapati imej untuk batu dan latar belakang langit. Anda boleh mencari batu dan langit di http://opengameart.org/content/rocks dan opengameart.org/content/sky-backdrop masing-masing.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.