Students Save 30%! Learn & create with unlimited courses & creative assets Students Save 30%! Save Now
Advertisement
  1. Game Development
  2. Game Engine Development
Gamedevelopment

Bagaimana Mengimplementasikan dan Menggunakan Antrian Pesan di Game Anda.

by
Difficulty:IntermediateLength:LongLanguages:

Indonesian (Bahasa Indonesia) translation by Kaso Toluppa (you can also view the original English article)

Sebuah permainan biasanya dibuat dari beberapa entitas yang berbeda yang berinteraksi satu sama lain. Interaksi tersebut cenderung sangat dinamis dan sangat terkait dengan gameplay.  Tutorial ini mencakup konsep dan implementasi sistem antrian pesan yang dapat menyatukan interaksi entitas, membuat kode anda mudah dikelola dan mudah dipelihara karena tumbuh dalam kompleksitas.  

Pengantar

Bom bisa berinteraksi dengan karakter dengan meledak dan menyebabkan kerusakan, sebuah alat medis dapat menyembuhkan suatu entitas, sebuah kunci bisa membuka pintu, dan seterusnya.  Interaksi dalam permainan tidak terbatas, tapi bagaimana kita bisa menjaga kode permainan tetap terkendali saat masih bisa menangani semua interaksi itu? Bagaimana kita memastikan kodenya dapat berubah dan terus bekerja saat interaksi baru dan tak terduga muncul?

Interactions in a game tend to grow in complexity very quickly
Interaksi dalam permainan cenderung tumbuh dalam kompleksitas dengan sangat cepat.

Seiring interaksi ditambahkan (terutama yang tak terduga), kode anda akan terlihat lebih dan lebih berantakan. Implementasi yang naif akan segera membawa anda mengajukan pertanyaan seperti:

"Ini adalah entitas A, jadi saya harus memanggil metode damage() di atasnya kan? Atau itu damageByItem ()? Mungkin DamageByWeapon () ini merupakan metode yang tepat? "

Bayangkan bahwa kekacauan kekacauan menyebar ke semua entitas permainan Anda, karena mereka semua berinteraksi satu sama lain dengan cara yang berbeda dan aneh. Untungnya, ada cara yang lebih baik, sederhana, dan lebih mudah dikelola untuk melakukannya.

Antrian Pesan

Masukkan message queue (antrian pesan) . Ide dasar dibalik konsep ini adalah menerapkan semua interaksi game sebagai sistem komunikasi (yang masih bisa digunakan saat ini): pertukaran pesan.  Orang telah berkomunikasi melalui pesan (surat) selama berabad-abad karena ini adalah sistem yang efektif dan sederhana.

Dalam layanan pos dunia nyata kita, isi setiap pesan bisa berbeda, namun cara mereka dikirim dan diterima secara fisik tetap sama.  Seorang pengirim memasukkan informasinya ke dalam amplop dan mengirimkannya ke tujuan. Tujuan dapat menjawab (atau tidak) dengan mengikuti mekanisme yang sama, cukup ganti bidang "dari / ke" pada amplop.   

Interactions made using a message queue system
Interaksi dilakukan dengan menggunakan sistem antrian pesan.

Dengan menerapkan gagasan itu pada permainan Anda, semua interaksi antar entitas dapat dilihat sebagai pesan. Jika sebuah entitas game ingin berinteraksi dengan yang lain (atau kelompoknya), yang harus dilakukan hanyalah mengirim pesan.  Tujuan akan menangani atau bereaksi terhadap pesan berdasarkan isinya dan siapa pengirimnya.

Dalam pendekatan ini, komunikasi antar entitas game menjadi terpadu. Semua entitas dapat mengirim dan menerima pesan. Tidak peduli seberapa kompleks atau anehnya interaksi atau pesannya, saluran komunikasi selalu tetap sama.

Pada bagian selanjutnya, saya akan menjelaskan pada anda bagaimana caranya menerapkan pendekatan antrian pesan pada permainan anda.

