Apa yang harus saya pertimbangkan ketika merancang Sistem Event Manager?

9

Saya telah bermain-main dengan dasar-dasar mesin game Java, dan saya telah mencapai titik di mana saya siap untuk menambahkan dalam sistem Event Manager.

Saya tahu, secara teori , apa yang harus dilakukan oleh seorang Manajer Acara: mengizinkan objek untuk "mendaftar" untuk acara tertentu, dan setiap kali Manajer Acara diberitahu tentang suatu peristiwa, menyiarkan acara itu kepada pendengar "yang terdaftar". Apa yang saya bingung adalah bagaimana memulai mengimplementasikannya.

Saya belum dapat menemukan apa pun, online, tentang penerapan sistem acara dari awal, jadi saya mencari masukan tentang praktik terbaik apa yang ada dalam kasus ini - apa yang seharusnya dan tidak seharusnya saya lakukan.

Misalnya, apakah benar-benar diperlukan untuk setiap objek game saya untuk memiliki EventManagerbidang? Karena semua objek game saya mewarisi dari satu, kelas induk abstrak, saya pikir saya harus dapat menggunakan referensi statis sehingga hanya ada satu instance dari Event Manager, dibagi di antara semua objek game. Saya melakukan sesuatu yang serupa, dengan Applet, yang saya gunakan untuk membuat setiap objek, sudah.

Saya kira saya harus memelihara koleksi semacam untuk setiap acara berlangganan yang mungkin - menambah dan menghapus objek game dari daftar, sesuai kebutuhan. Saya pikir seharusnya dimungkinkan untuk membuat antrian acara yang perlu disiarkan, dalam hal ini saya cukup menambahkan "EventManager.Update ()" ke loop permainan utama, dan minta Update()metode menyiarkan peristiwa yang terjadi di akhir dari setiap bingkai. Akhirnya, setiap objek akan memiliki HandleEvent(Event e)metode, yang kemudian dapat diurai dan ditanggapi dengan tepat.


Apakah ini terdengar seperti arah yang tepat untuk menerapkan sistem seperti itu, atau apakah saya keluar jalur dan / atau melewatkan sesuatu yang cukup jelas?

Raven Dreamer
sumber
2
gamedev.stackexchange.com/questions/7718/... Ini adalah Q / AI yang diberikan sebelumnya yang dapat membantu Anda memulai.
James
@ James Ah - sepertinya tautan yang bagus. Terima kasih! Saya pikir saya melewatkan itu, sebelumnya.
Raven Dreamer
4
Beberapa petunjuk tambahan: putuskan apakah beberapa peristiwa benar-benar harus segera diberlakukan alih-alih di akhir bingkai, terutama jika penangan peristiwa memicu peristiwa tambahan; pikirkan apa yang terjadi ketika Anda mendapatkan loop acara; jika Anda pergi dengan antrian, mungkin Anda akan memerlukan sistem prioritas, atau cara untuk memotong antrian.
sam hocevar

Jawaban:

6

Ini bisa sesederhana yang Anda inginkan.

for each object in the subscriber list:
    object.notify(this event) // (or 'HandleEvent' if you prefer)

Jangan mencoba dan mencari tahu apa yang harus dilakukan oleh seorang manajer acara - cari tahu apa yang perlu Anda lakukan. Selebihnya harus mengikuti dari sana, atau setidaknya, harus menyarankan beberapa pertanyaan yang lebih spesifik.

Kylotan
sumber
3
+1 untuk "Jangan mencoba dan mencari tahu apa yang harus dilakukan oleh seorang X - cari tahu apa yang perlu Anda lakukan." Faktanya, jangan menambahkan event manager sama sekali sampai Anda merasa perlu cara terpisahkan-belum-terpusat untuk memanggil fungsi.
@ JoWreschnig Ya Tuhan ya =) "selesaikan apa yang perlu Anda lakukan" Ini adalah di antara 3 bit nasihat teratas yang harus diambil setiap pengembang.
Patrick Hughes
Pada awalnya saya ingin tidak setuju dengan kalimat kedua Anda tentang tidak menambahkan event manager karena sebagian besar game dapat mengambil manfaat dari cara dipisahkan fungsi-belum terpusat untuk memanggil fungsi, tapi kemudian saya berpikir berapa banyak game kecil yang saya buat yang tidak memiliki manajer acara apa pun. jadi, yeah
jhocking
3

Tiga metode penting yang dibutuhkan sistem peristiwa adalah metode addListener (), metode removeListener (), dan metode untuk dispatchEvent (). Artinya, metode objek digunakan untuk mendaftar untuk suatu acara, metode objek digunakan untuk membatalkan pendaftaran, dan metode untuk benar-benar menyiarkan acara ke semua pendengar. Yang lainnya adalah saus.

