Etkinlik Yöneticisi Sistemi tasarlarken nelere dikkat etmeliyim?


9

Bir Java oyun motorunun temellerini inceliyorum ve bir Etkinlik Yöneticisi sistemine eklemeye hazır olduğum noktaya ulaştım.

Biliyorum, teoride bir Etkinlik Yöneticisi ne yapması gerektiğini: için nesneler belirli olaylar için "kayıt" izin ve Etkinlik Yöneticisi bir olayın bildirim alır zaman, "kayıtlı" dinleyicilere olayı yayınlayan. Üzerinde durduğum şey onu uygulamaya nasıl başlayacağım.

Çevrimiçi olarak, bir olay sistemini sıfırdan uygulama hakkında hiçbir şey bulamadım, bu yüzden bu durumda en iyi uygulamaların neler olduğunu - ne yapmamalı ve yapmamam gerektiğini öğrenmek istiyorum .

Örneğin, oyun nesnelerimin her birinin bir EventManageralanı olması gerçekten gerekli mi? Tüm oyun nesnelerim tek bir soyut ana sınıftan miras aldığından, tüm oyun nesneleri arasında paylaşılan Etkinlik Yöneticisi'nin yalnızca bir örneği olması için statik bir başvuru kullanabilmem gerektiğini düşünüyorum. Her nesneyi oluşturmak için kullandığım Applet ile benzer bir şey yapıyorum.

Her bir abone olunan her etkinlik için bir çeşit koleksiyon bulundurmam gerektiğini tahmin ediyorum - gerektiğinde oyun nesnelerini listeye ekleme ve kaldırma. Ben yayınlanması gereken olayların bir sıra yapmak mümkün olacağını düşünüyorum, bu durumda ben sadece ana oyun döngüsüne "EventManager.Update ()" eklemek ve Update()yöntem sonunda meydana olayları yayın var olabilir her çerçevenin. Son olarak, her nesnenin HandleEvent(Event e)uygun bir şekilde ayrıştırıp yanıt verebilecekleri bir yöntemi olacaktır .


Bu, böyle bir sistemin uygulanmasına yönelik uygun bir yön gibi mi geliyor, yoksa raydan çıkıp çok açık bir şeyi mi kaçırıyorum?


2
gamedev.stackexchange.com/questions/7718/… Bu, başlangıçta size yardımcı olabilecek bir Q / AI'dir .
James

@James Ah - iyi bir bağlantıya benziyor. Teşekkürler! Sanırım bunu daha önce özledim.
Raven Dreamer

4
Bazı ek ipuçları: Bazı olayların, özellikle bir olay işleyici ek olayları tetikliyorsa, çerçevenin sonunda yerine hemen etkili olup olmayacağına karar verir; olay döngüleri aldığınızda ne olacağını düşünün; bir kuyrukla giderseniz, bir öncelik sistemine veya kuyruğu atlamanın bir yoluna ihtiyacınız olabilir.
sam hocevar

Yanıtlar:


6

Bu istediğiniz kadar basit olabilir.

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

Bir etkinlik yöneticisinin ne yapması gerektiğini 'denemeye çalışmayın - ne yapmanız gerektiğini hesaplayın. Gerisi oradan gelmeli ya da en azından daha spesifik sorular önermelidir.


3
+1 için "Bir X'in 'ne yapması gerektiğini denemeyin ve yapmanıza gerek yok." Aslında, işlevleri çağırmak için ayrıştırılmış ancak merkezi bir yola ihtiyacınız olduğunu düşünene kadar bir etkinlik yöneticisi eklemeyin.

@JoeWreschnig Oh god yes =) "ne yapmanız gerekiyorsa çalışın" Bu, herhangi bir geliştiricinin kalbine alması gereken en önemli 3 tavsiye arasındadır.
Patrick Hughes

İlk başta bir etkinlik yöneticisi eklememe konusundaki ikinci cümlenize katılmıyorum, çünkü çoğu oyun, işlevleri çağırmak için ayrılmış ama merkezi bir yoldan yararlanabilir, ancak daha sonra, herhangi bir etkinlik yöneticisine sahip olmak. yani, evet
jhocking

3

Bir olay sisteminin ihtiyaç duyduğu üç temel yöntem bir addListener () yöntemi, removeListener () yöntemi ve dispatchEvent () yöntemidir. Yani, bir olaya kayıt olmak için kullanılan bir yöntem, kayıttan çıkarmak için kullanılan bir nesne ve bir olayı tüm dinleyicilere yayınlamak için kullanılan bir yöntemdir. Diğer her şey sos.

