Freitag, 4. Februar 2011

Googles Blogger-App jetzt im Android-Market verfügbar!

Seit kurzem dürfen sich Android-User auch unterwegs per Smartphone auf bequeme Weise ihrem Blogger-Blog widmen.

Google hat jetzt die hauseigene Blogger-App über den Android-Market freigegeben. Wie sie sich im Alltag schlägt probiere ich gerade mit diesem Blogeintrag aus!

Die App ist sehr übersichtlich und einfach aufgebaut. Beim ersten Start wählt man sein Google-Konto aus und die App holt sich die damit assoziierten Blogger-Blogs.

Die App von oben links nach unten rechts:

- Blogger-Logo
- Stift-Symbol zum erstellen eines neuen Blogeintrags.
- Listenübersicht alles (mobiler!!!) Blogeinträge und -entwürfe
- Darunter ein Dropdown-Menü zur Auswahl der Blogs
- Ein Eingabefeld für die Überschrift des Posts
- Das Post-Eingabefeld an sich.

Jetzt beginnen die Goodies, welche hoffentlich mit weiteren Versionen reicher ausfallen.

Momentan haben wir:

- Mögleichkeit zur Aufnahme von Bildern über die Kamera
- Möglickeit zur Auswahl eines Galleriebildes

Dann folgt noch ein Label-Feld, sowie die Möglichkeit den eigenen Standort frei zu geben, an dem man den Blogeintrag erstellt hat. Grösstes Manko welches mir eben aufgefallen ist:
Man kann nur aus einer vorhandenen Liste aus Vorschlägen den Standort auswählen, aber diesen nicht direkt hier editieren bzw. Alternativen suchen. Hoffentlich wird das noch erweitert.

Letztendlich folgt noch ein Button zur Veröffentlichung, welchen ich gleich mal betätigen werde, ein Speichern-Button zum manuellen sichern eures Entwurfes und ein Lösch-Button.

Die App speichert euren Fortschritt auch automatisch, sobald die App bzw. die Editor-Activity den Fokus verliert - man z.B. in die Listenansicht wechselt, oder auf den Homescreen, etc.

Noch ist die App komplett auf Englisch, aber aufgrund der wenigen Bedienelemente auch für Leute ohne Englisch-Kenntnisse in meinen Augen leicht bedienbar.

Die App kann man im Android-Market über euer Smartphone, oder ganz neu, über die Android-Market-Website auf dem Computer direkt auf das Smartphone schicken lassen und ist auch komplett kostenlos - wie alle Apps direkt von Google.

Hier gehts zum Market:

http://market.android.com/details?id=com.google.android.apps.blogger

- Edit: URLs werden leider nicht automatisch in Links konvertiert... Ich versuche es mal mit HTML-Tags (leider habe ich in der App noch keine Text-Edit-Werkzeuge gefunden, somit sind zur Zeit nur ganz formatlose Texte ohne grossen Aufwand erstellbar)

- Edit #2: Auch HTML wird nicht erkannt, sondern direkt als Text ausgegeben... :-(

Dienstag, 1. Februar 2011

Sunset of Sunrise - Ein Bilderbuch der Jahre 2007 und früher...

Mit diesem Post führe ich nun zu Ende, was im Grunde schon seit langer Zeit beendet scheint.

Ich habe in den früheren Jahren öfters an anderen Projekten gearbeitet und vieles ausprobiert.
Eines dieser Projekte war mein alter Blog "Sunrise" auf dem ich meine privaten 3D-Modelle und 3D-Graphik-Collagen präsentiert habe.
Leider wurde dieses Projekt zu einer Zeit von mir ins Leben gerufen, in der ich keine Zeit dafür gefunden habe. So geschah es, dass ich auch bald das Interesse daran verlor und der Blog auch keine neuen Inhalte mehr spendierte.

Zusätzlich zum mangelnden Interesse kam noch hinzu, dass ich die Blog-Software selbst administrieren musste - sie ist mittlerweile veraltet und wird von Spam-Bots überrannt! ;-)

Damit ich den alten Blog offline nehmen, aber die "Schätze" der damaligen Zeit retten kann, präsentiere ich euch nun die wenigen Arbeiten, welche ihren Weg auf meinen alten Blog gefunden haben.



