7 days of WordPress themes, graphics & videos - for free!* Unlimited asset downloads! Start 7-Day Free Trial
Advertisement
  1. Game Development
  2. Programming

Buat Shooter Vektor Neon di XNA: Efek Partikel

Read Time: 17 mins
This post is part of a series called Cross-Platform Vector Shooter: XNA.
Make a Neon Vector Shooter in XNA: Bloom and Black Holes
Make a Neon Vector Shooter in XNA: The Warping Grid

Indonesian (Bahasa Indonesia) translation by Suci Rohini (you can also view the original English article)

Dalam seri tutorial ini, saya akan menunjukkan cara membuat shooter tongkat neon, seperti Geometri Wars, di XNA. Tujuan dari tutorial ini bukan untuk meninggalkan Anda dengan replika Perang Geometri yang sama persis, melainkan untuk membahas elemen-elemen penting yang memungkinkan Anda membuat varian berkualitas tinggi sendiri.


Overview

Dalam seri sejauh ini, kita telah mengatur gameplay dan menambahkan mekar. Selanjutnya, kita akan menambahkan efek partikel.

Efek partikel dibuat dengan membuat sejumlah besar partikel kecil. Mereka sangat serbaguna dan dapat digunakan untuk menambahkan bakat ke hampir semua game. Dalam Shape Blaster kita akan membuat ledakan menggunakan efek partikel. Kita juga akan menggunakan efek partikel untuk membuat api knalpot untuk kapal pemain, dan untuk menambah bakat visual ke lubang hitam. Plus, kita akan melihat bagaimana membuat partikel berinteraksi dengan gravitasi dari lubang hitam.

Kelas ParticleManager

Kita akan mulai dengan membuat kelas ParticleManager yang akan menyimpan, memperbarui, dan menggambar semua partikel. Kita akan membuat kelas ini cukup umum sehingga dapat dengan mudah digunakan kembali dalam proyek lain. Untuk menjaga ParticleManager umum, itu tidak akan bertanggung jawab atas bagaimana partikel terlihat atau bergerak; kita akan menanganinya di tempat lain.

Partikel cenderung dibuat dan dihancurkan dengan cepat dan dalam jumlah besar. Kita akan menggunakan kumpulan objek untuk menghindari pembuatan sejumlah besar sampah. Ini berarti kita akan mengalokasikan sejumlah besar partikel di depan, dan kemudian terus menggunakan kembali partikel yang sama ini. Kita juga akan membuat ParticleManager memiliki kapasitas tetap. Ini akan menyederhanakannya dan membantu memastikan kita tidak melebihi kinerja atau keterbatasan memori dengan menciptakan terlalu banyak partikel. Ketika jumlah partikel maksimum terlampaui, kita akan mulai mengganti partikel tertua dengan partikel baru.

Kita akan membuat ParticleManager menjadi kelas generik. Ini akan memungkinkan kita untuk menyimpan informasi status kustom untuk partikel-partikel tanpa hard coding ke ParticleManager itu sendiri. Kita juga akan membuat kelas Partikel bertingkat.

Kelas Partikel memiliki semua informasi yang diperlukan untuk menampilkan sebuah partikel dan mengatur masa hidupnya. Parameter generik, T State, ada untuk menyimpan data tambahan yang mungkin kita perlukan untuk partikel-partikel kita. Data apa yang dibutuhkan akan bervariasi tergantung pada efek partikel yang diinginkan; itu bisa digunakan untuk menyimpan kecepatan, akselerasi, kecepatan putaran, atau apa pun yang mungkin Anda perlukan.

Untuk membantu mengelola partikel, kita membutuhkan sebuah kelas yang berfungsi sebagai array circular, yang berarti bahwa indeks yang biasanya berada di luar batas akan membungkus ke awal dari array. Ini akan memudahkan untuk menggantikan partikel tertua terlebih dahulu jika kita kehabisan ruang untuk partikel baru dalam array kita. Kita menambahkan berikut sebagai kelas bersarang di ParticleManager.

Kita dapat mengatur properti Mulai untuk menyesuaikan di mana indeks nol dalam CircularParticleArray kita sesuai dengan array yang mendasari, dan Hitung akan digunakan untuk melacak berapa banyak partikel aktif dalam daftar. Kita akan memastikan bahwa partikel pada indeks nol selalu merupakan partikel tertua. Jika kita mengganti partikel tertua dengan yang baru, kita hanya akan menaikkan Start, yang pada dasarnya memutar array melingkar.

