Saya membuat game sederhana, dan telah memutuskan untuk mencoba menerapkan sistem pesan.
Sistem pada dasarnya terlihat seperti ini:
Entity menghasilkan pesan -> pesan diposting ke antrian pesan global -> messageManager memberitahukan setiap objek pesan baru melalui onMessageReceived (Pesan Pesan) -> jika objek ingin, ia bertindak pada pesan.
Cara saya membuat objek pesan adalah seperti ini:
//base message class, never actually instantiated
abstract class Message{
Entity sender;
}
PlayerDiedMessage extends Message{
int livesLeft;
}
Sekarang SoundManagerEntity saya dapat melakukan sesuatu seperti ini dalam metode onMessageReceived ()
public void messageReceived(Message msg){
if(msg instanceof PlayerDiedMessage){
PlayerDiedMessage diedMessage = (PlayerDiedMessage) msg;
if(diedMessage.livesLeft == 0)
playSound(SOUND_DEATH);
}
}
Pro untuk pendekatan ini:
- Sangat sederhana dan mudah diimplementasikan
- Pesan dapat berisi informasi sebanyak yang Anda inginkan, karena Anda dapat membuat subkelas pesan baru yang memiliki informasi apa pun yang diperlukan.
Kontra:
- Saya tidak tahu bagaimana saya bisa mendaur ulang objek Pesan ke kumpulan objek , kecuali jika saya memiliki kumpulan yang berbeda untuk setiap subkelas Pesan. Jadi saya punya banyak dan banyak objek penciptaan / alokasi memori dari waktu ke waktu.
- Tidak dapat mengirim pesan ke penerima tertentu, tetapi saya belum membutuhkannya di game saya jadi saya tidak terlalu keberatan.
Apa yang kulewatkan di sini? Harus ada implementasi yang lebih baik atau beberapa ide yang saya lewatkan.
architecture
messaging
object-pools
kamu786
sumber
sumber
Jawaban:
Jawaban sederhana adalah Anda tidak ingin mendaur ulang pesan. Satu mendaur ulang objek yang dibuat (dan dihilangkan) oleh ribuan setiap frame, seperti partikel, atau sangat berat (puluhan properti, proses inisialisasi yang panjang).
Jika Anda memiliki partikel salju dengan bitmap, kecepatan, atribut fisik yang terkait yang baru saja turun di bawah tampilan Anda, Anda mungkin ingin mendaur ulangnya alih-alih membuat partikel baru dan menginisialisasi bitmap dan mengacak atribut lagi. Dalam contoh Anda, tidak ada yang berguna di dalam Pesan untuk menyimpannya, dan Anda akan membuang lebih banyak sumber daya untuk menghapus properti spesifik-instansinya, selain Anda hanya akan membuat objek Pesan baru.
sumber
Dalam permainan berbasis Java saya, saya datang dengan solusi yang sangat mirip, kecuali kode penanganan pesan saya terlihat seperti ini:
Saya menggunakan anotasi untuk menandai metode sebagai pengendali acara. Kemudian, pada permulaan gim, saya menggunakan refleksi untuk menghitung pemetaan (atau, seperti saya menyebutnya, "perpipaan") dari pesan - metode mana yang digunakan untuk memanggil objek mana saat suatu peristiwa dari kelas tertentu dikirim. Ini bekerja ... luar biasa.
Perhitungan perpipaan bisa menjadi sedikit rumit jika Anda ingin menambahkan antarmuka dan subkelas ke dalam campuran, tapi tetap saja cukup mudah. Ada sedikit perlambatan saat memuat game ketika semua kelas perlu dipindai, tetapi hanya dilakukan sekali (dan mungkin dapat dipindahkan ke utas terpisah). Apa yang didapat sebagai gantinya adalah pengiriman pesan yang sebenarnya lebih murah - saya tidak perlu memanggil setiap metode "messageReceived" dalam basis kode hanya untuk memeriksanya apakah acara tersebut dari kelas yang baik.
sumber
EDIT Jawaban Liosan lebih seksi. Lihatlah ke dalamnya.
Seperti kata Markus, pesan bukanlah kandidat umum untuk kumpulan objek. Jangan repot-repot karena alasan yang disebutkannya. Jika gim Anda mengirim berton-ton pesan jenis tertentu, maka mungkin itu akan bermanfaat. Tetapi kemudian pada saat itu saya sarankan Anda beralih ke panggilan metode langsung.
Ngomong-ngomong soal,
Jika Anda tahu penerima tertentu yang ingin Anda kirimi, bukankah cukup mudah untuk mendapatkan referensi ke objek itu dan melakukan panggilan metode langsung ke sana? Anda juga bisa menyembunyikan objek tertentu di belakang kelas manajer untuk akses yang lebih mudah di seluruh sistem.
Ada satu tipuan untuk implementasi Anda, dan ada potensi banyak objek untuk mendapatkan pesan yang tidak terlalu mereka pedulikan. Idealnya kelas Anda hanya akan menerima pesan yang benar-benar mereka pedulikan.
Anda dapat menggunakan a
HashMap<Class, LinkedList<Messagable>>
untuk mengaitkan jenis pesan dengan daftar objek yang ingin menerima jenis pesan itu.Berlangganan ke jenis pesan akan terlihat seperti ini:
Anda dapat menerapkan
subscribe
seperti itu (maafkan saya beberapa kesalahan, belum menulis java dalam beberapa tahun):Dan kemudian Anda bisa menyiarkan pesan seperti ini:
Dan
broadcastMessage
dapat diimplementasikan seperti ini:Anda juga dapat berlangganan pesan sedemikian rupa sehingga Anda dapat membagi penanganan pesan menjadi fungsi anonim yang berbeda:
Ini sedikit bertele-tele, tetapi membantu dengan organisasi. Anda juga dapat menerapkan fungsi kedua,
subscribeAll
yang akan menyimpan daftarMessagable
s terpisah yang ingin mendengar tentang semuanya.sumber
1 . Jangan.
Pesan berbiaya rendah. Saya setuju dengan Markus von Broady. GC akan mengumpulkannya dengan cepat. Cobalah untuk tidak melampirkan banyak info tambahan untuk pesan. Itu hanya pesan. Menemukan instance dari adalah info dengan sendirinya. Gunakan itu (seperti yang Anda lakukan dalam contoh Anda).
2 . Anda dapat mencoba menggunakan MessageDispatcher .
Berbeda dengan solusi pertama, Anda mungkin memiliki pengirim pesan terpusat yang memproses pesan dan meneruskannya ke objek yang dituju.
sumber