Das erste 3D Modell stammt von Anfang 2000 und ist eine Hommage an eines meiner lieblings Videospiele vergangener Tage:

Nintendos Super Mario Kart

Nebenbei zeigen die Renderings auch das Go-Kart welches mir persönlich noch am besten gefiel (Version SuperNintendo / Nintendo 64).

Alles was danach kam war irgendwie albern... ^_^



Einmal von vorne mit eingeschlagenem Lenkrad...


 ... und die Ansicht von hinten... auch mit eingeschlagenem Lenkrad!



Und wenn wir schon bei Videospielen sind:

Ja, ich bin ein wenig Nintendo-geschädigt. Anders als Sony und Microsoft hat mich Nintendos Videospielewelt immer fasziniert und inspiriert. Nur Sega konnte da mithalten - was aber nicht bedeuten soll, dass Sony und Microsoft schlechte Spiele / Konsolen produzieren, aber mir fehlt da irgendwie dieses gewisse Etwas.

Na ja, zurück zum Thema:

Was wäre Nintendo ohne Super Mario? Gute Frage...
Aber noch viel wichtiger: Was wäre Super Mario ohne Gegner, auf die er springen kann? Wahrscheinlich noch dicker... Einer seiner bekanntesten personal Trainer ist sehr putzige Goomba.

Am Anfang stand die Zeichnung... danach folgte das Nachmodellieren - zuerst möglichst einfach und low-Poly wurden die wichtigsten Ecken und Kanten ausgearbeitet...


... danach mittels Mesh-Smooth die Sache abrundet.

Mit welcher 3d studio max Version ist das modelliert habe weiß ich aber leider nicht mehr!


Hier noch eine Matching-Ansicht bei der man gut erkennt, dass ich einigermaßen akkurat meine Zeichnung getroffen habe!



Als Nächstes folgt dann ein 3D Modell eines Schachspiels. Vieles gibt es dazu nicht zu sagen.

Alle Spielfiguren und das Brett sind self-made. Sogar das 3-S-E Logo ist zu erkennen.


Hier die Nahansicht der Spielfiguren...

... selbe Ansicht als Drahtgittermodell-Version.



So, dieses Modell ist, wie man hoffentlich erkennt, ein Fass.

Leider wurde weder das Fass noch die Szene dazu jemals fertig. Nichtsdestotrotz habe ich bei der Erstellung des Fasses ein paar nette Techniken beim Modellieren gelernt.


Dann noch ein Rendering einer Wüstenszene.
Der morgendliche Nebel wurde mit Photoshop nachträglich eingefügt.



Das Modell selbst ist eine 3ds studio max Szene.


Und zu guter Letzt noch ein Logo für einen ehemaligen Kommilitonen, welcher ein Pro im Schachsport ist.

Dieses Logo sollte seinem Heimatverein dienen, ob es je benutzt wurde? Ich weiß es nicht.

Auch dieses Logo ist schon in die Jahre gekommen und heute hätte ich vieles anders gemacht. Erstellt wurde es mit 3ds max und nachbearbeitet in Photoshop.

Sonntag, 23. Januar 2011

Java - Nicht blockierende Konsolen-Eingabe mit BufferReader

Es ist schon erstaunlich, da sitze ich am ersten richtigen Tutorial / Artikel für meinen Entwicklerblog und möchte euch auf einfache Art und Weise etwas über Determinismus in einem Spiele-Mail-Loop erzählen, da hält mich doch Tatsächlich die Eingabe eines beliebigen Zeichens von der Tastatur eine Stunde lang auf. Man möchte meinen, dass in Zeiten von Touchscreens, Gestenerkennung und den ersten Schritten in der mentalen Steuerung von Programmen, eine simple Tastatureingabe in der Kommandozeile, keine zwei Zeilen Quellcode erfordert.

Weit gefehlt... Und somit ist mein erster richtiger Artikel dieser hier geworden. Das ist einerseits auch nicht verkehrt, andererseits auch nötig, damit im zweiten Artikel zum Thema "Prinzipien einer deterministischen Spiele-Main-Loops" jeder versteht, wie die Tastatureingabe realisiert wurde. Also los!

