Advertisement
  1. Game Development
  2. Game Engine Development
Gamedevelopment

Bagaimana Melaksanakan dan Menggunakan Mesej Dihantar dalam Permainan Anda.

by
Difficulty:IntermediateLength:LongLanguages:

Malay (Melayu) translation by Urwah bin Azzubair (you can also view the original English article)

Permainan biasanya dibuat dari beberapa entiti yang berbeza yang berinteraksi antara satu sama lain. Interaksi tersebut cenderung sangat dinamik dan sangat berkaitan dengan permainan.  Tutorial ini merangkumi konsep dan pelaksanaan sistem antrian mesej yang boleh menyatukan interaksi entiti, menjadikan kod anda mudah diurus dan mudah dikekalkan kerana ia semakin rumit. 

Pengenalan

Bom boleh berinteraksi dengan aksara dengan meletup dan menyebabkan kerosakan, peranti perubatan boleh menyembuhkan entiti, kunci boleh membuka pintu, dan sebagainya.  Interaksi dalam permainan tidak terhad, tetapi bagaimana kita dapat mengekalkan kod permainan dalam kawalan sementara masih menangani semua interaksi itu? Bagaimanakah kita memastikan kod itu berubah dan terus berfungsi apabila interaksi baru dan tidak dijangka muncul?

Interactions in a game tend to grow in complexity very quickly
Interaksi dalam permainan cenderung berkembang dengan kerumitan dengan cepat.

Apabila interaksi ditambah (terutama yang tidak dijangka), kod anda akan kelihatan lebih dan lebih berantakan. Pelaksanaan yang naif akan mendorong anda untuk bertanya soalan seperti:

"Ini entiti A, jadi saya perlu memanggil kaedah damage() di atasnya dengan betul? Atau itu damageByItem () ? Mungkin DamageByWeapon () adalah kaedah yang betul?" 

Bayangkan kekacauan kekacauan merebak ke semua entiti permainan anda, kerana mereka semua berinteraksi antara satu sama lain dengan cara yang berbeza dan pelik. Nasib baik, ada cara yang lebih baik, mudah, dan lebih mudah diurus untuk melakukannya.

Perbaruan Mesej

Masukkan antrian mesej (mesej gilir). Idea asas di sebalik konsep ini adalah untuk menerapkan semua interaksi permainan sebagai sistem komunikasi (yang masih boleh digunakan hari ini): pertukaran mesej.  Orang telah berkomunikasi melalui mesej (surat) selama berabad-abad kerana ini adalah sistem yang berkesan dan mudah.

Di dalam perkhidmatan pos dunia kami, kandungan setiap mesej boleh berbeza, tetapi cara mereka dihantar dan diterima secara fizikal tetap sama.  Seorang pengirim memasuki maklumat tersebut ke dalam sampul surat dan menghantarnya ke destinasi. Objektif dapat menjawab (atau tidak) dengan mengikuti mekanisme yang sama, cukup ganti bidang "dari / ke" pada sampul surat.

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

Dengan menggunakan idea itu untuk permainan anda, semua interaksi antara entiti boleh dilihat sebagai mesej. Jika entiti permainan mahu berinteraksi dengan orang lain (atau kumpulan), yang perlu anda lakukan ialah menghantar mesej.  Matlamat akan mengendalikan atau bertindak balas terhadap mesej berdasarkan kandungan mereka dan siapa penghantarnya.

Dalam pendekatan ini, komunikasi antara entiti permainan menjadi bersepadu.Semua entiti boleh menghantar dan menerima mesej. Tidak kira bagaimana kompleks atau ganjil interaksi atau mesej itu, saluran komunikasi sentiasa tetap sama.

Di bahagian seterusnya, saya akan menerangkan kepada anda bagaimana untuk melaksanakan pendekatan antrian mesej dalam permainan anda.

Merancang Sampul Surat (Mesej)