Seperti yang Anda perhatikan, Anda tentu membutuhkan semacam struktur data untuk melacak pendengar yang terdaftar. Pendekatan paling sederhana adalah array asosiatif (Kamus, atau Objek dalam JavaScript) yang mengaitkan vektor (atau hanya Array tergantung pada bahasa) dengan suatu peristiwa. Vektor itu adalah daftar semua pendengar terdaftar; tambahkan pendengar ke daftar atau hapus mereka dalam metode add / removeListener ().

Untuk menyiarkan suatu peristiwa di dispatchEvent () itu bisa sesederhana perulangan melalui vektor. Anda dapat menambahkan lebih banyak kerumitan untuk pengiriman dengan menyortir prioritas acara atau apa pun, tetapi jangan khawatir tentang hal itu sampai Anda membutuhkannya. Dalam banyak kasus Anda tidak akan membutuhkannya.

Ada sedikit nuansa untuk dispatchEvent () ketika Anda mempertimbangkan data apa yang harus diteruskan dengan acara tersebut. Pada tingkat paling dasar Anda mungkin tidak akan melewatkan data tambahan apa pun; yang harus diketahui pendengar hanyalah bahwa suatu peristiwa terjadi. Namun sebagian besar acara memiliki data tambahan yang menyertainya (mis. Di mana peristiwa itu terjadi) untuk Anda ingin dispatchEvent () menerima dan melewati beberapa parameter.

Misalnya, apakah benar-benar perlu bagi setiap GameObjects saya untuk memiliki bidang "EventManagner"? Karena semua GameObjects saya mewarisi dari satu, kelas induk abstrak, saya pikir saya harus dapat menggunakan referensi statis sehingga hanya ada satu instance dari EventManager, dibagi di antara semua objek game.

Ada banyak cara untuk memberikan semua objek game Anda referensi ke kelas EventManager. Referensi statis tentu saja satu arah; yang lainnya adalah dengan Singleton. Kedua pendekatan tersebut sangat tidak fleksibel, sehingga sebagian besar orang di sini merekomendasikan pelacak layanan atau injeksi ketergantungan. Saya sudah melakukan injeksi ketergantungan; itu berarti bidang EventManager terpisah untuk setiap objek, yang tampaknya ingin Anda hindari, tapi saya tidak yakin mengapa itu menjadi masalah. Ini tidak seperti ada banyak overhead dari menyimpan banyak petunjuk.

jhocking
sumber
ya, pertama kali saya benar-benar memahami dan menerapkan injeksi ketergantungan adalah untuk objek EventDispatcher. Begitu saya mendapatkannya, saya sudah gatal untuk memperbaiki banyak hal dengan pola itu.
jhocking
0

PENOLAKAN

Saya bukan seorang programmer Java tetapi saya menulis sebuah artikel yang menjelaskan cara membuat sistem acara di C89, salah satu bahasa yang paling mudah (IMHO), lihat saja

https://prdeving.wordpress.com/2017/04/03/event-driven-programming-with-c-89/

Dasar-dasar penanganan acara cukup sederhana.

  • mendaftarkan suatu acara dengan panggilan balik
  • pemicu acara
  • loop melalui pendengar untuk melihat apakah ada kecocokan
  • penangan api jika ditemukan
  • ulang

Mengetahui hal ini (tetapi tidak tahu bagaimana mengimplementasikannya di Jawa), mudah dipahami bahwa Anda memerlukan beberapa penangan (fungsi untuk menangani acara) dan menambahkannya ke array (dengan pointer, dalam C) dipasangkan dengan nama acara. Setelah Anda memicu suatu peristiwa, Anda menyimpan nama acara yang dipicu dan argumennya di tumpukan, ini disebut kumpulan acara.

Kemudian Anda memiliki event digest (loop sederhana), yang muncul acara pertama di tumpukan itu, mencoba untuk menemukan penangan untuk itu, dan jika ada, jalankan dengan params.

Tentu saja, intisari acara ini dapat dipicu kapan pun Anda inginkan, misalnya sekali per bingkai setelah Anda memanggil Update()fungsi Anda .

PRDeving
sumber
-2

Untuk bidang EventManager, gunakan variabel statis. A Singleton untuk EventManager juga merupakan ide bagus.

Pendekatan Anda kedengarannya bagus, tetapi jangan lupa untuk membuatnya aman.

Adalah baik untuk mengeksekusi IO-Events sebelum atau setelah "GameEvent", jadi dalam satu frame setiap "GameEvent" berhubungan dengan data yang sama.

Sibbo
sumber
"Thread-save"? Hmmm
U62
-1 untuk saran tunggal yang sama sekali tidak perlu dan tidak dapat dibenarkan.