Da ich den Quellcode für den Artikel mit Java schreibe (da ich z.Z. für Android programmiere - woraus auch die Ideen für die nachfolgenden Blog-Einträge stammen - liegt es nahe Java zu benutzen), habe ich nach einer einfachen Art gesucht Zeichen von der Tastatur auszulesen. Die Java-Klasse "BufferReader" gibt hierfür eine sehr einfache Art der Eingabe von Strings vor.

import java.io.BufferedReader;
import java.io.InputStreamReader;

// ...

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

// ...

String input = this.in.readLine();

// ...

Das Problem: Das Auslesen der Keyboard-Eingabe mit readLine() ist blockierend, sprich: Sobald das readLine() ausgeführt wird, verharrt das Programm in dieser Methode bis man auf der Tastatur die eingegebene Zeile mit Enter abschließt. Erst dann kehrt der Programmzeiger zurück und der Quellcode unterhalb von readLine() wird ausgeführt.

Die Motivation: Diese Art der Ausführung ist nicht gerade vorteilhaft, wenn man z.B. einen Game-Main-Loop programmieren möchte, wie ich es für den nächsten Artikel vorhabe. So ein Game-Main-Loop soll ja möglichst schnell und ohne Unterbrechungen immer wieder durchlaufen. Wenn ihr ein z.B. einen Shooter spielt, wollt ihr ja schließlich auch nicht, dass sich eure Figur, die Gegner, die zerstörbaren Objekte etc. erst dann um einen kleinen Schritt verändern / bewegen, wenn ihr auf die Enter-Taste drückt. Dass soll jetzt nur ein Beispiel sein, man könnte das noch auf vieles andere übertragen. Der Kern der Aussage ist jedoch, dass es unvorteilhaft ist, wenn das Programm augenscheinlich stehen bleibt und sich solange nichts mehr tut, bis man Enter betätigt hat.

Die Lösung: Ich habe mich im Internet umgeschaut und habe auf eine ein bis zwei Zeilen lange Lösung gehofft. Leider waren fast alle brauchbaren Lösungen auf Server-Klient-Applikationen beschränkt und es wurde geraten einfach den Socket zu schließen um aus readLine() raus zu kommen. Total nutzlos für mein Vorhaben, weil mein deterministischer Game Loop keine Sockets braucht! ;)
Also habe ich, entgegen meiner vorhergehenden Planung im ersten Game-Mail-Loop Artikel diese Technik nicht anwenden zu wollen, die Sache mit Threads gelöst.

Kontrekt heißt das, dass ich den BufferReader in eine eigene Klasse ausgelagert habe, welche von der Thread-Klasse erbt und readLine() in der run() Methode aufruft:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

// Für die nicht blockierende Keyboard-Abfrage erben wir von der Thread-Klasse
class NonBlockingBufferReader extends Thread {

    // Erzeigen ein BufferReader-Objekt "in"
    private BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

    // Deklarieren eine String-Variable "input", welche unsere Keyboard-Eingabe speichert
    private String input = "";

    // Diese Variable speichert, ob der Hauptschleifendurchlauf in der run() Methode 
    // wiederholt werden soll
    private boolean running = true;

    // Die von der Thread-Oberklasse (bzw. vom Runnable-Interface) vorgegebene run() Methode 
    // müssen wir hier noch überschreiben / implementieren.
    // Die run() Methode ist genau die Methode, welche in einem neuen Thread durchgeführt wird.
    // Sobald die Ausführung am Ende der run() Methode angekommen ist und diese verlässt, wird 
    // auch der Thread beendet.
    @Override
    public void run(){

        // Damit der Thread nicht nach einem Durchlauf beendet wird, 
        // haben wir hier eine (pseudo) Endlosschleife, welche von der oben deklarierten 
        // und initialisierten running-Variable gesteuert wird.
        while(this.running){
            try{
                // Hier wird das böse readLine() aufgerufen!
         this.input = this.in.readLine();
            }catch(IOException e){
                e.printStackTrace();
            }
        }

        System.out.println("## Closing NonBlockingReader! ##");
    }

