Her şeyi statik hale getir ve global tasarım desenimden kurtulmak istiyorum, ama nasıl?


11

Uzayda küçük bir zindan paleti yapıyorum ve motorun arka ucunun nasıl daha güzel hale getirileceğine dair bazı tavsiyeler duymak istiyorum. Temel olarak, şu anda her şey yöneticilerin bir yığınına dayanmaktadır:

  • BackgroundManager: AddBackground(image, parallax)havalı arka plan efektleri yapma yöntemine sahiptir .
  • ConfigManager: yapılandırma dosyasını okur / yapar ve bu yapılandırma dosyasından okunan verileri tutar.
  • DrawManager: has Draw(sprite)ekrana şeyler çizmek için yöntem ve işler gibi SetView(view), GetView()vb
  • EntityManager: tüm aktif varlıkları tutar ve varlık ekleme, çıkarma ve bulma yöntemlerine sahiptir.
  • DungeonManager (aslında bir GridManager denilen, ancak bu basitlik içindir): has yöntemler gibi GenerateDungeon(), PlaceEnemies(), PlaceFinish()vb

Şimdi orada bile tüm yöneticilerimi listelemiyorum, bu yüzden bunun değişmesi gerektiğini düşünüyorum. Oyunum ayrıca Ekranları da temel alıyor, bu da daha can sıkıcı bir durum, çünkü yöneticilerimin yönettiği şeylerin yarısına ihtiyacım yok, örneğin ana menü !)

Şimdi yöneticileri statik hale getirmeyi ve ScreenMainGame'ime oyuna özgü tüm yöneticilerin bir örneğini vermeyi düşündüm. Ancak bu, yöneticilerle ilgili herhangi bir şeyi aramak / almak büyük bir karmaşaya neden olur ... örneğin, zindanımı içinde olmayan herhangi bir yerden çekmek ScreenMainGame.Draw()istersem, bunu yapmak zorundayım ...

((ScreenMainGame)ScreenManager.CurrentScreen).GridManager.Draw()

Bu gerçekten çirkin.

Peki oyun geliştiricileri, bu karışıklığı nasıl çözeceğiniz hakkında bir fikriniz var mı? Takdir ediyorum!


Size tam olarak nasıl yardım edeceğinizden emin değilim, ancak tasarım desenleri hakkında iyi bir kitap okumanızı tavsiye ederim. İlk Baş Tasarım Desenlerini okudum ve anlaması çok kolay. Örnekler Java, ama bu size yardımcı olmak için C # için yeterince yakın olacağını düşünüyorum. Benim önerim çok acemi ise üzgünüm.
Amplify91

Grafik kartıyla arayüz oluşturmak için ne kullanıyorsunuz? XNA? SlimDX?
BlueRaja - Danny Pflughoeft

@MaviRaja: SFML.NET kullanıyorum.
Dlaor

Bu durumda, C # 'da bu sorunlarla başa çıkmak için normal yöntemleri kullanmalısınız: Aşağıdaki son bağlantımın yanı sıra bağımlılık enjeksiyonu nedir?
BlueRaja - Danny Pflughoeft

Yanıtlar:


10

Ne hakkında bileşen tabanlı motor ?

EngineBir listesini tutacak GameScreens, kendilerinin bir listesini tutacak bir ana sınıfınız olurdu Components.

Motor bir sahiptir Updateve bir Drawyöntem ve her iki çağrıyı GameScreen'ler Updateve Drawkendilerini her bileşen ve çağrı geçmesi yöntemleri Updateve Draw.

Bu şekilde sunulan, kötü ve tekrarlayan bir tasarım gibi geldiğini kabul ediyorum. Ama inan bana, kodum tüm eski yönetici sınıflarımdan daha bileşen tabanlı bir yaklaşım kullanarak daha temiz hale geldi .

Sadece büyük bir sınıf hiyerarşisinden geçtiğiniz BackgroundManagerve belirli tüm farklı arka planları aramak zorunda olmadığınız için bu kodu korumak çok daha basittir . Sadece bir var ScrollingBackground, ParallaxBackground, StaticBackgroundvb bir türet hangi tüm Backgroundsınıfa.

Sonunda, sıkça kullanılan birçok bileşen ve yardımcı yöntemle (örneğin FrameRateDisplayer, hata ayıklama yardımcı programı, Spritevektörler için bir doku ve uzatma yöntemlerine sahip temel bir hareketli grafik olarak bir sınıf) tüm projeleriniz üzerinde yeniden kullanabileceğiniz oldukça sağlam bir motor oluşturacaksınız. ve rastgele sayı oluşturma).