Mari kita mulakan dengan merancang sampul surat, yang merupakan elemen paling asas dalam sistem antrian mesej.

Sampul surat dapat digambarkan seperti dalam gambar di bawah:

Structure of a message
Struktur Mesej

Dua bidang pertama ( sender dan destination ) adalah rujukan kepada entiti yang dicipta dan entiti yang akan menerima mesej ini. Dengan menggunakan bidang ini, kedua-dua penghantar dan penerima boleh mengetahui di mana mesej akan dihantar dan dari mana ia datang.

Dua bidang lain ( Type dan Data ) berfungsi bersama untuk memastikan mesej dikendalikan dengan betul. Seksyen Type menerangkan mesej ini; sebagai contoh, jika jenis "damage" , penerima akan mengendalikan mesej ini sebagai arahan untuk mengurangkan titik kesihatan; jika jenis "pursue" , penerima akan menganggapnya sebagai arahan untuk mengejar sesuatu - dan sebagainya.

Bahagian data disambungkan terus ke medan type . Seperti pada contoh terdahulu, jika jenis mesej adalah "damage" , medan data akan mengandungi sebutan, 10 - yang menerangkan jumlah kerosakan yang harus digunakan pada titik kesihatan.  Jika jenis mesej "pursue" , data akan mengandungi objek yang menggambarkan target yang hendak dicuba.

Medan data boleh mengandungi sebarang maklumat, yang menjadikan sampul surat cara komunikasi yang serba guna. Apa-apa pun boleh diletakkan di dalam medan tersebut: bilangan bulat, pelampung, tali, dan benda lain.  Peraturan praktikal adalah bahawa penerima mesti mengetahui apa yang ada dalam medan data berdasarkan apa yang ada di medan type .

Semua teori ini boleh diterjemahkan ke dalam kelas yang sangat mudah dikenali sebagai Message . Ia mengandungi empat sifat. Satu untuk setiap bidang.

Sebagai contoh penggunaan ini, jika entiti mahu menghantar mesej "damage" kepada entiti , perkara yang perlu dilakukan ialah memberi instantiate objek kelas Message , tetapkan harta untuk , tetapkan harta itu sendiri (entiti ), tetapkan type kepada "damage" dan akhirnya, tetapkan data ke beberapa nombor ( 10 , sebagai contoh):

Sekarang kita mempunyai cara untuk membuat mesej, sudah tiba masanya untuk memikirkan kelas yang akan menyimpan dan menyampaikannya.

Melaksanakan Antrian

Kelas yang bertanggungjawab untuk menyimpan dan menyampaikan mesej akan dipanggil sebagai MessageQueue (mesej antrian). Ini akan berfungsi sebagai pejabat pos: semua mesej dihantar ke kelas ini, yang memastikan mereka akan dihantar ke destinasi mereka.

Buat masa ini, kelas MessageQueue akan mempunyai struktur yang sangat mudah:

Ciri-ciri messages adalah array. Ini akan menyimpan semua mesej yang akan dihantar oleh MessageQueue . Kaedah add() menerima objek kelas Message sebagai parameter, dan menambah objek tersebut pada senarai mesej.

Begini bagaimana contoh entiti kita sebelum ini menghantar mesej pada entiti tentang kerosakan yang akan berfungsi menggunakan kelas MessageQueue :

Sekarang kita mempunyai cara untuk membuat dan menyimpan mesej dalam barisan. Sekarang adalah masa untuk mendapatkan mereka untuk mencapai matlamat mereka.

Menghantar Mesej

Untuk menjadikan kelas MessageQueue benar-benar menghantar mesej yang disiarkan, pertama kita perlu menentukan bagaimana entiti akan mengendalikan dan menerima mesej tersebut. Cara paling mudah adalah dengan menambah kaedah yang dinamakan onMessage () kepada mana-mana entiti yang boleh menerima mesej:

Kelas MessageQueue akan memanggil kaedah onMessage () pada setiap entiti yang seharusnya menerima mesej tersebut. Parameter yang diberikan kepada kaedah adalah mesej yang dihantar oleh sistem antrian (dan diterima oleh destinasi).

Kelas MessageQueue akan menghantar mesej kepada giliran sekaligus, dalam kaedah dispatch() :

Kaedah ini memulakan semua mesej dalam baris gilir dan, bagi setiap mesej, field to-digunakan untuk mendapatkan rujukan kepada penerima.  Kaedah onMessage () penerima kemudian dilancarkan, dengan mesej semasa sebagai parameter, dan mesej kemudian dipadamkan dari senarai MessageQueue . Proses ini diulang sehingga semua mesej dihantar.

Menggunakan Mesej Dihantar

Sudah tiba masanya untuk melihat semua butiran pelaksanaan ini bekerjasama.Mari gunakan sistem antrian mesej kami dalam demo yang sangat mudah yang terdiri daripada beberapa entiti mudah alih yang berinteraksi antara satu sama lain.  Untuk menjadi mudah, kami akan bekerjasama dengan tiga entiti: Healer Runner dan Hunter .

Runner mempunyai bar kesihatan dan bergerak secara rawak. Healer akan menyembuhkan setiap Runner berlalu berdekatan; Sebaliknya, Hunter akan menimbulkan kerosakan di tempat yang paling dekat dengan Runner . Semua interaksi akan dikendalikan menggunakan sistem antrian mesej.

Tambah Mesej Dihantar

Mari kita mulakan dengan membuat PlayState yang menyenaraikan entiti (penyembuh, pelari, dan pemburu) dan contoh kelas MessageQueue :

Dalam gelung permainan, diwakili oleh kaedah update() , barisan pesanan dari kaedah dispatch() dipanggil, supaya semua mesej dihantar pada akhir setiap bingkai permainan.

Ditambah Runner

Kelas Runner mempunyai struktur berikut:

Bahagian yang paling penting ialah kaedah onMessage() yang dipanggil oleh gilir mesej apabila terdapat mesej baru untuk contoh ini. Seperti yang disebutkan sebelumnya, bidang type dalam mesej digunakan untuk menentukan komunikasi ini.

Berdasarkan jenis mesej, tindakan yang betul diambil: jika jenis mesej adalah "damage" , titik kesihatan berkurangan; jika jenis mesej "heal" , kenaikan nilai kesihatan. Bilangan titik kesihatan meningkat atau berkurang ditentukan oleh penghantar dalam bidang mesej data .

Di PlayState , kami menambah beberapa pelari ke senarai entiti:

Hasilnya adalah empat pelari bergerak secara rawak:

Tambah pemburu (pemburu)

Kelas Hunter mengikut struktur berikut:

Hunter juga akan bergerak, tetapi akan menyebabkan kerosakan kepada semua pelari yang menghampiri. Tingkah laku ini diterapkan dalam kaedah update() , di mana semua entiti permainan diperiksa dan pelari diberi mesej tentang kerosakan.

Mesej kerosakan dibuat seperti berikut:

Mesej ini mengandungi maklumat mengenai destinasi ( entitas , dalam kes ini, yang merupakan entiti yang dianalisis dalam lelaran semasa), penghantar ( ini mewakili pemburu yang melakukan serangan itu), jenis mesej ( " damage " )dan kerosakan / kerosakan , (2, dalam kes ini, diberikan kepada bidang mesej data ).

Mesej tersebut kemudian diposkan ke destinasi melalui this.getMessageQueue () menambahkan (msg) , yang menambah mesej yang baru dibuat ke barisan mesej.

Akhir sekali, kami menambah Hunter ke senarai entiti di PlayState :

Hasilnya adalah beberapa pelari yang bergerak, menerima mesej dari pemburu ketika mereka rapat bersama:

Saya menambah sampul surat terbang sebagai bantuan visual untuk membantu menunjukkan apa yang sedang berlaku.