    // Wir brauchen noch eine Methode, welche uns die ausgelesene Keyboard-Ausgabe 
    // aus dem Thread zurückgibt, um ihn im Hauptprogramm bzw. Hauptthread 
    // verarbeiten zu können.
    // Diese Methode ist synchronisiert, damit sie nicht auf die input-Variable zugreift,
    // während diese z.B. gerade von readLine() beschrieben wird - weil dann gibts Bit-Salat.
    public synchronized String getInput(){
        String tempInput = "";
        if(this.input != null){
            tempInput = this.input;
            this.input = "";
        }
        return tempInput;
    }
}

Diese Klasse enthält fast alles, was man braucht um im Hauptprogrammteil die Tastatureingabe auslesen zu können, ohne dass dort auf die Rückkehr aus readLine() gewartet werden muss.

Die Klasse erweitert die / erbt von der Thread-Klasse. Man könnte auch einfach das Runnable-Interface implementieren, doch dann erfordert das starten des Threads mehr Aufwand. Ich persönlich mag das erben von der Thread-Klasse lieber.

In beiden Fällen muss die run() Methode überschrieben / implementiert werden. Diese Methode wird beim Start des Threads ein Mal ausgeführt und der Thread danach ad acta gelegt. Damit das hier nicht passiert, weil wir ja dauerhaft unsere Keyboard-Eingabe abgreifen wollen, läuft in der run() Methode eine Endlosschleife. Im Quellcode habe ich im Kommentar geschrieben, dass es sich um eine Pseudo-Endlosschleife handelt. Das liegt daran, dass sie sehr wohl irgendwann aufhört, im Idealfall wenn die boolsche Variable "running" auf false gesetzt wird (oder euer Rechner abschmiert, ihr die Java-VM tötet etc. - das ist aber nicht der Idealfall).
Diese running-Variable wird jetzt noch nicht verändert, aber dazu kommen wir noch.

Die Nutzung dieser Klasse sieht z.B. so aus:

...

public static void main(String[] args){

    // Erzeugen des nichtblockierenden BufferReader Objektes
    NonBlockingBufferReader readKey = new NonBlockingBufferReader();

    // Starten des Threads
    readKey.start();

    // Auslesen der Eingabe
    String input = readKey.getInput();

    // Ausgabe der Eingabe auf der Konsole
    System.out.println("Input was: " + input);
}

...

Diese Nutzung ist natürlich nur ein Beispiel, wie die Klasse bzw. in welcher Reihenfolge die Methoden der Klasse zu nutzen sind. Im Praxiseinsatz würde die Main-Methode da druchrasen und das Programm wäre schneller beendet als ihr gucken könnt.

... beendet? Na ja, nicht ganz...

Obwohl die Main-Methode nach der Konsolenausgabe beendet ist, so läuft der Thread der NonBlockingBufferReader-Klasse noch munter weiter.

Um den Herr zu werden reicht es leider nicht aus einfach die running-Variable auf false zu setzen. Sobald der Programmzeiger die readLine() Methode erreicht hat, verschwindet er darin und wartet auf die nächste Zeileneingabe. Somit stimmt es nicht ganz, dass der Thread "munter weiter"-läuft. Er hängt wieder in readLine() fest. Das ist solange nicht schlimm, wie das Hauptprogramm irgendwas macht, weil sobald man etwas auf der Tastatur eingibt und Enter drückt, wird ja die input-Variable befüllt und kann vom Hauptprogramm wie oben gezeigt ausgelesen werden. Wenn aber das Hauptprogramm schon längst durch ist, verschlingt der Thread nur Resourcen und man hat ein super Leck geschaffen.
Die running-Variable hilft euch also nur, wenn der Programmzeiger gerade aus der readLine() Methode zurückkehrt und ihr genau jetzt über eine externe Methode die Variable ändert, bevor die while-Schleifenbedingung evaluiert wird.
Das ist allerdings ein Glücksspiel und absolut an der Praxis vorbei.

