Sonntag, 12. Februar 2012


Artikel

Mai 2008 | Artikel

Get rich and famous, be a game designer! Fortsetzung, Teil 4

Teil 1   Teil 2   Teil 3   Teil 4   Teil 5   

Der Screen Manager im Einsatz

Damit der Screen Manager seine Arbeit beginnen kann, wird die Klasse in der Initialize-Methode der Game-Ableitung instanziert. Die Components-Auflistung, von der bereits im ersten Teil der Serie die Rede war, wird um dieses Objekt erweitert. Die AddScreen-Methode übergibt dem Screen-Manager eine Instanz der BackgroundScreen-Klasse. Der Screen- Manager wird anschließend an die Components- Auflistung gehängt (Listing 7):

  1. protected override void Initialize()
  2. {
  3. m_oScreenManager = new ScreenManager(this);
  4. m_oScreenManager.AddScreen(
  5. new BackgroundScreen());
  6. this.Components.Add(m_oScreenManager);
  7. base.Initialize();
  8. }
Kollisionskontrolle

Beim Konstrukt Bounding Box handelt es sich um einen imaginären Quader, der das komplette Modell umschließt. Eine Bounding Box reduziert die Silhouette auf eine einfache geometrische Form, die durch zwei Vektoren beschrieben werden kann. Im Sektor der zweidimensionalen Grafikausgabe kommt an Stelle eines Quaders ein Rechteck zum Einsatz. Zudem ist die Abstraktion auf diese geometrische Form nicht ganz so weit hergeholt, wie im 3DBereich, denn der Inhalt einer Grafikdatei ist immer rechteckig.

Eine Kollision liegt dann vor, wenn sich zwei Rechtecke überschneiden. Die Vorteile dieser Erkennungsmethode liegen klar auf der Hand. Das dahinter liegende mathematische Konzept ist nicht allzu kompliziert, der Computer führt die Berechnungen zügig durch. Ein Nachteil ist der Verlust von Detailinformationen. Stellen die Grafiken Billardkugeln dar und eine Kollisionskontrolle verläuft positiv, so ist damit noch nicht sichergestellt, dass die Kugeln auf dem Bildschirm wirklich aneinandergeprallt sind, da die Grafiken transparente Pixel enthalten. Hat das Programm eine Schnittmenge zwischen zwei Rechtecken ermittelt, ist es ratsam im Anschluss daran eine detaillierte Kollisionskontrolle durchzuführen. Das bedeutet ein Vergleich aller Pixel.

Die Rectangle-Struktur ist der prädestinierte Datentyp des .NET Framework, mit dessen Hilfe sich die Position und die Ausmaße einer Grafik beschreiben lassen. Dabei muss berücksichtigt werden, dass die X- und Y-Koordinaten der Position des Sprite auf dem Back Buffer entsprechen. Der Einfachheit halber wird im Folgenden der Ursprung (0, 0) vorausgesetzt. Die folgende Befehlsfolge bereitet die Daten auf die Kollisionsprüfung vor:

  1. Rectangle oDestinationRect = new Rectangle(
  2. m_oPosition.X, m_oPosition.Y,
  3. m_oTexture.Width, m_oTexture.Height)

Zu Beginn werden die maximalen bzw. minimalen Werte für alle Seiten ermittelt. Sobald die oberste Kante des neuen imaginären Rechtecks kleiner ist als die unterste Kante sowie die Linke kleiner ist als die Rechte, liegt eine Kollision vor. Die Kollisionskontrolle auf Per-Pixel- Basis prüft alle Pixel, die im Schnittbereich zweier Rechtecke liegen. Sobald zwei Pixel nicht transparent sind, liegt eine Kollision vor. Die Pixel-Informationen gibt die GetData-Methode eines Texture2D-Objekts zurück:

  1. Color[] m_oPixels = new Color[m_oTexture.Width *
  2. m_oTexture.Height];
  3. m_oTexture.GetData<Color>(m_oPixels)

Wird eine Überlappung zweier Rechtecke festgestellt, gilt es die erforderlichen Pixel-Daten aus dem Array zu extrahieren. Das Grundgerüst bilden zwei For- Schleifen, die alle Koordinaten des neuen Rechtecks durchlaufen. Anhand dieser Koordinaten lässt sich der Index des Pixels errechnen (Abbildung 5):

Anhand jener Koordinaten und der Koordinaten des jeweiligen Rechtecks werden die Spalten- und Zeilennummer extrahiert. Zu der Spaltennummer wird das Produkt aus der Zeilennummer und der Pixelanzahl pro Zeile addiert.

Diese Methode besitzt aber einen Nachteil: Sie ist nicht fähig, transformierte und skalierte Sprites auf eine Kollision hin zu prüfen. Weil das Beispielprojekt keinen Gebrauch von skalierten und rotierten Sprites macht, genügt die Prüfung aus Listing 9.

Kollisionsprüfung zwischen zwei imaginären Rechtecken (Listing 8):

  1. int iTop = Math.Max(oRectA.Top, oRectB.Top);
  2. int iBottom = Math.Min(oRectA.Bottom, oRectB.Bottom);
  3. int iLeft = Math.Max(oRectA.Left, oRectB.Left);
  4. int iRight = Math.Min(oRectA.Right, oRectB.Right);
  5. if (iTop <= iBottom && iLeft <= iRight)
  6. return true;
  7. else
  8. return false;

Kollisionsprüfung auf Per-Pixel-Basis (Listing 9):

  1. for (int iY = iTop; iY < iBottom; iY++)
  2. for (int iX = iLeft; iX < iRight; iX++)
  3. {
  4. Color oPixelA = this.Pixels[(iX - this.DestinationRect
  5. .Left) +
  6. (iY - this.DestinationRect.Top) * this.Width];
  7. Color oPixelB =
  8. oObject.Pixels[(iX - oObject.DestinationRect.Left) +
  9. (iY - oObject.DestinationRect.Top) * oObject.Width];
  10. if (oPixelA.A != 0 && oPixelB.A != 0)
  11. return true;
  12. }

Teil 1   Teil 2   Teil 3   Teil 4   Teil 5   

Kommentare

Gravatar reifrund 17.02.2011
um 02:27 Uhr
Guter Artikel. Ich würde es aber schöner finden, wenn die Beschriftungen in dem Bild vom Controller auch in deutscher Sprache wären. Natürlich muss das nicht sein, jeder User, der diese Seite regelmäßig besucht, müsste schließlich so viel englisch sprechen. Allerdings ein optisches Detail ... ;-) #zitieren