Belirttiğiniz gibi, kayıtlı dinleyicileri takip etmek için kesinlikle bir çeşit veri yapısına ihtiyacınız olacaktır. En basit yaklaşım, bir vektörü (veya dile bağlı olarak bir Array) bir olayla ilişkilendiren ilişkilendirilebilir bir dizi (Sözlük veya JavaScript'teki bir Nesne) olacaktır. Bu vektör kayıtlı tüm dinleyicilerin bir listesidir; listeye dinleyiciler ekleyebilir veya add / removeListener () yöntemleriyle bunları kaldırabilirsiniz.

Bir olayı dispatchEvent () içinde yayınlamak, vektörde döngü yapmak kadar basit olabilir. Olayların önceliğini veya herhangi bir şeyi sıralayarak gönderime daha fazla karmaşıklık katabilirsiniz, ancak ihtiyacınız olana kadar endişelenmeyin. Çoğu durumda buna ihtiyacınız olmaz.

Olayla birlikte hangi verilerin iletileceğini düşündüğünüzde dispatchEvent () yöntemi için küçük bir nüans vardır. En temel düzeyde herhangi bir ek veri iletemeyebilirsiniz; dinleyicinin bilmesi gereken tek şey bir olayın gerçekleştiğidir. Bununla birlikte, çoğu olay, onlarla birlikte gelen (örneğin, olayın gerçekleştiği yer) ek verilere sahiptir ve dispatchEvent () öğesinin bazı parametreleri kabul etmesini ve iletmesini istersiniz.

Örneğin, her bir GameObjectsimin "EventManagner" alanına sahip olması gerçekten gerekli mi? Tüm GameObjects'im tek bir soyut ana sınıftan miras aldığından, tüm oyun nesneleri arasında paylaşılan EventManager'ın yalnızca bir örneği olması için statik bir referans kullanabilmem gerektiğini düşünüyorum.

Tüm oyun nesnelerinize EventManager sınıfına referans vermenin birçok yolu vardır. Statik bir referans kesinlikle bir yoldur; diğeri Singleton'la. Bununla birlikte, bu yaklaşımların her ikisi de oldukça esnek değildir, bu nedenle buradaki çoğu insan ya bir servis bulucu ya da bağımlılık enjeksiyonu önermektedir. Bağımlılık enjeksiyonu yapıyorum; Bu, her nesne için ayrı bir EventManager alanı anlamına gelir, bu da kaçınmak istediğiniz şeydir, ancak bunun neden bir sorun olduğundan emin değilim. Bir sürü işaretçi saklamaktan çok fazla yük var gibi değil.


Evet, ilk kez bağımlılık enjeksiyonunu ilk kez kavrattım ve uyguladım, bir EventDispatcher nesnesi içindi. Bunu kemerin altına aldığımda, bu desenle birçok şeyi yeniden gözden geçirmek için kaşınıyordum.
jhocking

0

REDDİ

Bir Java programcısı değilim ama en kolay dillerden (IMHO) biri olan C89'da bir olay sisteminin nasıl oluşturulacağını açıklayan bir makale yazdım

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

Olay işlemenin temelleri oldukça basittir.

  • bir etkinliği geri arama ile kaydetme
  • tetikleyici olay
  • bir eşleşme olup olmadığını görmek için dinleyiciler arasında dolaşın
  • bulunursa yangın giderici
  • tekrar et

Bunu bilmek (ancak Java'da nasıl uygulanacağını bilmemek), bazı işleyicilere (olayları işlemek için işlevlere) ihtiyacınız olduğunu ve bunları bir olay adıyla eşleştirilmiş bir diziye (C ile işaretçilerle) eklemeniz gerektiğini anlamak kolaydır. Bir olayı tetikledikten sonra, tetiklenen olay adını ve bunun bağımsız değişkenlerini bir yığına kaydedersiniz, buna olay havuzu denir.

Daha sonra, o yığındaki ilk olayı açan, bunun için bir işleyici bulmaya çalışan bir olay özeti (basit bir döngü) vardır ve varsa parametre ile çalıştırır.

Tabii ki, bu olay özeti istediğiniz zaman tetiklenebilir, örneğin Update()fonksiyonunuzu çağırdıktan sonra kare başına bir kez .


-2

EventManager alanı için statik bir değişken kullanın. EventManager için bir Singleton da harika bir fikir olacaktır.

Yaklaşımınız kulağa hoş geliyor, ancak iş parçacığı için güvenli hale getirmeyi unutmayın.

IO-Events'i "GameEvent" lerden önce veya sonra yürütmek iyidir, bu nedenle bir çerçevede her "GameEvent" aynı veriyle ilgilenir.


"Konu-save"? Hmmm
U62

Tamamen gereksiz ve haksız singleton önerisi için -1.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.