Mittwoch, 30. März 2011

Pong - C# XNA - Bitspielerei

Mit Pong ist es jetzt schon das dritte Minigame das wir innerhalb einer Woche umgesetzt haben. Diesmal stellen wir euch hier das Komplette Visual Studio 2008 Projekt als Download zur Verfügung.

Hier im Blog möchte ich nur einen kleinen Teil des Quellcodes vorstellen und euch die Arbeit auf Bit- und Byteebene etwas näher bringen.

Die Anzeigetafel:

Eine Ziffer der Anzeigetafel besteht aus 3 x 5 Feldern.

3 x 5 = 15

Insgesamt sind also 15 Felder für die Darstellung einer Ziffer nötig. Jedes dieser Felder kann entweder "leuchten" oder "aus" sein.
Das bedeutet, dass für die Anzeige einer Ziffer 15 Bits benötigt werden.

Die Signatur der Methode, die eine Ziffer zeichnen soll benötigt also nur einen Parameter und könnte so aussehen:

void DrawDigit(int bitField);

Soll in dieser Methode eine 8 gezeichnet werden muss also als Parameter

1 1 1
1 0 1
1 1 1
1 0 1
1 1 1

übergeben werden.

Zu beachten ist jetzt noch die Bitwertigkeit. Links oben soll sich das LSB (Least Significant Bit) befinden und rechts unten das MSB (Most Significant Bit).

Das heißt, der zu übergebende Wert ist 111101111101111, also 31727.

DrawDigit(31727); zeichnet eine 8.
Auf diese Art und Weise lässt sich also jedes beliebige Bild darstellen, das auf 3 x 15 Feldern passt. (Zum Beispiel Buchstaben und sonstige Symbole wie Smilies).

Die Komplette ausprogrammierte Methode zum Zeichen der Ziffer sieht dann folgendermaßen aus:
public void DrawDigit(int bitField)
{
   double count = 0;
   Vector2 startPos = new Vector2(0, 0);
   for (int i = 0; i < 5; i++)
   {
      for (int y = 0; y < 3; y++)
      {
         if ((bitField & (int)Math.Pow(2, count)) > 0)
            spriteBatch.Draw(mPixel, new Rectangle((int)startPos.X + 17 * y, (int)startPos.Y + 17 * i, 15, 15), Color.White);

         count++;
      }
   }
}

Den Quellcode findet ihr hier:
Download

Mission Sony Ericsson Xperia Play

In wenigen Tagen ist es soweit, das erste Handy mit Playstation-Zertifizierung kommt auf den Markt. Das Sony Ericsson Xperia Play.

Da zufälligerweise mein alter Vertrag am 4. April ausläuft und ich deswegen ein neues Handy + Vertrag brauche bietet sich das Xperia Play mit Erscheinungstermin 1. April geradezu für mich an.

Ich werde also versuchen mir am Freitag eines der begehrten (?) Exemplare zu sichern, um es anschließen ausgiebig zu testen.

Da es auch mein erstes Android-Handy sein wird, werde ich mich dann am Wochenende in die App-Programmierung für Android einarbeiten, um möglichst schnell eigene Software auf mein Handy zu bekommen ;) Und das Zocken wird dabei natürlich auch nicht zu kurz kommen.

Freut euch schon mal auf das erste Android-App ;)

Samstag, 26. März 2011

Snippet of the Week #1

Wir wollen euch ab heute, jeden Samstag, einen Codeausschnitt vorstellen den wir in der vergangenen Woche produziert haben und als hilfreich erachten.

Bei unserem ersten Snippet geht es um das Zeichnen eines Bildes mit transparentem Hintergrund unter Windows Mobile.

Als Ressource steht ein PNG zur Verfügung. Leider unterstüzt das .Net Comapct Framework keine Transparenz. Deswegen muss das im Code umgesetzt werden.

Wir befinden uns in der überschriebenen OnPaint-Methode eines Controls. Das Bild soll in unserem Beispiel auf einen schwarzen Hintergrund gezeichnet werden.

