XNA ile oyun mimarisi ile ilgili sorular


12

Sonunda XNA ile oynamaya başladım ve bir 2D oyun yaparak oynuyorum (iOS'ta geliştiren bir arkadaşımdan bir sürü sanat varlığım var)

Bir çok şey yapmak kolay ve kutudan çıkıyor gibi görünüyor, ancak literatürün çoğu (örneğin satın aldığım kitaplar) 2D'ye çok fazla dikkat etmediği için bir sürü şey için güdük bıraktım.

Aşağıdaki görevler hakkında herhangi bir açıklamayı veya daha fazla bilgiye dikkat etmekten gerçekten memnun olurum:

  1. Oyun Hizmetinin anlamı nedir? Başka bir GameComponent'in onu alabilmesi için bir nesneyi bir hizmet olarak kaydetmenin tüm deyimini anlıyorum, ancak bu nasıl basitçe kamusal veya statik hale getiriyor? Örneğin, kitabım SpriteBatch nesnesinin Game.cs sınıfına kaydedilmesini önerdi. Yine de sadece bir oyun örneği (singleton) olması gerektiğinden, bunu genel / statik hale getirmek için nasıl tercih edileceğinden emin değilim?

  2. Ne zaman GameComponent veya RenderableGameComponent devralmak gerekir. Tüm varlıkların tek bir yönetici tarafından yaratıldığı / sahip olduğu ve diğer şeyler için aynı olan bir Yönetici / Denetleyici tasarımını takip etmeye çalışıyorum. Şu anda her Yönetici / Denetleyici GameComponent'ten miras aldım, ancak bu Oyun nesnesinin tüm Yöneticilere sahip olması ve manuel olarak güncellemeyi çağırması ve çizmesi nasıl oluyor?

  3. Initialize'ın ContentLoad () 'den önce çağrıldığını fark ettim, Initialize'de bazı varlıklarımı (örneğin Sprite, Player vb.) Oluşturmak istediğim yer olduğu için bu can sıkıcı buldum, ancak onlara yüklenemiyorum SpriteSheets veya Textures, onları yükleme çağrısından bu yana henüz gerçekleşmedi. Belki yanlış mı başlatıyorum yoksa insanlar sadece ContentLoad içinde dokuyu daha aşağı mı atacak?

Bunlar benim gerçekten anlamadığım en büyük " WTF " gibi görünüyor

Yanıtlar:


11

Sorunuzun cevabı basitçe: Neyin işe yaradığını yapın. İdeal olanı basit ve işe yarıyor. Genellikle yerleşik mimariyi kullanmak basit değildir, çünkü buldukça, oyununuzu istediğiniz gibi yapılandırmak için çemberlerden atlamanız gerekir.

Birinci soruyu cevaplamak için, sizi "Neden hizmetleri kullanıyorsunuz?" Sorusuna vereceğim. . Kısa cevap, hizmetlerin kendi kendine yeten bir oyunda asla karşılaşmayacağınız birleştirme (sürüm oluşturma, bağımlılık, genişletilebilirlik) sorunlarından kaçınmanın iyi bir yoludur . Çoğu zaman sadece bir üye public(ve belki de staticaceleniz varsa) yapmak ve daha ilginç problemler hakkında endişelenmek daha kolaydır .

İkinci sorunuzu cevaplamak için, size "Bir oyun nesnesinin her örneği için DrawableGameComponent kullanmanın avantajları nelerdir?" oyun mimarisi hakkındaki düşüncelerimin yanı sıra . Kısa cevap: GameComponentkendi sınıflarınızı yaratmanın Drawve Updatekendiniz gibi yöntemleri çağırma yöntemini kullanmanın bir yararı yoktur . GameComponentİstediğiniz mimariye tam olarak uyuyorsa , elbette kullanın - ama neredeyse her zaman değil.

Hizmetlerin ve bileşenlerin kullanılması, yalnızca üçüncü taraf tüketimi için bir kitaplık oluşturuyorsanız ilginç hale gelir. XNA'nın kendisi bunu yapar - ve vardır IGraphicsDeviceServiceve GamerServicesComponentörneğin. Bunlar, bir oyun geliştirirken tipik olarak karşılaşmadığınız özel ayırma gereksinimlerini karşılar.

Son olarak, üçüncü sorunuzun cevabı oldukça basit: Sadece oyun varlıklarınızı oluşturun LoadContent. Özellikle özel bir şey yok Initialize.

Tüm Microsoft.Xna.Framework.Gamemontajın isteğe bağlı olduğunu belirtmek gerekir . Son derece kullanışlı bir başlangıç ​​noktası sağlar - ancak hiçbir şekilde işleri yapmak için "tek doğru yol" olarak düşünülmemelidir.


Onu görmek için çok ilginç bir yol. Cevabımdan çok daha gerçekçi ve yeryüzüne. +1 hak etti, efendim.
Jesse Emond

Bir sorum daha var! Bir Texture2D için çizdiğinizde başlangıç ​​noktası ne olacak? Kökeni dokunun alt ortasına yerleştirmek yaygın mıdır? Animasyonlar yapmaya çalışıyorum ve (0,0) 'da başlangıç ​​noktasına sahip olmanın, genişlik ve yükseklik aynı değilse dokunun biraz kaymasına neden olduğunu
görüyorum

@Setheron: Gerçekten yeni bir soru yaratmalısınız - çünkü bu orijinal soru ile oldukça ilgisiz. Bu soruya yaptığınız düzenlemeye geri döneceğim. Kökeni SpriteBatch.Draw, dokunun sol üst köşesine göre doku piksel koordinatlarında belirtilir (veya kullanıyorsanız, dikdörtgen dikdörtgen).
Andrew Russell

1
@Andrew: Son zamanlarda oyunumu public/ staticözellik yerine tamamen hizmetlere dayalı olacak şekilde yeniden düzenledim . Neden? Testedilebilirlik. Mülk yaklaşımı ile işleri değiştirmek neredeyse imkansızdır, oysa her IServiceProviderşey test yönteminizle sınıfın ihtiyaç duyduğu herhangi bir şeyle doldurulabilen bir şeyle başlatılırsa önemsizdir . Ayrıca Gametestte nesnenin kendisini somutlaştırma ihtiyacını da ortadan kaldırır , bu da çok hızlı bir şekilde dağınık hale gelir.
Matthew Scharley

Bir kenara, hala Gamenesne üzerinde çok sayıda ortak mülk var . Bunlara sadece içine itilen ve Game.Servicessonra ihtiyaç duyduklarını tekrar almak için her şeye aktarılan arayüzler aracılığıyla erişiliyorlar .
Matthew Scharley

3

İlk sorunuz için, gerçek cevabı gerçekten bilmediğimi itiraf etmeliyim. Sanırım singleton'un neden genellikle kötü bir tasarım deseni olduğu ile aynı olurdu. Sizi bu linkten bir alıntıya yönlendireceğim :

İlk düşündüğümüz (ve hizmet sunmanın arkasındaki nedenlerden biri) bir oyunda bir GraphicsDevice referansı sunmaktı.Orijinal olarak Oyunun GraphicsDevice'e sahip olması ve Game.GraphicsDevice gibi bir özellik aracılığıyla ortaya çıkarmasıydı. Buradaki sorun, bunun GraphicsDevice'i oyuna sıkıca bağlaması, başka birisinin cihaza (bir oluşturucu gibi) sahip olmasına izin vermemesi ve birisinin gelecekteki güncellenmiş bir GraphicsDevice'i Oyunun yeni bir sürümünü göndermeden kullanmasını engellemesiydi. t geriye dönük uyumlu olmalıdır.

İkinci sorunuz için, bunun yerine Bileşen tabanlı bir yaklaşımı takip ederseniz, bunun gibi SpriteBileşenleri kullanmanın, her sprite nasıl güncelleneceğini ve çizileceğini bilen yönetici. Aynı fikirdeyim, kulağa aynı geliyor ama bileşen tabanlı bir tasarımı tercih ediyorum, çünkü sahip olduğu nesne odaklı yaklaşımı gerçekten çok seviyorum.

Üçüncü sorunuz için evet, LoadContent yöntemine herhangi bir içerik biçimini (varlıklar, yazı tipleri vb.) Yüklemelisiniz. Başlatma işlemine gelince, genellikle Initialize işlevi içinde Player nesnesini oluşturur ve ardından içeriğini LoadContent içine yüklersiniz. Ya da isterseniz bunu LoadContent içinde yapabilirsiniz.

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.