Teknik apa yang harus saya gunakan untuk memfasilitasi komunikasi antara XNA GameComponents (atau antara komponen jenis apa pun dalam game)?


9

Saya memulai proyek game 'yang tepat' pertama saya, dan saya pasti akan berusaha keras untuk memutuskan bagaimana komponen-komponen game dalam XNA harus berkomunikasi.

Dari acara pemrograman GUI sebelumnya (Jawa), penangan dan pendengar tampak seperti jalan ke depan. Jadi saya akan memiliki semacam bus acara yang menerima pendaftaran acara dan kelas yang berlangganan acara-acara tersebut, dengan penangan untuk menghadapinya. Misalnya (kodesemu):

class SpriteManager
    Update(){
        if(player.collidesWith(enemy)
             // create new 'PlayerCollisionEvent'
    }

class HUDManager
    onPlayerCollisionEvent(){
        // Update the HUD (reduce lives etc)
    }

Namun, saya tidak yakin tentang pengaturan kode (dalam C #) yang akan diperlukan untuk menyelesaikan ini sepenuhnya. Apa yang melacak peristiwa (semacam bus?), Dan bagaimana strukturnya?

Tampaknya juga ada banyak yang disebutkan tentang Layanan Game, di mana Anda dapat mendaftarkan GameComponent di kelas Game.cs utama Anda, lalu mengambilnya dari mana saja dalam kode Anda yang memiliki referensi ke objek 'Game' utama. Saya sudah mencoba ini dengan objek SpriteBatch saya dan sepertinya sangat mudah .. namun, saya tidak bisa melihat ini sefleksibel model acara.

Ambil contoh ketika musuh mati. Kami ingin memperbarui skor permainan. Dengan menggunakan layanan, saya bisa mendapatkan referensi ke objek StateManager saya yang dibuat di Game1 dan ditambahkan sebagai layanan, lalu atur 'skor' ke nilai baru. Saya akan berpikir acara 'onEnemyDeath', yang dapat ditangani secara berbeda oleh banyak kelas, tetapi diprakarsai oleh 1 baris kode di bagian 'deteksi kematian musuh' yang relevan, akan lebih baik daripada secara individual casting setiap GameComponent yang diperlukan kemudian memanggil apa pun metode diperlukan.

Atau apakah ini strategi yang lebih rendah daripada yang lain?

Saya menyadari ini adalah sebagian dari pengetahuan C # saya yang buruk seperti halnya paradigma komunikasi permainan, tetapi saya benar-benar ingin memperbaiki hal mendasar ini.

Memperbarui

Setelah melihat Layanan lebih detail saya kurang yakin - itu pada dasarnya melewati variabel global sekitar (dari apa yang saya mengerti).

Perbarui 2

Setelah melihat tutorial dasar tentang penanganan event dan pengujian kode sampel ini, sepertinya acara akan menjadi pilihan logis untuk apa yang saya diskusikan. Tapi saya tidak bisa banyak menggunakannya dalam sampel yang saya lihat. Adakah alasan yang jelas mengapa seseorang tidak melakukannya?


Saya akan merekomendasikan Anda mencoba FlatRedBall terlebih dahulu. Itu duduk di atas XNA dan membuat hidup sangat mudah.
ashes999

3
Saya ingin benar-benar memahami dasar-dasar apa yang terjadi sebelum melompat ke mesin.
codinghands

Saya pikir kegagalan Anda di sini adalah benar-benar kurangnya informasi tentang C #. C # menggunakan acara untuk memfasilitasi komunikasi antar kelas biasanya. Terserah Anda bagaimana melakukannya - XNA menyediakan kelas SpriteBatch, dan sebagian besar pekerjaannya terserah Anda untuk menulis. Mesin akan memberi Anda gagasan yang solid tentang bagaimana segala sesuatu bekerja pada tingkat yang lebih tinggi sebelum masuk ke detail.
ashes999

1
Saya setuju sampai batas tertentu, tetapi dari saya sudah membaca sebagian besar komunikasi antar kelas antara GameComponents dapat dilakukan dengan menggunakan Layanan. Saya terbiasa menggunakan acara. Saya tidak yakin mana yang terbaik, atau jika ada alternatif yang valid (lajang, kelas statis yang menyamar sebagai global sebagai 2 metode lain yang telah saya
hilangkan

Jawaban:


4

Dari acara pemrograman GUI sebelumnya (Jawa), penangan dan pendengar tampak seperti jalan ke depan. Jadi saya akan memiliki semacam bus acara yang menerima pendaftaran acara dan kelas yang berlangganan acara-acara tersebut, dengan penangan untuk menghadapinya.

Alasan Anda tidak akan menemukan banyak tentang bus acara di C # adalah karena saya tidak berpikir siapa pun di luar Jawa menyebut hal seperti itu 'bus', menurut pengalaman saya. Istilah yang lebih umum mungkin adalah antrian pesan, manajer acara, sinyal / slot, terbitkan / berlangganan, dll.

Anda tidak memerlukan semua itu untuk membuat game yang berfungsi, tetapi jika itu adalah jenis sistem yang Anda sukai, itu akan membantu Anda dengan baik di sini juga. Sayangnya tidak ada yang bisa memberi tahu Anda cara membuatnya karena semua orang menggulungnya sedikit berbeda, jika mereka menggunakannya sama sekali. (Saya tidak, misalnya.) Anda mungkin mulai dengan System.Collections.Generic.List<Event>antrian sederhana , dengan berbagai acara Anda menjadi subkelas Acara, dan daftar pelanggan untuk setiap jenis acara. Untuk setiap acara dalam antrian, dapatkan daftar pelanggan, dan untuk setiap pelanggan, panggil handle(this_event)saja. Kemudian hapus dari antrian. Ulang.

Tampaknya juga ada banyak yang disebutkan tentang Layanan Game, di mana Anda dapat mendaftarkan GameComponent di kelas Game.cs utama Anda, lalu mengambilnya dari mana saja dalam kode Anda yang memiliki referensi ke objek 'Game' utama. Saya sudah mencoba ini dengan objek SpriteBatch saya dan sepertinya sangat mudah .. namun, saya tidak bisa melihat ini sefleksibel model acara.

Mungkin tidak fleksibel, tetapi lebih mudah untuk di-debug. Acara dan pesan rumit karena memisahkan fungsi panggilan dari fungsi yang dipanggil, yang berarti bahwa tumpukan panggilan Anda tidak terlalu membantu ketika debugging, tindakan perantara dapat menyebabkan sesuatu rusak yang biasanya berfungsi, hal-hal dapat gagal secara diam-diam ketika tidak dihubungkan dengan benar , dan seterusnya. Metode eksplisit "ambil komponen, dan panggil apa yang Anda butuhkan di atasnya" berfungsi dengan baik ketika menangkap kesalahan sejak dini dan memiliki kode yang jelas dan eksplisit. Itu hanya cenderung mengarah ke kode yang sangat erat dan banyak dependensi kompleks.

Saya menyadari ini adalah sebagian dari pengetahuan C # saya yang buruk seperti halnya paradigma komunikasi permainan, tetapi saya benar-benar ingin memperbaiki hal mendasar ini.

C # adalah bahasa yang hampir identik dengan Java. Apa pun yang Anda lakukan di Java dapat dilakukan dalam C #, hanya dengan sintaks yang berbeda. Jika Anda kesulitan menerjemahkan konsep, itu mungkin hanya karena Anda hanya tahu nama khusus Java untuknya.


@Kylotan terima kasih. Karena penasaran, sistem apa yang Anda gunakan sendiri untuk komunikasi antar kelas - pendekatan Layanan atau yang lainnya?
codinghands

AFAIK, bus acara mirip dengan antrian pengiriman pesan, tetapi untuk acara.
ashes999

2
@codinghands, saya biasanya tidak menggunakan metode komunikasi antar kelas yang diformalkan. Saya hanya menjaga hal-hal sederhana - jika satu kelas perlu memanggil yang lain, itu biasanya sudah memiliki referensi ke kelas kedua sebagai anggota, atau memiliki kelas kedua disahkan sebagai argumen. Namun kadang-kadang ketika saya bekerja dengan mesin Unity, yang memiliki pendekatan yang mirip dengan apa yang Anda sebut pendekatan 'layanan', di mana saya akan mencari objek dengan nama yang memiliki komponen yang saya butuhkan, mencari komponen pada objek, lalu panggil metode pada komponen itu.
Kylotan

@ ashes999 - Pesan dan acara hampir sama dalam konteks ini. Jika Anda menempatkan suatu peristiwa ke dalam antrian, atau bus, atau apa pun, apa yang sebenarnya Anda simpan adalah pesan yang menunjukkan bahwa suatu peristiwa telah terjadi. Demikian pula menempatkan pesan pada antrian menyiratkan bahwa suatu peristiwa terjadi untuk menghasilkan pesan itu. Hanya beberapa cara berbeda dalam melihat panggilan fungsi asinkron.
Kylotan

Maaf saya belum menandai ini sebagai 'dijawab', tapi saya pikir akan ada lebih banyak sudut pandang mengingat bahwa setiap permainan perlu berkomunikasi antar komponen entah bagaimana, terlepas dari bahasa ... Apakah kita sudah membahas kemungkinan utama?
codinghands

1

Sudahkah Anda mencoba menggunakan kejadian statis sederhana? Misalnya, jika Anda ingin kelas skor Anda tahu tentang kapan musuh mati, Anda akan melakukan sesuatu seperti ini:

Score.cs

class Score
{
    public int PlayerScore { get; set; }

    public Score()
    {
        EnemySpaceship.Death += new EventHandler<SpaceshipDeathEventArgs>(Spaceship_Death);
    }

    private void Spaceship_Death(object sender, SpaceshipDeathEventArgs e)
    {
        PlayerScore += e.Points;
    }
}

EnemySpaceship.cs

class EnemySpaceship
{
    public static event EventHandler<SpaceshipDeathEventArgs> Death;

    public void Kill()
    {
        OnDeath();
    }

    protected virtual void OnDeath()
    {
        if (Death != null)
        {
            Death(this, new SpaceshipDeathEventArgs(50));
        }
    }
}

SpaceshipDeathEventArgs.cs

class SpaceshipDeathEventArgs : EventArgs
{
    public int Points { get; private set; }

    internal SpaceshipDeathEventArgs(int points)
    {
        Points = points;
    }
}


0

coba gunakan agregator acara seperti ini


4
Jawaban ini akan lebih baik jika Anda menguraikan lebih lanjut tentang saran Anda, daripada hanya memberikan tautan.
MichaelHouse
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.