//Buffer Bitmap erstellen
if (mBufferBM == null)
     mBufferBM = new Bitmap(ClientSize.Width, ClientSize.Height, PixelFormat.Format32bppRgb);

Graphics gfOff = Graphics.FromImage(mBufferBM);
gfOff.Clear(mBackClearColor);

Image drawImg = null;
            
if (drawImg != null)
{
     ImageAttributes attr = new ImageAttributes();
     //Transparente Farbe ermitteln indem wir die Farbe des 
     //ersten Pixels (links oben) nehmen
     attr.SetColorKey(((Bitmap)drawImg).GetPixel(0, 0), ((Bitmap)drawImg).GetPixel(0, 0));
     //Das Bild auf das Buffer-Bitmap zeichnen
     gfOff.DrawImage(drawImg, new Rectangle(0, 0, iSize, iSize), 0, 0, drawImg.Width, drawImg.Height, GraphicsUnit.Pixel, attr);
        
}
            
e.Graphics.DrawImage(mBufferBM, 0, 0);

Tic Tac Toe in einer Stunde

Weil uns die Programmierung des Pacmanclones so viel Spaß bereitet hat, haben wir uns heute gleich an das nächste Minigame gemacht um euch zu zeigen, was innerhalb kurzer Zeit noch alles so gemacht werden kann.

Diesmal sollte es Tic Tac Toe sein. Die Zeit hatten wir diesmal vorher auf 1 Stunde beschränkt.

Wieder gibt es eine Java und eine C# - XNA Lösung.

Programmierzeit Java: 1 h 15 min
Programmierzeit C#: 57 min

Heute möchten wir etwas mehr auf den dabei entstandenen Code eingehen.

Anhand des Java-Beispiels möchten wir euch die TicTacToe-KI vorstellen. Man beachte bitte die begrenzte Zeit von einer Stunde und unsere absolute Priorität liegt bei der schnellen Programmierung.


    private void play() {
        for (int i = 0; i < field.length; i++) {
            int cpu = 0;
            int player = 0;
            int none = 0;
            for (int j = 0; j < field[i].length; j++) {
                switch (field[i][j]) {
                    case PLAYER:
                        player++;
                        break;

                    case CPU:
                        cpu++;
                        break;

                    case NONE:
                        none++;
                        break;
                }
            }
            if (cpu == 2 || player == 2) {
                for (int j = 0; j < field[i].length; j++) {
                    if (field[i][j] == NONE) {
                        set(i, j);
                        return;
                    }
                }
            }
        }

        for (int j = 0; j < field.length; j++) {
            int cpu = 0;
            int player = 0;
            int none = 0;
            for (int i = 0; i < field[j].length; i++) {
                switch (field[i][j]) {
                    case PLAYER:
                        player++;
                        break;

                    case CPU:
                        cpu++;
                        break;

                    case NONE:
                        none++;
                        break;
                }
            }
            if (cpu == 2 || player == 2) {
                for (int i = 0; i < field[j].length; i++) {
                    if (field[i][j] == NONE) {
                        set(i, j);
                        return;
                    }
                }
            }
        }

        int cpu = 0;
        int player = 0;
        int none = 0;
        for (int i = 0; i < field.length; i++) {
            switch (field[i][i]) {
                case PLAYER:
                    player++;
                    break;

                case CPU:
                    cpu++;
                    break;

                case NONE:
                    none++;
                    break;
            }
        }
        if (cpu == 2 || player == 2) {
            for (int i = 0; i < field.length; i++) {
                if (field[i][i] == NONE) {
                    set(i, i);
                    return;
                }
            }
        }

        cpu = 0;
        player = 0;
        none = 0;

        for (int i = 0; i < field.length; i++) {
            switch (field[i][2 - i]) {
                case PLAYER:
                    player++;
                    break;

                case CPU:
                    cpu++;
                    break;

                case NONE:
                    none++;
                    break;
            }
        }
        if (cpu == 2 || player == 2) {
            for (int i = 0; i < field.length; i++) {
                if (field[i][2 - i] == NONE) {
                    set(i, 2 - i);
                    return;
                }
            }
        }

        boolean set = false;
        while (!set) {
            int x = (int) (3 * Math.random());
            int y = (int) (3 * Math.random());
            if (field[x][y] == NONE) {
                set(x, y);
                set = true;
            }
        }
        checkWon(CPU);
    }


