Kuro's GameServices Tutorial

Dev²
Verfügbare Informationen zu "Kuro's GameServices Tutorial"

  • Qualität des Beitrags: 0 Sterne
  • Beteiligte Poster: kuroneko - melwyn
  • Forum: Dev²
  • Forenbeschreibung: -= Code Games Or Die Trying =-
  • aus dem Unterforum: Tutorials
  • Antworten: 2
  • Forum gestartet am: Dienstag 22.05.2007
  • Sprache: deutsch
  • Link zum Originaltopic: Kuro's GameServices Tutorial
  • Letzte Antwort: vor 14 Jahren, 7 Monaten, 21 Tagen, 6 Stunden, 38 Minuten
  • Alle Beiträge und Antworten zu "Kuro's GameServices Tutorial"

    Re: Kuro's GameServices Tutorial

    kuroneko - 30.05.2007, 22:39

    Kuro's GameServices Tutorial
    Einführung
    Spiele und Programme im Allgemeinen bestehen aus vielen verschiedenen logischen Modulen, wie z.B. dem Renderer, dem TextRenderer, dem GUI-Renderer, einem Soundmodul, einem Inputmodul und viele viele mehr.
    Diese Module interagieren untereinander, rufen gegenseitig Methoden auf, fragen Properties ab oder setzen Flags.
    Das führt in der Regel zu kleineren und größeren Problemen:
    einzelne Module können nicht ohne weiteres geändert werden, weil schnell ungewünschte und teils unabsehbare Seiteneffekte in anderen Modulen auftreten können, und im Allgemeinen wird der Code einfach unübersichtlicher.

    Hier bietet XNA ein einfaches aber recht geniales Konzept, das die Strukturierung und Organisation einzelner logischer Programmodule stark vereinfachen sollte: GameComponents und GameServices.


    GameComponents
    Das Konzept der GameConponents in XNA beruht auf der Beerbung 2 verschiedener Klassen, die das XNA-Framework zu Verfügung stellt:
    Microsoft.Xna.Framework.GameComponent und Microsoft.Xna.Framework.DrawableGameComponent. Der Name lässt schon auf den einzigen Unterschied schließen: Die Klasse DrawableGameComponent wird von allen Komponenten beerbt, die sich selbst in irgendeiner Forum auf den Bildschirm zeichnen lassen wollen, und GameComponent wird von allen Komponenten beerbt, die keine Darstellungslogik benötigen.

    Um also eine entsprechende XNA-Komponente zu erzeugen, muss die Klasse, die unsere Komponente repräsentiert, entweder von GameComponent oder von DrawableGameComponent abgeleitet sein:

    Code: public class MyDrawableComponent
      : Microsoft.Xna.Framework.DrawableGameComponent{
    }


    Durch die Vererbung erhält die Klasse unter anderem die Methoden Draw(), Update() und Initialize(), wobei die Methode Draw() logischerweise nur von DrawableGameComponent abgeleitete Klassen erben.

    Diese 3 Methoden bilden das eigentliche Herzstück der Komponente - sie müssen nun überschrieben und mit eigener Funktionalität gefüllt werden.
    Die Routinen werden später automatisch von der Game-Klasse, die jedes XNA-Projekt erstellt, aufgerufen. Wann wird welche Routine aufgerufen?

    Game.Update() --> Update()
    Game.Initialize() --> Initialize()
    Game.Draw() --> Draw()

    Soweit erstmal logisch - natürlich ist es auch möglich, die einzelnen Methoden manuell aufzurufen.

    So, klingt ja alles erstmal ganz gut?

    Moment!

    Die einzelnen Komponenten müssen ja trotzdem aufeinander zugreifen, oder etwa nicht? Also sind die Komponenten genauso untereinander verzahnt wie zuvor. Arbeit für nichts gemacht?
    Hier kommen die GameServices ins Spiel.


    GameServices

    GameServices sind im Prinzip nichts weiter als Interfaces, die zusätzlich zur Vererbung von GameComponent / DrawableGameComponent spezifizieren, was genau eine Komponente nun leistet.
    Also muss die Implementierung unserer Komponente erweitert werden, indem wir unserer Kompoente ein entsprechendes Interface zuordnen, das wir natürlich noch definieren müssen.
    Als Beispiel definieren wir uns ein ganz einfaches Interface, das nur besagt, das die Komponente, die dieses Interface einbindet, eine Projection- und eine View-Matrix beinhalten muss.

    Interface:

    Code: public interface IMyService {
      Matrix Projection { get; set; }
      Matrix View { get; set; }
    }

    Um das ganze noch ein wenig sauberer zu machen, implementieren wir in der Kompoente zusätzlich zum Interface schonmal den Konstruktor, der erstmal nur den Base-Konstruktor (also den der Klasse, von der abgeleitet wurde) aufruft:

    Code: public class MyDrawableComponent
      : Microsoft.Xna.Framework.DrawableGameComponent,
        IMyService{

      public MyDrawableComponent(Game pGame): base(pGame){
        //Konstruktorroutinen
      }

      public override void Draw (GameTime gameTime){
        //Zeichenroutinen
      }

      public override void Initialize (){
        //Initialisierungsroutinen
      }

      public override void Update (GameTime gameTime){
        //Updateroutinen
      }
    }


    So, und jetzt kommt der eigentliche Trick an der ganzen Geschichte:
    Wie man oben sieht, bekommt unsere Komponente im Konstruktor die Game-Klasse übergeben, die die Instanz unseres Spiels repräsentiert.
    Mithilfe dieser Klasse können wir unsere Komponente als GameService registrieren, so das andere Komponenten darauf zugreifen können:

    Code: public MyDrawableComponent(Game pGame): base(pGame){
        pGame.Services.Add(typeof(IMyService), this);
      }


    Das war aber natürlich nur die halbe Miete, denn wie greifen wir jetzt auf andere, benötigte Kompoenten zu? Angenommen, wir brauchen in unserer Komponente Zugriff auf GraphicsDevice...was tun?
    Nun, natürlich sind auch die Standard-Komponenten von XNA nach diesem Prinzip aufgebaut, so das glücklicherweise unser GraphicsDevice das Interface IGraphicsDeviceService implementiert hat und sich ind er Game-Klasse nach dem Init auch registriert hat, so wie wir es mit unserer Komponente im Konstruktor tun. Alles, was nun also noch zu tun bleibt, ist im Initialize unserer Komponente mal bei der GameServices-Collection aus der Klasse Game anzufragen, wer uns die Funktionalitäten, die in IGraphicsDeviceService implemetiert sind, bietet.

    Code: public override void Initialize() {
        IGraphicsDeviceService xGraphicsDeviceService =
          (IGraphicsDeviceService)Game.GameServices.GetService(
            typeof(IGraphicsDeviceService)
          );
      // Nun Service intern merken, benutzen, was auch immer
    }

    Das wars erstmal in aller Kürze, wenn ich mal Zeit finde kann ich mal ne "richtige" Komponente posten. Wird dann vielleicht klarer!
    Für Tippfehler und so übernehm ich keine Verantwortung, bin schon ziemlich platt. Aber das Konzept müsste klar werden, denk ich :)

    Ansonsten:



    Re: Kuro's GameServices Tutorial

    melwyn - 31.05.2007, 13:26

    genial
    Das hört sich doch schonmal alles ganz vernünftig und ordentlich an. Ich habs jedenfalls verstanden und wir sollten das auch so machen. Ich hatte schonmal ein ähnliches tut gelesen, aber da ist es mir noch net ganz klar geworden... supi!



    Mit folgendem Code, können Sie den Beitrag ganz bequem auf ihrer Homepage verlinken



    Weitere Beiträge aus dem Forum Dev²



    Ähnliche Beiträge wie "Kuro's GameServices Tutorial"

    - Tutorial - - Bastlwastl (Sonntag 22.07.2007)
    Auto Tutorial - gearbox (Freitag 19.03.2004)
    Realease 2 - Mit Tutorial und reference - vankurt (Mittwoch 02.06.2004)
    Tutorial animierte Texturen / Sprites für HL² | CS:S !! - erwin (Samstag 05.03.2005)
    lift tutorial - erwin (Sonntag 03.04.2005)
    Gs-Handbuch , Leveltutorial , C-Script-Tutorial - lanzet3 (Dienstag 18.05.2004)
    MDL-Tutorial - lanzet3 (Mittwoch 19.05.2004)
    Tutorial - Master (Samstag 22.05.2004)
    FL Tutorial update - DJMechanix (Freitag 31.08.2007)
    Tutorial zu Little Fighter 2 (Online)... - Anonymous (Sonntag 13.06.2004)