Craving Healer (Healer)

Kelas Healer mempunyai struktur berikut:

Kod dan strukturnya sangat serupa dengan kelas Hunter , kecuali beberapa perbezaan. Sama dengan pemburu yang telah dilaksanakan, kaedah pembaruan update() penyembuh digunakan untuk senarai entiti dalam permainan, mesej setiap entiti dalam julat penyembuhannya:

Mesej ini juga mempunyai objektif ( entitas ), pengirim ( ini , penyembuh melakukan tindakan), jenis mesej (" heal / penyembuhan") dan jumlah titik penyembuhan ( , yang diberikan dalam bidang mesej data ).

Kami menambah healer kepada senarai entiti di PlayState dengan cara yang sama seperti hunter kami dan hasilnya adalah adegan dengan pelari, pemburu dan penyembuh:

Dan itu sahaja! Kami mempunyai tiga entiti berbeza yang berinteraksi antara satu sama lain dengan menukar mesej. 

Perbincangan Mengenai Fleksibiliti

Sistem antrian mesej ini adalah cara serba boleh untuk menguruskan interaksi dalam permainan. Interaksi dilakukan melalui saluran komunikasi bersatu dan mempunyai antara muka yang mudah digunakan dan dilaksanakan.

Memandangkan permainan anda berkembang dengan kerumitan, interaksi baru mungkin diperlukan. Sesetengah daripada mereka mungkin benar-benar tidak dijangka, jadi anda perlu menyesuaikan kod anda untuk menanganinya.  Jika anda menggunakan sistem antrian mesej, masalahnya adalah untuk menambah mesej baru di suatu tempat dan mengendalikannya di tempat lain.

Sebagai contoh, bayangkan anda ingin membuat hunter berinteraksi dengan healer ; Anda hanya perlu membuat hunter menghantar mesej dengan interaksi baru-contohnya, "flee" - dan memastikan bahawa healer boleh mengendalikannya dalam kaedah onMessage :

Mengapa Tidak Hantar Mesej Secara Terus?

Semasa bertukar-tukar mesej antara entiti boleh berguna, anda mungkin berfikir mengapa MessageQueue diperlukan. Tidakkah anda memanggil penerima?Kaedah onMessage() sendiri tidak bergantung kepada MessageQueue , seperti dalam kod di bawah?

Anda pasti dapat melaksanakan sistem pesanan seperti itu, tetapi penggunaan MessageQueue mempunyai beberapa kelebihan.

Contohnya, dengan memusatkan pesanan, anda boleh menggunakan beberapa ciri yang keren seperti mesej yang tertangguh, keupayaan untuk menghantar mesej entiti kumpulan, dan maklumat debug visual (seperti sampul surat yang digunakan dalam tutorial ini).

Terdapat ruang untuk kreativiti dalam kelas MessageQueue , sehingga anda dan keperluan permainan anda.

Kesimpulannya

Mengendalikan interaksi antara entiti permainan menggunakan sistem antrian mesej adalah cara untuk memastikan kod anda teratur dan bersedia untuk masa depan. Interaksi baru dapat dengan mudah dan cepat ditambah, bahkan ide-ide anda yang paling rumit, selagi mereka dirumuskan sebagai mesej.

Seperti yang dibincangkan dalam tutorial, anda boleh mengabaikan penggunaan baris gilir mesej utama dan hanya menghantar mesej terus ke entiti. Anda juga boleh memusatkan komunikasi menggunakan penghantaran (kelas MessageQueue dalam kes kami) untuk memberi ruang kepada ciri-ciri baru pada masa akan datang, seperti mesej belum selesai.

Saya harap anda mendapati pendekatan ini berguna dan menambahnya kepada tali permainan pemaju permainan anda. Kaedah ini mungkin kelihatan berlebihan untuk projek kecil, tetapi ia pasti akan membuat anda sedikit sakit kepala dalam jangka masa 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.