Merancang Amplop (Pesan)

Mari kita mulai dengan merancang amplop, yang merupakan elemen paling mendasar dalam sistem antrian pesan.   

Amplop bisa digambarkan seperti pada gambar di bawah ini:  

Structure of a message
Struktur Pesan

Dua bidang pertama (sender dan destination) adalah referensi ke entitas yang dibuat dan entitas yang akan menerima pesan ini. Dengan menggunakan bidang-bidang itu, baik pengirim maupun penerima dapat mengetahui dari mana pesan tersebut akan dikirim dan dari mana asalnya.

Dua bidang lainnya (Type dan Data) bekerja sama untuk memastikan pesan ditangani dengan benar. Bagian Type  menggambarkan apa pesan ini; misalnya, jika tipe ini   "damage", penerima akan menangani pesan ini sebagai perintah untuk mengurangi poin kesehatan; jika tipenya adalah  "pursue", penerima akan menganggapnya sebagai instruksi untuk mengejar sesuatu - dan seterusnya.

Bagian data terhubung langsung dengan bidang type. Seperti  contoh sebelumnya, jika tipe pesannya adalah   "damage", maka bidang data akan berisi angka-katakan,   10-yang menggambarkan jumlah kerusakan yang harus diaplikasikan pada poin kesehatan.  Jika jenis pesannya adalah   "pursue",   data akan berisi objek yang menggambarkan target yang harus diupayakan.

Bidang data dapat berisi informasi apapun, yang menjadikan amplop sarana komunikasi yang serbaguna. Apa pun dapat ditempatkan di bidang itu: bilangan bulat, pelampung, senar, dan bahkan benda lainnya.  Aturan praktisnya adalah bahwa penerima harus tahu apa yang ada di bidang data berdasarkan apa yang ada di bidang type.

Semua teori tersebut dapat diterjemahkan dalam kelas yang sangat sederha bernama Message . Ini mengandung empat properti. Satu untuk setiap bidang.

Sebagai contoh penggunaan ini, jika suatu entitas A ingin mengirim sebuah pesan  "damage" ke entitas B, hal yang harus dilakukan adalah melakukan instantiate objek kelas  Message, setel properti  untuk  B, atur properti dari dirinya sendiri (entity  A),  atur type untuk "damage" dan terakhir, atur data ke beberapa nomor (10, misalnya):

Sekarang kita punya cara untuk membuat pesan, sekarang saatnya memikirkan kelas yang akan menyimpan dan mengantarkannya.

Menerapkan Antrian

Kelas yang bertanggung jawab untuk menyimpan dan menyampaikan pesan akan dipanggil sebagai MessageQueue (antrian pesan).  Ini akan bekerja sebagai kantor pos: semua pesan diserahkan ke kelas ini, yang memastikan mereka akan dikirim ke tempat tujuan mereka.

Untuk saat ini, kelas MessageQueue akan memiliki struktur yang sangat sederhana:

Properti   messages   adalah sebuah array.  Ini akan menyimpan semua pesan yang akan dikirimkan oleh MessageQueue.    Metode add()  menerima objek kelas Message  sebagai parameter, dan menambahkan objek itu ke dalam daftar pesan.  

Begini cara contoh entitas A kita sebelumnya mengirim pesan pada entitas B tentang kerusakan yang akan bekerja dengan menggunakan kelas MessageQueue:

Sekaranf kita memiliki cara membuat dan menyimpan pesan dalam antiran (quenue). Sekarang waktunya membuat mereka mencapai tujuannya.

Mengirim Pesan

Untuk membuat kelas  MessageQueue  sebenarnya  kirimkan pesan yang diposting, pertama kita perlu mendefinisikannya   bagaimana entitas akan menangani dan menerima pesan. Cara termudah adalah dengan menambahkan metode yang dinamai  onMessage () untuk setiap entitas yang dapat menerima pesan:

Kelas MessageQueue akan memanggil metode   onMessage ()   dari masing-masing entitas yang harus menerima pesan. Parameter yang dilewatkan ke metode tersebut adalah pesan yang disampaikan oleh sistem antrian (dan diterima oleh tujuan).  

Kelas MessageQueue akan mengirimkan pesan ke antreannya sekaligus, di metode dispatch():

Metode ini mengulai  semua pesan dalam antrian dan, untuk setiap pesan,    bidang to yang digunakan untuk mengambil referensi ke penerima.  Metode  onMessage () penerima kemudian dipanggil, dengan pesan saat ini sebagai parameter, dan pesan yang disampaikan kemudian dihapus dari daftar  MessageQueue. Proses ini diulang sampai semua pesan dikirim.

Menggunakan Antrian Pesan

Saatnya untuk melihat semua rincian pelaksanaan ini bekerja sama. Mari kita gunakan sistem antrian pesan kita dalam sebuah demo yang sangat sederhana yang terdiri dari beberapa entitas bergerak yang saling berinteraksi satu sama lain. Agar sederhana, kita akan bekerja dengan tiga entitas: Healer (penyembuh), Runner (pelari) dan Hunter (pemburu).

Runner memiliki bar kesehatan dan bergerak secara acak. Healer akan menyembuhkan setiap Runner yang lewat didekatnya; di sisi lain, Hunter akan menimbulkan kerusakan di tempat terdekat dari Runner. Semua interaksi akan ditangani dengan menggunakan sistem antrian pesan.

Menambahkan Antrian Pesan

Mari kita mulai dengan membuat PlayState yang berisi daftar entitas (healer, runner, dan hunter) dan sebuah instance dari kelas MessageQueue:

Dalam lingkaran permainan (game loop), diwakili oleh metode update(), antrian pesan dari metode dispatch() dipanggil, jadi semua pesan dikirim di akhir setiap frame permainan.

Menambahkan Runner

Kelas Runner memiliki struktur sebagai berikut:

Bagian yang paling penting adalah metode onMessage() yang dipanggil oleh antrian pesan setiap kali ada pesan baru untuk contoh ini. Seperti yang sudah dijelaskan sebelumnya, bidang type dalam pesan tersebut digunakan untuk memutuskan apa komunikasi ini.

Berdasarkan jenis pesannya, tindakan yang benar dilakukan: jika tipe pesannya adalah "damage", titik kesehatan menurun; jika tipe pesannya adalah "heal", poin kesehatan meningkat. Jumlah poin kesehatan yang meningkat atau menurun ditentukan oleh pengirim di bidang pesan data.

Dalam PlayState, kami menambahkan beberapa runner ke daftar entitas:

Hasilnya adalah empat pelari bergerak secara acak.:

Menambahkan Hunter (pemburu)

Kelas Hunter mengikuti struktur sebagai berikut:

Hunter juga akan bergerak, tapi akan menyebabkan kerusakan pada semua pelari yang mendekat. Perilaku ini diterapkan di metode update(), di mana semua entitas permainan diperiksa dan pelari diberi pesan tentang kerusakan.

Pesan kerusakan dibuat sebagai berikut:

Pesan berisi informasi tentang tujuan (entitas, dalam kasus ini, yang merupakan entitas yang dianalisis dalam iterasi saat ini), pengirim (ini, yang mewakili hunter yang melakukan serangan tersebut), jenis pesannya (" damage ") dan jumlah damage / kerusakan (2, dalam hal ini, ditugaskan ke bidang pesan data).

Pesan tersebut kemudian diposting ke tujuan melalui perintah this.getMessageQueue () menambahkan (msg), yang menambahkan pesan yang baru dibuat ke antrian pesan.

Akhirnya, kita tambahkan Hunter ke daftar entitas di PlayState:

Hasilnya adalah beberapa runner bergerak, menerima pesan dari hunter saat mereka saling berdekatan:

Saya menambahkan amplop terbang sebagai bantuan visual untuk membantu menunjukkan apa yang sedang terjadi.

Menambakan Healer (Penyembuh)

Kelas Healer memiliki struktrur sebagai berikut:

Kode dan strukturnya sangat mirip dengan kelas Hunter, kecuali beberapa perbedaan. Sama halnya dengan hunter yang diimplementasikan, metode update() healer diualang atas daftar entitas dalam permainan, pesan setiap entitas dalam jangkauan penyembuhannya:

Pesan ini juga memiliki tujuan (entitas), pengirim (ini, penyembuh yang melakukan aksinya), jenis pesan ("heal / penyembuhan") dan jumlah titik penyembuhan (2, yang ditugaskan di bidang pesan data).

Kami menambahkan healer ke daftar entitas di PlayState cara yang sama dengan hunter kita dan hasilnya adalah adegan dengan runner, hunter dan healer:

Dan itu dia! Kita memiliki tiga entitas yang berbeda yang berinteraksi satu sama lain dengan bertukar pesan.

Diskusi Mengenai Fleksibilitas

Sistem antrian pesan ini merupakan cara serbaguna untuk mengelola interaksi dalam sebuah game. Interaksi dilakukan melalui saluran komunikasi yang bersatu dan memiliki satu antarmuka yang mudah digunakan dan diimplementasikan.

Seiring bertambahnya permainan anda berada dalam kompleksitas, interaksi baru mungkin dibutuhkan. Beberapa dari mereka mungkin benar-benar tak terduga, jadi anda harus menyesuaikan kode anda untuk menghadapinya. Jika anda menggunakan sistem antrian pesan, masalah ada pada menambahkan pesan baru di suatu tempat dan menanganinya di tempat lain.

Misalnya, bayangkan Anda ingin membuat hunter berinteraksi dengan healer; Anda hanya perlu membuat hunter mengirim pesan dengan interaksi baru-misalnya, "flee" - dan pastikan bahwa healer bisa mengatasinya di metode onMessage:

Mengapa Tidak Mengirim Pesan secara Langsung?

Meski bertukar pesan antar entitas bisa bermanfaat, anda mungkin berpikir mengapa MessageQueue sangat dibutuhkan. Tidak bisakah anda memanggil receiver itu? Metode onMessage() sendiri tidak mengandalkan pada MessageQueue, seperti pada kode di bawah ini?

Anda pasti bisa menerapkan sistem pesan seperti itu, tapi penggunaan sebuah MessageQueue memiliki beberapa keuntungan.

Misalnya, dengan memusatkan pengiriman pesan, anda dapat menerapkan beberapa fitur keren seperti pesan tertunda, kemampuan untuk memberi pesan pada sekelompok entitas, dan informasi debug visual (seperti amplop terbang yang digunakan dalam tutorial ini).

Ada ruang untuk kreativitas di kelas MessageQueue, terserah pada anda dan persyaratan permainan anda.

Kesimpulan

Menangani interaksi antara entitas permainan menggunakan sistem antrian pesan adalah cara agar kode anda tetap teratur dan siap dimasa depan. Interaksi baru dapat dengan mudah dan cepat ditambahkan, bahkan gagasan anda yang paling rumit sekalipun, selama mereka dienkapsulasi sebagai pesan.

Seperti yang dibahas dalam tutorial, anda bisa mengabaikan penggunaan antrian pesan utama dan hanya mengirim pesan langsung ke entitas. Anda juga bisa memusatkan komunikasi menggunakan pengiriman (kelas MessageQueue dalam kasus kita) untuk memberi ruang bagi fitur baru di masa depan, seperti pesan tertunda.

Saya harap Anda menemukan pendekatan ini berguna dan menambahkannya ke sabuk utilitas pengembang game Anda. Metode ini mungkin tampak berlebihan untuk proyek kecil, namun pastinya akan membuat Anda sedikit sakit kepala dalam jangka panjang untuk permainan yang lebih besar.

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.