... Ausgangspunkt: Die Screen-Klasse Eine abstrakte Klasse mit dem Namen Screen dient als die Ausgangsbasis zur Implementierung der Spiel- und Menülogik. Bisher nahm die Game-Klasse die Logik des Spiels auf. Jeder Spielstatus wird jetzt in eine von Screen abgeleitete Klasse ausgelagert, um so die Zustände logisch zu trennen. Die grundlegende Architektur des XNA Framework soll weiterhin erhalten bleiben, jedoch komfortabler werden. Das bedeutet konkret, dass jedes Screen-Objekt mit den Methoden Initialize, LoadGraphicsContent, UnloadGraphicsContent sowie Update und Draw ausgestattet wird, um das Handling einer DrawableGameComponent- Instanz zu übernehmen. Mehr Komfort bieten hier die „frei Haus“ gelieferten Objekte, die bis jetzt über den Service Container des Game-Objektes abgerufen werden mussten:
- ScreenManager Manager
- ContentManager Content
- ScreenStates State
- Bool HasFocus
- Bool CanGetFocus
- Bool IsOpaque
Jedes Screen-Objekt erhält eine Referenz auf das „Oberhaupt“ vom Typ ScreenManager. Den Zugriff auf die Content Pipeline gewährt der bekannte Content Manager. Das Graphics Device übernimmt wie bisher die Grafikausgabe. Alle Referenzen weist der Screen Manager, wenn dieser ein neues Screen-Objekt über die AddScreen- Methode entgegennimmt, zu. In welchem Zustand sich ein Screen befindet, gibt eine Konstante der ScreenStates-Enumeration an. Die Zustände Active und Hidden geben an, ob der Screen Manager die Inhalte rendern soll. Loading und Closing aktivieren die Übergangsphasen zwischen zwei Screens. Zum Beispiel sind sanfte Einblendungen denkbar.
Die Screen-Objekte aktualisieren
Der Update-Methode wird eine Standardlogik verpasst, die die Stati eines Screens verwaltet. Pro Frame gibt das ScreenManager- Objekt jedem Screen neben der verstrichenen Zeitperiode zusätzlich die Information mit, ob die Ebene den Eingabefokus erhält oder eine andere Ebene diese überdeckt. Ein Übergang tritt dann ein, wenn der Screen geladen oder geschlossen wird. Den Zustand der Überblendung steuert die UpdateBlending-Methode. Sie gibt einen booleschen Wert zurück, um das Ende des Vorgangs zu signalisieren. Deswegen bleibt ein Screen-Objekt so lange im Speicher bis die Überblendung beim Schließen einer Ebene abgeschlossen ist. Anschließend löscht sich eine Ebene selbst aus der Liste des ScreenManager-Objekts.
Aktualisierung der Screen-Stati (Listing 1):
public virtual void Update(GameTime oGameTime,bool IsHidden, bool bHasFocus){m_bHasFocus = bHasFocus;if (m_bClosing)if (!UpdateBlending(oGameTime, this.BlendOutTime,BlendMode.BlendOut))this.State = ScreenStates.Closing;else{this.Manager.RemoveScreen(this);m_bClosing = false;}else if (IsHidden)if (!UpdateBlending(oGameTime, this.BlendOutTime,BlendMode.BlendOut))this.State = ScreenStates.Closing;elsethis.State = ScreenStates.Hidden;elseif(!UpdateBlending(oGameTime, this.BlendInTime,BlendMode.BlendIn))this.State = ScreenStates.Loading;elsethis.State = ScreenStates.Active;}
Bekommt die Ebene das Signal, dass sie verdeckt wird, tritt ebenfalls eine Überblendung ein, wobei der Status danach auf ScreenStates.Hidden gesetzt wird. Als Konsequenz erspart sich die ScreenManager- Klasse das Rendern dieser Ebene. Bleiben die vorherigen zwei Ereignisse aus, erhält eine Ebene den Status Screen- States.Loading, so lange die Überblendung anhält, andernfalls gilt sie als aktiv.
Überblendungszustand
UpdateBlending berechnet den aktuellen Überblendungszustand. 0 beschreibt vollständig eingeblendete Ebenen und 1 entspricht einer ausgeblendeten Ebene. Neben dem GameTime-Objekt erhält die Methode eine TimeSpan-Struktur, welche die Dauer der Überblendung definiert. Das letzte Argument vom Typ BlendMode gibt die Richtung der Überblendung in Form zweier Konstanten vor, die die Werte -1 und 1 annehmen.
protected virtual bool UpdateBlending(GameTime oGameTime,TimeSpan oTime, BlendMode oBlendMode){float fBlendingStep = 1.0f;if (oTime != TimeSpan.Zero)fBlendingStep =(float)(oGameTime.ElapsedGameTime.TotalMilliseconds /oTime.TotalMilliseconds);this.BlendState += fBlendingStep * (int)oBlendMode;if (this.BlendState < 0 || this.BlendState > 1){this.BlendState = MathHelper.Clamp(this.BlendState,0.0f, 1.0f);return true;}return false;}
MathHelper ist eine Klasse des XNA Framework. Die Methode Clamp hält Werte in einem fest definierten Wertebereich. Mithilfe des Überblendfaktors wird eine Color-Struktur generiert, dessen Alpha-Kanal in Relation zum Zustand des Screen-Objekts steht. Sprites sind unsichtbar, wenn die Ebene ausgeblendet ist. Wechselt eine Ebene in den aktiven Modus, dann werden alle Sprites langsam eingeblendet. Die unten ersichtliche Eigenschaft berechnet den Alphawert als Byte und die Color-Struktur nimmt diesen im Konstruktor entgegen:
public byte BlendAlpha{get { return (byte)(255 - this.BlendState * 255); }}<h5>State Controlling</h5>
Die ScreenManager-Klasse ist als DrawableGameComponent konzipiert, sodass in einem neuen Projekt die Components- Auflistung innerhalb der Game-Klasse lediglich um eine Instanz dieser Klasse erweitern werden muss. Das Objekt ruft über den Service Container die Referenz des Graphic Device ab und benutzt den im ersten Teil selbst implementierten Dienst IContentService, um an das ContentManager- Objekt zu gelangen. Alle Ebenen lagern in einer generischen Liste. Für jedes gelistete Objekt reicht der Screen Manager die Anweisungen LoadGraphicsContent, UnloadGraphicsContent, Update und Draw durch. Zudem instanziiert der Screen Manager ein SpriteBatch-Objekt, das beim Rendern an alle aktiven und sichtbaren Ebenen weitergereicht wird – dies bewirkt eine Reduzierung der Speicherauslastung.
Aktualisiert werden alle Screens von der obersten bis zur untersten Ebene. Die Eigenschaft IsOpaque eines Screens besagt dabei, ob die nachfolgenden Ebenen verdeckt werden. Zu Beginn erstellt die Update-Methode eine Kopie der Screen- Liste, um zu vermeiden, dass ein und derselbe Screen zweimal aktualisiert wird, weil die Aktualisierung einer Ebene dazu geführt hat, dass ein weiterer Screen in die Liste eingetragen wurde. ...









