Etkinlik İşleyicileri ile delirebilir miyim? Tasarımımla “yanlış yola” mı gidiyorum?


12

Olay işleyicilerini gerçekten sevdiğime karar verdim sanırım. Analiz felçinden biraz acı çekiyor olabilirim, ancak tasarımımı kararsız hale getirmekten veya tasarım kararlarımda öngörülemeyen başka bir sonuçla karşılaşmaktan endişeliyim.

Oyun motorum şu anda yatay kaydırma tepegöz kamera ile temel hareketli grafik tabanlı görüntü oluşturma yapıyor. Tasarımım şöyle:

SceneHandler

SceneListener arabirimini uygulayan sınıfların bir listesini içerir (şu anda yalnızca Sprite'lar). Çağrılar her işaret için bir kez render () olur ve onCameraUpdate (); SceneListeners'a mesajlar.

InputHandler

Girişi işaret başına bir kez yoklar ve InputListeners'a basit bir "onKeyPressed" mesajı gönderir. Bir SceneHandler örneği tutan ve updateCamera () tetikleyen bir Camera InputListener var; girdinin ne olduğuna bağlı olaylar.

AgentHandler

Herhangi bir Aracıdaki (AI) varsayılan eylemleri her onaylamada bir kez çağırır ve kayıtlı olan yeni olaylar için bir yığını kontrol eder ve gerektiğinde belirli Aracılara gönderir.

Bu yüzden bir sahne etrafında hareket edebilen ve seyahat için temel direksiyon davranışlarını kullanabilen temel hareketli grafik nesnelerim var. Çarpışma tespitine girdim ve burası tasarımımın gittiği yönün iyi olduğundan emin değilim. Çok sayıda küçük olay işleyicisine sahip olmak iyi bir uygulama mı? Bir çeşit CollisionHandler uygulamak zorunda olduğum gibi gidiyorum.

AI, çarpışma güncellemeleri ve diğer varlık etkileşimlerini tek bir sınıfta işleyen daha konsolide bir EntityHandler ile daha iyi olur muyum? Yoksa sadece ne tür bir olaya bağlı olarak birbirlerine mesajlar ileten birçok farklı olay işleme alt sistemi uygulamak iyi olacak mı? Tüm bu alt olay işleyicilerini koordine etmekten sorumlu bir EntityHandler yazmalı mıyım?

Benim InputHandler ve SceneHandler gibi bazı durumlarda, bunların çok özel olaylar olduğunu anlıyorum. Oyun kodumun büyük bir kısmı girdi ile ilgilenmez ve büyük bir kısmı tamamen sahnenin oluşturulmasında meydana gelen güncellemeleri umursamaz. Böylece bu sistemleri tecrit etmemin haklı olduğunu hissediyorum. Ancak, bu soruyu özellikle oyun mantığı türü olaylara yaklaşırken soruyorum.

Yanıtlar:


21

Olaya dayalı tasarım çoğunlukla Reactor tasarım modelinin uygulanmasını içerir .

Bileşenleri tasarlamaya başlamadan önce, bu modelin sınırlamalarına bir göz atmalısınız (bu konuda bol miktarda bilgi bulabilirsiniz).

İlk ve en önemli sorun, GUI tabanlı çerçeveler ve javascript tabanlı uygulamalar üzerinde bazı serius çalışması yapan herkesin iyi bildiği gibi , işleyicilerin hızlı bir şekilde geri dönmesi gerektiğidir.

Her uygulamayı iyi bir karmaşıklıkla geliştirdiğinizde , er ya da geç, zaman gerektiren karmaşık bir iş yapan bir işleyiciyle karşılaşacaksınız .

Bu durumlarda iki durumu ayırt edebilirsiniz (karşılıklı olarak münhasır değildir):

Karmaşık olayla ilgili sorumluluklar ve karmaşık olayla ilgili olmayan sorumluluklar.

Olayla ilgili karmaşık sorumluluklar:

İlk durumda , tek bir bileşen işleyicide çok fazla sorumluluk birleştirdiniz : bir olaya yanıt olarak çok fazla işlem yapılıyor veya örneğin çalışan senkronizasyonlar var.

Bu durumda çözüm, işleyiciyi farklı işleyicilere (gerekirse farklı nesnelerde) bölmek ve doğrudan işleme kodunu çağırmak yerine olayları tetiklemesine izin vermektir. Bu, birincil işleyiciniz olay kuyruğuna etkinlik ekledikten sonra geri döndüğünden, daha yüksek öncelikli bir etkinliğin daha önce yönetilmesine izin vermenizi sağlar.

Başka bir çözüm, harici bir varlığın olayları tetiklemesine ve diğerlerinin ilgiliyse abone olmasına izin vermektir (zamanlama olayı genelleştirebileceğiniz en önemsiz örnektir).

Etkinlikle ilgili olmayan karmaşık sorumluluklar:

İkinci durum, bir olaydan sonra yapılacak eylemde içsel bir karmaşıklık olduğunda gerçekleşir: örneğin bir olaydan sonra bir fibonacci numarası hesaplamanız gerekir.

Burada Reaktör deseni temelde başarısız olur , fibonacci nesil algoritmasını bir sonraki adımı tetiklemek için sonlandırma üzerine olayları ateşleyen küçük parçalara ayırmaya değmez.

Burada çözüm, dişli bir tasarımı reaktöre karıştırmaktır , iyi haber şu ki, karmaşıklık içsel ise (böylece doğru bölümü okuyorsunuz), başlamanın mümkün olduğunu ve işi yapan bağımsız bir dişin ve Reactor ile ilgili bileşenlerin geri kalanı hakkında çok az şey bilmek veya hiç bir şey bilmemesi gerekir.

Bu tür durumlarla başa çıkmak için, esnek bir parçacığı havuzu üzerinden bir iş kuyruğu benimsemeyi yararlı buldum .

Bir işleyici uzun eylemi başlatmak için gerektiğinde, kapsüller bu eylem bir iş birimine iş kuyruğunda konması. Bu kapsüllenmiş eylemin , reaktör dişindeki olayları tetikleyecek bir ortama sahip olması gerekir . İş kuyruğu yöneticisi kendi iş parçacığında veya reaktör iş parçacığında çalışabilir ve "newJob" olayına yanıt verebilir.

İş kuyruğu yöneticisi aşağıdakileri yapar:

  • havuz bir iş parçacığı sağlayabiliyorsa, shedule algoritmasını kullanarak esnek iş parçacığı havuzundan bir iş birimini ayırır (ücretsiz iş parçacığı varsa veya yeni iş parçacığı oluşturulmasına izin verilir)

  • bir iş biriminin bitip bitmediğini görmek için havuzun kendisini dinleyin, böylece varsa bekleyen bir iş parçasını daha çalıştırmak için bir iş parçacığının kurtarılması.

Olay ateşleme mekanizmasını kullanarak bir iş birimi, tamamlanma, güncelleme durumu, uyarılar, hatalar veya gerektiğinde bildirimde bulunmak için olayları tetikleyebilir. Esnek iplik havuzu, tüm sistemi asmak için ölü ipliklerden kaçınırken kaynakların iyi kullanımını sağlar; iş kuyruğu, tutarlı bir miktarda hesaplama kaynağı gerektireceklerini bildiğiniz için, farklı tür eylemlere hangi tür öncelik atayacağınızı seçmenize olanak tanır.


3
+1 çok kapsamlı olduğu için. Meraklı okuyucu için birkaç bağlantı harika olurdu.
sam hocevar

1

Çoğu durumda, olayları diğer seçeneklere göre kullanmak genellikle hızı ve ademi merkeziyetçiliği artırabilir. Bence çok sayıda etkinlik kullanabiliyorsan bunun için gitmelisin.

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.