Sekarang kita memiliki kelas penolong, kita bisa mulai mengisi kelas ParticleManager. Kita membutuhkan beberapa variabel anggota, dan konstruktor.

Variabel pertama yang dideklarasikan, updateParticle, akan menjadi metode kustom yang memperbarui partikel secara tepat untuk efek yang diinginkan. Sebuah permainan dapat memiliki beberapa ParticleManager yang memperbarui secara berbeda jika diperlukan. Kita juga membuat CircularParticleList dan mengisinya dengan partikel kosong. Konstruktor adalah satu-satunya tempat ParticleManager mengalokasikan memori.

Selanjutnya kita tambahkan metode CreateParticle(), yang menciptakan partikel baru menggunakan partikel yang tidak digunakan berikutnya di kolam, atau partikel tertua jika tidak ada partikel yang tidak digunakan.

Partikel dapat dihancurkan setiap saat. Kita perlu menghilangkan partikel-partikel ini sambil memastikan partikel-partikel lainnya tetap dalam urutan yang sama. Kita bisa melakukan ini dengan melakukan iterasi melalui daftar partikel sambil melacak berapa banyak yang telah dihancurkan. Ketika kita pergi, kita memindahkan setiap partikel aktif di depan semua partikel yang hancur dengan menukarnya dengan partikel pertama yang hancur. Setelah semua partikel yang hancur berada di akhir daftar, kita menonaktifkannya dengan mengatur variabel Count daftar ke jumlah partikel aktif. Partikel yang hancur akan tetap berada di larik yang mendasari, tetapi tidak akan diperbarui atau digambar.

ParticleManager.Update() menangani pembaruan setiap partikel dan menghapus partikel yang hancur dari daftar.

Hal terakhir yang harus diterapkan dalam ParticleManager adalah menggambar partikel.

The ParticleState Struct

Hal berikutnya yang harus dilakukan adalah membuat kelas atau struct khusus untuk menyesuaikan bagaimana partikel akan terlihat di Shape Blaster. Akan ada beberapa jenis partikel yang berbeda dalam Shape Blaster yang berperilaku sedikit berbeda, jadi kita akan mulai dengan membuat enum untuk tipe partikel. Kita juga membutuhkan variabel untuk kecepatan dan panjang awal partikel.

Sekarang kita siap untuk menulis metode pembaruan partikel. Ini adalah ide yang baik untuk membuat metode ini cepat karena mungkin harus dipanggil untuk sejumlah besar partikel.

Kita akan mulai sederhana. Tambahkan metode berikut ke ParticleState.

Enemy Explosions

Kita akan kembali dan memperbaiki metode ini sebentar lagi. Pertama, mari kita buat beberapa efek partikel sehingga kita benar-benar dapat menguji perubahan kita. Di GameRoot, deklarasikan ParticleManager baru dan panggil metode Update() dan Draw().

Juga, deklarasikan Texture2D baru yang disebut LineParticle untuk tekstur partikel di kelas Seni, dan muat tekstur seperti yang kita lakukan untuk sprite lainnya.

Sekarang mari kita membuat musuh meledak. Ubah metode Enemy.WasShot() sebagai berikut.

Ini menciptakan 120 partikel yang akan menembak keluar dengan kecepatan yang berbeda di semua arah. Kecepatan acak tertimbang sedemikian rupa sehingga partikel lebih mungkin melakukan perjalanan dekat kecepatan maksimum. Ini akan menyebabkan lebih banyak partikel berada di tepi ledakan saat mengembang. Partikel terakhir 190 frame, atau hanya lebih dari tiga detik.

Anda sekarang dapat menjalankan game dan menyaksikan musuh meledak. Namun, masih ada beberapa perbaikan yang harus dilakukan untuk efek partikel.

Masalah pertama adalah partikel menghilang tiba-tiba begitu durasi mereka habis. Akan lebih baik jika mereka lancar menghilang. Tapi mari kita melangkah lebih jauh dari ini dan membuat partikel bersinar lebih terang ketika mereka bergerak cepat. Juga, terlihat bagus jika kita memperpanjang partikel yang bergerak cepat dan mempersingkat gerakan lambat.

