In diesem Artikel erkläre ich, wie ich das Interface für mein Projekt implementiert habe.
Einleitung
Wer mit C# bereits Windows Anwendungen erstellt hat, wird in XNA den Komfort von fertigen Schaltflächen vermissen. Hier gibt es keine Button Klasse, welche sich benutzen lässt. Jedoch gibt es eine Möglichkeit, mit XNA in einer Form zu rendern und dort auf die aus den Winforms bekannten Klassen zuzugreifen. Dies ist jedoch nicht Bestandteil des Artikels.
Die Hintergrundmaske
Eine Hintergrundmaske ist eine schwarze Textur mit eingefärbten Bereichen. Diese Bereiche stellen die Schaltflächen dar (siehe Bild 1). Jeder Bereich hat eine eigene Farbe, auch wenn dies mit dem Auge nicht erkennbar ist. Bei einem Klick wird nun der Farbwert des angeklickten Pixels ausgelesen und damit die auszuführende Aktion festgelegt. Die Hintergrundmaske selber wird nicht gezeichnet, da sie nur zur Auswertung der angeklickten Bereiche dient. Anstelle der Maske wird das eigentliche Hintergrundbild und die Schaltflächen gezeichnet.
Implementation
Einlesen der Pixelinformationen
Zuerst müssen wir ein Array erzeugen, welches jeden Pixel der Textur speichern kann. In der zweiten Zeile wird dieses Array mit den Informationen aus der Textur gefüllt. MaskTexture enthält die Grafik der Hintergrundmaske und ist vom Typ Texture2D. Das Laden der Textur wird hier nicht gezeigt.
Code: Alles auswählen
private uint[] MaskData;
private Texture2D MaskTexture;
public void GetMaskData()
{
this.MaskData = new uint[this.MaskTexture.Width * this.MaskTexture.Height];
this.MaskTexture.GetData<uint>(this.MaskData);
}
Nachdem wir die Pixel in unserem Array gespeichert haben, können wir nun die Farbe auslesen. Dazu bestimmen wir zuerst die Position auf der Textur, wo wir geklickt haben. Es ist wichtig, dass bei diesem Vorgehen die Hintergrundmaske die volle Größe des Fensters einnimmt, da sich sonst die Berechnung der Position verändern würde. Im zweiten Schritt formatieren wir den Farbwert in das Hex-Format um. Die Parameter sind die X- und Y-Koordinaten der Maus.
Code: Alles auswählen
public string GetMaskPixelColor(int xCoordinate, int yCoordinate)
{
uint Position = Convert.ToUInt32(yCoordinate) * Convert.ToUInt32(this.MaskTexture.Width) + Convert.ToUInt32(xCoordinate);
return String.Format("{0:x2}", MaskData[Position]);
}
Das ist der leichteste Teil. Wir fragen über das Switch-Konstrukt die aktuelle Farbe ab und reagieren entsprechend.
Code: Alles auswählen
switch (GetMaskPixelColor(xCoordinate, yCoordinate))
{
// Schaltfläche 1
case "ff646464":
// Hier abfragen ob Mausklick gemacht wurde und entsprechend reagieren
break;
// Schaltfläche 2
case "ff6e6e6e":
// Hier abfragen ob Mausklick gemacht wurde und entsprechend reagieren
break;
}
Vorteile
- beliebig Komplexe Buttons möglich
- Design lässt sich ohne Änderungen im Code verändern, es muss nur die neue Grafik eingebunden werden
- Lässt sich mit der Alternative kombinieren für komplexere Buttons bei der Alternative.
- schwerer zu implementieren als die Alternative (siehe unten)
Wer nur einfache Schaltflächen darstellen möchte, oder eine veränderbares Interface hat, kann auch auf die Klasse Rectangle zurückgreifen und mithilfe der Intersect Methode prüfen, welches Rechteck angeklickt wurde.
Anmerkungen
Ich habe den Code nicht 1:1 aus meinem Projekt übernommen um ihn lesbarer zu machen und hoffe dabei keine Fehler eingebaut zu haben.
Wollt ihr Hovereffekte für die Schaltflächen erstellen, dann solltet ihr die Methode GetMaskPixelColor immer in eurer Update Methode des Spiels aufrufen, könnt ihr jedoch auf diese Spielerei verzichten, dann braucht ihr GetMaskPixelColor erst beim Betätigen einer Maustaste aufrufen.
Gruß Thomas
Update 1
Ich habe nun eine Zip-Datei angehängt, die eine Klassendatei beinhaltet. Diese Klasse setzt das oben beschriebene um.
Es kann entweder im Konstruktor oder aber über eine Eigenschaft die Textur zugewiesen werden und über die Methode GetColor() lässt sich die Farbe der übergebenenen Koordinaten bestimmen.
Update 2
Ich habe die Vor- und Nachteile dieser Methode aus der Diskussion ergänzt und die Alternative aufgeführt.