Artık BackgroundManagerbir Backgroundsınıfınız olmayacak, onun yerine kendi kendini yönetecek bir sınıfınız olacaktır.

Oyununuz başladığında yapmanız gereken tek şey şu:

// when declaring variables:
Engine engine;

// when initializing:
engine = new Engine();
engine.Initialize();
engine.LoadContent();
engine.AddGameScreen(new MainMenuScreen());

// when updating:
engine.Update();

// when drawing:
engine.Draw();

Ve oyun başlangıç ​​kodunuz için bu kadar.

Ardından, ana menü ekranı için:

class MainMenuScreen : MenuScreen // where MenuScreen derives from the GameScreen class
{
    const int ENEMY_COUNT = 10;

    StaticBackground background;
    Player player;
    List<Enemy> enemies;

    public override void Initialize()
    {
        background = new StaticBackground();
        player = new Player();
        enemies = new List<Enemy>();

        base.AddComponent(background); // defined within the GameScreen class
        base.AddComponent(player);
        for (int i = 0; i < ENEMY_COUNT; ++i)
        {
            Enemy newEnemy = new Enemy();
            enemies.Add(newEnemy);
            base.AddComponent(newEnemy);
        }
    }
}

Genel fikri anlıyorsunuz.

Ayrıca , bir sınıf içinde bile yeni ekranlar ekleyebilmek için, Enginetüm GameScreensınıflarınızdaki referansları koruyabilirsiniz GameScreen(örneğin, kullanıcı sizin içindeyken StartGame düğmesini tıkladığında, öğesineMainMenuScreen geçiş yapabilirsiniz GameplayScreen).

Aynı şey Componentsınıf için de geçerlidir : yeni bileşenler eklemek GameScreeniçin hem Enginesınıfa hem de üst öğeye erişime sahip olması için üst öğesinin referansını tutması gerekir GameScreen(örneğin DrawableButton, bir DrawableTextbileşeni ve bileşeni tutan denilen HUD ile ilişkili bir sınıf yapabilirsiniz StaticBackground).

Bundan sonra, Enginesınıfınızda farklı yararlı hizmetleri tutabileceğiniz "hizmet tasarım deseni" (tam addan emin değilim) gibi diğer tasarım desenlerini de uygulayabilirsiniz (sadece bir IServices listesini tutarsınız ve diğer sınıfların kendileri hizmet eklemesine izin verirsiniz) ). Örneğin Camera2D, diğer bileşenleri çizerken dönüşümünü uygulamak için bir bileşeni hizmet olarak tüm projem üzerinde tutacağım . Bu, onu her yerde bir parametre olarak geçirmek zorunda kalmaz.

Sonuç olarak, bir motor için kesinlikle daha iyi tasarımlar olabilir, ancak bu bağlantı tarafından önerilen motoru çok zarif, son derece kolay bakım ve tekrar kullanılabilir buldum . Şahsen en azından denemenizi tavsiye ederim.


1
XNA, tüm bunları kullanıma hazır GameComponents ve hizmetler aracılığıyla destekler . Ayrı bir Enginesınıfa gerek yok .
BlueRaja - Danny Pflughoeft

Bu cevap için +1. Ayrıca, çizimi oyun güncelleme iş parçacığından ayrı bir iş parçacığına koymak anlamlı olur mu?
f20k

1
@BlueRaja - DannyPflughoeft: Gerçekten ama XNA'nın kullanılmadığını varsaydım, bu yüzden nasıl yapılacağı hakkında biraz daha açıkladım.
Jesse Emond

@ f20k: Evet, XNA'nın yaptığı gibi. Yine de nasıl uygulandığını bilmiyorum. = / İnternette bir yerde bunun nasıl yapılacağı hakkında bir makale olmalı. :)
Jesse Emond

Evet, XNA kullanmıyorum ama bu yaptığım şeye hoş bir alternatif gibi görünüyor. Şu anda başka alternatif olup olmadığını görmek için "Head First Design Patterns" kitabını okuyorum. Şerefe!
Dlaor


-3

Statik veya global olmaları, her zaman yüklenmesi / başlatılması gerektiği anlamına gelmez. Tekli bir desen kullanın ve yöneticilerin istendiğinde yeniden yüklenebilmesini ve yüklenmesini sağlayın.


4
Bir singleton, OP'nin burada çözmeye çalıştığı temel sorunun sadece bir cephesidir.
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.