smart developer Ein Code für alle (Vorschau)
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
Entwicklung<br />
WP7-Entwicklung mit XNA<br />
Listing 4: Drawing in der Draw-Methode<br />
// Clear background in black<br />
GraphicsDevice.Clear(Color.Black);<br />
Collection wie im gezeigten <strong>Code</strong> via Touch-<br />
Panel.GetState() oder über Gestures, wenn<br />
man diese <strong>für</strong> sein Spiel aktivieren will.<br />
Wenn der User auf die linke Bildhälfte<br />
klickt, soll der aktuelle Block nach links bewegt<br />
werden, berührt der Spieler die rechte<br />
Bildschirmhälfte (X Position größer als 450<br />
Pixel), dann soll sich der Block nach rechts<br />
bewegen. Um dies auch gleich wieder mit F5<br />
(Start Projekt Hotkey in Visual Studio) testen<br />
zu können, sollte man zunächst den aktuellen<br />
Block auf den Bildschirm zeichnen (siehe<br />
Abschnitt Drawing), um zu testen, ob <strong>alle</strong>s<br />
bisher richtig läuft. Den restlichen <strong>Code</strong><br />
braucht man da<strong>für</strong> noch nicht.<br />
Als Nächstes überprüfen Sie über die Update-Methode,<br />
ob eine Viertelsekunde vergangen<br />
ist. Wenn ja, dann wird der restliche<br />
<strong>Code</strong> ausgeführt. Wie erwähnt, dient dieser<br />
Workaround dazu, den Block nicht 30-mal<br />
pro Sekunden nach unten bewegen zu müssen.<br />
Kann der Block ein Feld nach unten bewegt<br />
werden, dann tut dies die App – fertig.<br />
spriteBatch.Begin();<br />
// Place background in center (800 pixels width ‐ 512 pixels) / 2 = 144<br />
spriteBatch.Draw(background, new Vector2(144, 0), Color.White);<br />
// Draw all field blocks<br />
for (int x = 0; x < FieldWidth; x++)<br />
for (int y = 0; y < FieldHeight; y++)<br />
if (field[x,y])<br />
spriteBatch.Draw(block, GetBlockRect(x, y), Color.DarkGray);<br />
// And finally also add the current block<br />
spriteBatch.Draw(block, GetBlockRect(currentBlockX, currentBlockY),<br />
Color.White);<br />
spriteBatch.End();<br />
Listing 5: Die Hilfsfunktion GetBlockRect<br />
/// <br />
/// Get block position and rectangle for the current block or a field block<br />
/// <br />
private Rectangle GetBlockRect(int x, int y)<br />
{<br />
// Place blocks in center (800 pixels width ‐ 480 pixels height) / 2<br />
// Note: Reduced to 477 to make 9*53 fit into 477 (480 would have spaces)<br />
return new Rectangle(162 + x * 477 / FieldWidth, y * 477 / FieldHeight,<br />
477 / FieldWidth, 477 / FieldHeight);<br />
} // GetBlockRect(x, y)<br />
Kompliziert wird es erst wieder, wenn wir<br />
ganz unten angelangt sind oder auf dem Zielfeld<br />
bereits ein Block existiert. Dann stoppt<br />
die App den aktuellen Block und brennt ihn<br />
in das Feld. Schlussendlich wird noch überprüft,<br />
ob wir eine komplette Zeile von links<br />
nach rechts gefüllt haben und wenn dies der<br />
Fall ist, wird die gesamte Zeile gelöscht und<br />
das Spielfeld darüber einen Block nach unten<br />
verschoben.<br />
Drawing<br />
Wir sind nun fast fertig, aber ohne Draw-<strong>Code</strong><br />
sehen wir noch nichts auf dem Bildschirm,<br />
nur nach wie vor den hellblauen Standard-<br />
Hintergrund des erstellten XNA-Projektes.<br />
Zunächst löschen wir den Hintergrund in<br />
Schwarz und dann zeichnen wir die Spielelemente<br />
auf die Zeichenfläche (Listing 4). In<br />
2D-XNA benutzt man dazu die SpriteBatch-<br />
Klasse, welche mehrere Draw-Calls zusammenfasst<br />
und <strong>für</strong> uns optimiert. Nachdem<br />
der spriteBatch per Begin gestartet wurde,<br />
erscheint das SpaceBackground-Hintergrundbild<br />
zentriert.<br />
Als Nächstes zeichnen wir <strong>alle</strong> 9x9-Feld-<br />
Blöcke (am Anfang noch leer). Sobald der<br />
Spieler jedoch ein paar Blöcke gefüllt hat,<br />
werden hier mehr und mehr Blöcke gezeichnet<br />
(Abbildung 1). Sobald eine Zeile voll ist<br />
und wieder gelöscht wurde, vereinfacht sich<br />
das Spielfeld natürlich wieder. Das Letzte<br />
was noch getan werden muss, ist den aktuellen<br />
beweglichen Block zu zeichnen. Beim fixierten<br />
Feld wurde die Farbe Color.DarkGray<br />
benutzt, beim aktuellen Block hingegen die<br />
Farbe Color.White. So kann man leicht auseinanderhalten,<br />
welcher Block momentan der<br />
Ideal <strong>für</strong> <strong>Ein</strong>steiger<br />
Das hier beschriebene Spiel ist in etwa ein bis<br />
zwei Stunden Programmierarbeit entstanden.<br />
Es wurde par<strong>alle</strong>l zu diesem Artikel geschrieben<br />
und es gibt nicht nur eine XNA-Version <strong>für</strong><br />
WP7, sondern auch eine Variante mit der Delta<br />
Engine, die auf <strong>alle</strong>n Plattformen läuft. Wichtig<br />
ist, dass man sich klare Ziele setzt und konstant<br />
testet, ob das gewünschte Ergebnis in die<br />
richtige Richtung geht. Bei uns im Team benutzen<br />
wir viele Tausende Unit-Tests, um kleine<br />
Teile zu testen, und selbst bei diesem kleinen<br />
Spiel macht es Sinn, die <strong>Ein</strong>zelteile separat zu<br />
testen (GetBlockRect, Spiellogik, Drawing, Current<br />
Block, Block Field, etc.). Alternativ kann<br />
man sich, auch wie in diesem Artikel beschrieben,<br />
langsam hocharbeiten und einzelne Probleme<br />
nacheinander lösen (erst Visual Studio<br />
installieren, dann XNA Projekt erstellen, dann<br />
testen, dann aktuellen Block hinzufügen, etc.).<br />
64<br />
02/2011 <strong>smart</strong>-<strong>developer</strong>.de