Ubah metode ParticleState.UpdateParticle() sebagai berikut (perubahan disorot).

Ledakannya terlihat jauh lebih baik sekarang, tetapi semuanya memiliki warna yang sama. Kita dapat memberi mereka lebih banyak variasi dengan memilih warna acak. Salah satu metode menghasilkan warna acak adalah dengan memilih komponen merah, biru dan hijau secara acak, tetapi ini akan menghasilkan banyak warna kusam dan kita ingin partikel memiliki penampilan lampu neon. Kita dapat memiliki lebih banyak kendali atas warna-warna kita dengan menentukannya di ruang warna HSV. HSV berarti hue, saturation, dan value. Kita ingin memilih warna dengan warna acak tetapi saturasi dan nilai tetap. Kita membutuhkan fungsi pembantu yang dapat menghasilkan warna dari nilai-nilai HSV.

Sekarang kita dapat memodifikasi Enemy.WasShot() untuk menggunakan warna acak. Untuk membuat warna ledakan kurang monoton, kita akan memilih dua warna kunci terdekat untuk setiap ledakan dan secara linear interpolasi antara mereka dengan jumlah acak untuk setiap partikel.

Ledakan akan terlihat seperti animasi di bawah ini.

Enemy Explosion

Anda dapat bermain-main dengan generasi warna sesuai preferensi Anda. Teknik alternatif yang berfungsi baik adalah dengan memilih sejumlah pola warna untuk ledakan dan memilih secara acak di antara skema warna yang Anda pilih sebelumnya.

Ledakan Peluru

Kita juga bisa membuat peluru meledak ketika mereka mencapai tepi layar. Kita pada dasarnya akan melakukan hal yang sama yang dilakukan untuk ledakan musuh.

Tambahkan anggota Random statis ke kelas Bullet.

Kemudian, ubah Bullet.Update() sebagai berikut.

Anda mungkin memperhatikan bahwa memberikan partikel arah acak adalah sia-sia, karena paling tidak separuh partikel akan langsung menuju ke luar layar (lebih banyak lagi jika peluru meledak di sudut). Kita bisa melakukan beberapa pekerjaan tambahan untuk memastikan partikel hanya diberi kecepatan yang berlawanan dengan dinding yang mereka hadapi. Sebaliknya, kita akan mengambil petunjuk dari Geometry Wars dan membuat semua partikel terpental dari dinding. Setiap partikel yang menuju ke luar layar akan dipantulkan kembali.

Tambahkan baris berikut ke ParticleState.UpdateParticle() di mana saja antara baris pertama dan terakhir.

Ledakan Kapal Pemain

Kita akan membuat ledakan yang sangat besar ketika pemain itu terbunuh. Ubah PlayerShip.Kill() seperti ini:

Ini mirip dengan ledakan musuh, tetapi kita menggunakan lebih banyak partikel dan selalu menggunakan skema warna yang sama. Jenis partikel juga diatur ke ParticleType.None.

Dalam demo, partikel-partikel dari ledakan musuh melambat lebih cepat daripada partikel-partikel dari kapal pemain yang meledak. Ini membuat ledakan pemain bertahan lebih lama dan terlihat sedikit lebih epik.


Lubang Hitam Revisited

Sekarang kita memiliki efek partikel, mari kita kembali ke lubang hitam dan membuat mereka berinteraksi dengan partikel.

Efek pada Partikel

Lubang hitam harus mempengaruhi partikel selain entitas lain, jadi kita perlu mengubah ParticleState.UpdateParticle(). Tambahkan baris berikut.

Di sini, n adalah vektor satuan yang menunjuk ke arah lubang hitam. Gaya yang menarik adalah versi modifikasi dari fungsi kuadrat terbalik. Modifikasi pertama adalah penyebut adalah \(distance^ 2 + 10.000 \). Hal ini menyebabkan daya tarik untuk mendekati nilai maksimum daripada cenderung menuju tak terbatas karena jaraknya menjadi sangat kecil. Ketika jaraknya jauh lebih besar dari 100 piksel, \(distance^ 2 \) menjadi jauh lebih besar dari 10.000. Oleh karena itu, menambahkan 10.000 ke \(distance^ 2 \) memiliki efek yang sangat kecil, dan fungsi mendekati fungsi kuadrat invers normal. Namun, ketika jaraknya jauh lebih kecil dari 100 piksel, jarak memiliki efek kecil pada nilai penyebut, dan persamaannya menjadi kurang lebih sama dengan:

Modifikasi kedua adalah menambahkan komponen menyamping ke kecepatan ketika partikel cukup dekat ke lubang hitam. Ini melayani dua tujuan. Pertama, itu membuat partikel berputar searah jarum jam menuju lubang hitam. Kedua, ketika partikel cukup dekat, mereka akan mencapai kesetimbangan dan membentuk lingkaran bercahaya di sekitar lubang hitam.

Tip: Untuk memutar vektor, V, 90° searah jarum jam, ambil (V.Y, -V.X). Demikian pula, untuk memutar 90 ° berlawanan arah jarum jam, ambil (-V.Y, V.X).

Memproduksi Partikel

Lubang hitam akan menghasilkan dua jenis partikel. Pertama, mereka secara berkala akan menyemprotkan partikel yang akan mengorbit di sekitar mereka. Kedua, ketika sebuah lubang hitam ditembak, ia akan menyemprotkan partikel khusus yang tidak terpengaruh oleh gravitasinya.

Tambahkan kode berikut ke metode BlackHole.Was Shot().

Ini kebanyakan bekerja dengan cara yang sama seperti ledakan partikel lainnya. Satu perbedaan adalah kita memilih warna berdasarkan waktu permainan total yang telah berlalu. Jika Anda menembak lubang hitam beberapa kali secara berurutan, Anda akan melihat rona ledakan berangsur-angsur berotasi. Ini terlihat kurang berantakan daripada menggunakan warna acak sementara masih memungkinkan variasi.

Untuk semprotan partikel yang mengorbit, kita perlu menambahkan variabel ke kelas BlackHole untuk melacak arah di mana kita saat ini menyemprotkan partikel.

Sekarang tambahkan berikut ke metode BlackHole.Update().

Ini akan menyebabkan lubang hitam menyemburkan partikel ungu yang akan membentuk cincin berpendar dingin yang mengorbit di sekitar lubang hitam, seperti:


Pembuangan Kebakaran Kapal

Sebagaimana ditentukan oleh hukum fisika geometrik-neon, kapal pemain mendorong dirinya sendiri dengan mengalirkan aliran partikel api keluar dari pipa knalpotnya. Dengan mesin partikel kami di tempat, efek ini mudah dibuat dan menambahkan bakat visual ke pergerakan kapal.

Ketika kapal bergerak, kita membuat tiga aliran partikel: aliran pusat yang memancar langsung ke bagian belakang kapal, dan dua aliran sisi yang sudutnya berputar maju mundur relatif terhadap kapal. Kedua sisi sungai berputar ke arah yang berlawanan untuk membuat pola berselang-seling. Aliran samping memiliki warna yang lebih merah, sedangkan aliran tengah memiliki warna yang lebih panas, kuning-putih. Animasi di bawah ini menunjukkan efeknya.

ShapeBlaster Exhaust FireShapeBlaster Exhaust FireShapeBlaster Exhaust Fire

Untuk membuat api bersinar lebih terang daripada dari mekar saja, kita akan memiliki kapal memancarkan partikel tambahan yang terlihat seperti ini:

Glow Particle

Partikel-partikel ini akan diwarnai dan dicampur dengan partikel biasa. Kode untuk seluruh efek ditunjukkan di bawah ini.

Tidak ada yang licik dalam kode ini. Kita menggunakan fungsi sinus untuk menghasilkan efek swiveling di aliran samping dengan memvariasikan kecepatan menyamping mereka dari waktu ke waktu. Untuk setiap aliran, kami membuat dua partikel tumpang tindih per frame: satu LineParticle semitransparan-putih dan partikel cahaya berwarna di belakangnya. Hubungi MakeExhaustFire() di akhir PlayerShip.Update(), segera sebelum mengatur kecepatan kapal ke nol.


Kesimpulan

Dengan semua efek partikel ini, Shape Blaster mulai terlihat cukup keren. Di bagian akhir seri ini, kita akan menambahkan satu lagi efek yang mengagumkan: grid background warping.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Game Development tutorials. Never miss out on learning about the next big thing.
Advertisement
Scroll to top
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.