26.02.2014 Aufrufe

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

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!