Die beiden Versionen im Video:

C#:

Java:

Freitag, 25. März 2011

Pacman-Speedcoding

Pacman programmieren in 4 Stunden? Unmöglich? NEIN!

Diese unvorstellbar schwere Aufagbe haben wir uns vorgenommen um nach Feierabend ein wenig zu erholen. (Manchen das auch andere Leute, mit anderen Berufen? Zieht ein Maruer nach Feiberabend aus Lust an der Freude noch schnell ne Mauer hoch?)

Und es hat mehr oder weniger auch geklappt.

Heute möchten wir euch die Ergebnisse vorstellen.

Version 1:
Programmiert in Java mit Java2D
Vorbereitung:
  • 31 Tiles mit der Grösse 25x25 zeichnen
Stunde 1:
  • Objekttyp Level mit dazugehöriger Lademethode
  • Klasse JPacApp erstellt und in der Main alle Ressourcen einlesen lassen :)
Stunde 2:
  • Vorschau Control mit Levelauswahl
  • Klasse Figure, Pacman und Ghost
Stunde 3:
  • Levelfenster
  • Logikthread, in den alles Sonstige irgendwie reingeschmissen wurde
  • Bewegungen und Kollision für Pacman
  • 3 Minuten durchsuchen der File nach einem Codestück (Folge der Schweinerei :))
Stunde 4:
  • Bewegung und Kollision für die Geister
  • Erster Programmstart...
  • Pacman stockt (aufgrund der Unterschätzung der Genauigkeit von Doublewerten) und ist aus zunächst unerklärlichen Gründen extrem schnell, Geister finden sich nicht zurecht
  • Stocken gelöst, Geister wissen wo es langgeht
  • Zeit vorbei!
Zusatz:
  • Aus Langeweile Leveleditor geschrieben

Version 2:
Programmiert in C# mit XNA.
Stunde 1:
  • XNA-Gaming Studio heruntergeladen und installiert
  • Pacman Grafiken erstellt
  • Pacmansteuerung implementiert
Stunde 2:
  • Spielfeld programmiert
  • Pacmansteuerung überarbeitet (Jetzt bleibt er auch innerhalb des Fensters)
  • Pacmansteuerung überarbeitet (Jetzt bleibt er auch innerhalb des Spielfeldes)
  • Pacmansteuerung überarbeitet (Jetzt kann er sogar nach oben laufen -.-)
Stunde 3:
  • Spielfeld um Punkte und Speedpunkte erweitert
  • Geister erstellt
  • Geister-KI implementiert (Geister können durch Wände laufen .. it's not a bug.. hmm oder doch)
Stunde 4:
  • Geister-KI "verbessert" (Um den Schwierigkeitsgrad etwas zu senken, können die Geister nicht mehr durch Wände laufen. Sie finden jetzt aber auch den Ausgang ihres Hauses nicht. IT'S NOT A BUG...)
  • Zeit vorbei!


     It's your turn! 4 Stunden, ab JETZT!

    Sex, Drugs and Code - A Developers Life

    Das Leben eines Programmiers. Wie stellen sich die Nicht-Nerds unter uns das vor? .. Stundenlanges, stupides herumhacken auf der Tastatur, wie gefangen in einer while(true)-Schleife? Sozial isoliert, ohne Freunde und Interessen außerhalb des WWWs?

    Ok, das lässt sich nicht komplett abstreiten, das ist aber nur die halbe Wahrheit. Wir zeigen euch die andere, aufregende Seite des Coderdaseins.

    Also.. Let's rock.. ähm.. code mein ich ;)