Das andere Problem: Die genutzte BufferReader-Klasse hat keine Methode, welche readLine() vorzeitig abbrechen lässt. Zwar gibt es die "close()" Methode, doch diese beendet die Ausführung nicht. Man muss also mindestens noch ein Mal etwas eingeben, damit readLine() zurückkehrt. Dann gibts aber eine unschöne Exception und das kann nicht das Ziel eines sauberen Programms sein.

Meine Lösung sieht deshalb so aus:


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

class NonBlockingBufferReader extends Thread {
    private BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    private String input = "";

    // Sobald dieser String eingegeben wird, wird der Thread beendet
    private String interruptKey = "x";

    private boolean running = true;

    // Mit diesem Konstruktor wird nicht nur das Objekt erzeugt, sondern
    // auch der String festgelegt, mit dem die Ausführung des Thread beendet wird.
    public NonBlockingBufferReader(String interruptKey) {
        this.interruptKey = interruptKey;
    }

    @Override
    public void run(){
        while(this.running){
            try{
                this.input = this.in.readLine();

                // Ist der eingegebene String gleich dem String für das Beenden,
                // so wird der Thread beendet!
                if(this.input.equalsIgnoreCase(this.interruptKey)){
                    this.in.close();
                    this.running = false;
  }
            }catch(IOException e){
                e.printStackTrace();
            }
        }

        System.out.println("## Closing NonBlockingReader! ##");
    }

    public synchronized String getInput(){
        String tempInput = "";
        if(this.input != null){
            tempInput = this.input;
            this.input = "";
        }
        return tempInput;
    }
}

Im Grunde ist das die erste Implementierung von oben. Die wesentlichen Änderungen sind hier das Einführen einer neuen Variable "interruptKey".

Diese Variable hält eine Zeichenkette (Eingabezeile) welche von der Tastatur durch readLine() eingelesen wird. Nachdem readLine() die Tastatureingabe gelesen hat, wird die Eingabe mit der interruptKey-Variable verglichen. Sind beide gleich, so werden zum einen alle Resourcen des BufferReaders durch close() befreit (zu dem Zeitpunkt wird readLine() ja nicht ausgeführt!) und die running-Variable auf false gestellt.

Beim nächsten Durchlauf der While-Schleifenbedingung evaluiert running zu false und die Schleife bricht ab. Dadurch verfängt sich nichts mehr in readLine() und die run() Methode erreicht ihr Ende kurz nachdem auf der Konsole die Nachricht ausgegeben wird:

## Closing NonBlockingReader! ##

Somit führen wir den Thread zu einem sauberen Ableben.

Die Nutzung der NonBlockingBufferReader-Klasse hat sich dadurch natürlich auch etwas geändert:

...

public static void main(String[] args){

    // Erzeugen des nichtblockierenden BufferReader Objektes 
    // UND registrieren des Strings, welcher den Thread des Objekts beendet.
    NonBlockingBufferReader readKey = new NonBlockingBufferReader("quit");

    // Starten des Threads
    readKey.start();

    // Auslesen der Eingabe
    String input = readKey.getInput();

    // Ausgabe der Eingabe auf der Konsole
    System.out.println("Input was: " + input);
}

...

Hierbei ändert sich nur der Konstruktoraufruf, indem er um einen Parameter erweitert wird. Dieser Parameter ist die Zeichenkette, welche bei Eingabe auf dem Keyboard zum beenden des Threads führt.


Ich hoffe mein erster Artikel auf meinem Blog hat euch gefallen und vielleicht auch genützt.
Natürlich gibt es unzählige andere Varianten den BufferReader von seinen "Blockaden" zu befreien bzw. ganz andere Klassen in Java mit denen man das bewerkstelligen kann (NIO z.B.).
Ich habe mich aber für den nächsten Artikel dafür entschieden. Ihr werdet merken, dass die Eingabe an sich keine große Rolle spielen wird, denn sie dient nur der Steuerung einiger Programmteile und wird deshalb nicht nochmal behandelt.

Über Kritik und Anregungen, sowie Korrekturen wäre ich sehr erfreut.
Nutzt dazu doch die Kommentarfunktion! ;)
Bei Fragen werde ich versuchen euch mit Rat weiter zu helfen.

Bis zum nächsten Post...