quixotic project blog

Archive for the ‘Java’ tag

Adding Javadoc Links in IntelliJ Idea with Live Templates

without comments

In Eclipse there is this wonderful little helper for adding Javadoc links while you’re typing a class name. It looks like this:

auto completion for Javadoc links in Eclipse

It suggests not just to put the classes name there but also use a @link tag so one can navigate the Javadoc sources later on. The finished comment:

auto completion for Javadoc links in Eclipse

Unfortunately this functionality is not available in JetBrains’ IntelliJ Idea. There is (of course) auto completion for classnames in Idea but it simply doesn’t put them in a @link tag. A simple trick saves the day: simply create a live template with context ‘Java comment’ like here:

creating a live template for the javadoc link

EDIT: The screenshot is missing the word ‘link’. The complete template should be: ‘{@link $LINK$} ‘.

Don’t forget to click on ‘Edit variables’ and fill in ‘complete()’ as Expression. This activates the auto completion for classnames.

Now everytime a @link in the Javadocs is needed we invoke the Live Templates with Alt + J and enter a classname. The @link tag will be build around that name. It’s not as simple as with Eclipse, but works pretty well.

live template for the javadoc @link

live template for the javadoc @link tag

Written by michi

January 26th, 2010 at 11:55 pm

Trouble with Vertex Buffer Objects solved

without comments

It has been a while since I last used Vertex Buffer Objects (VBO) with LWJGL. It seemed as if they had changed some of the method signatures since I used them last time. I couldn’t even get the simplest example running. After experimenting for a while I finally figured it out. Have a look at the signature of the VertexPointer method:

static void glVertexPointer(int size, int type,
  int stride, long pointer_buffer_offset);

With the last offset one can specify where the vertex information starts in the buffer given to the VBO management. Well, I could/should have guessed that this offset has to be in bytes since I am dealing with a buffer here but instead I used the number of floats.. So next time I see an operation dealing with buffers that takes a long argument I’ll try the byte-count from the beginning..

Written by michi

October 25th, 2009 at 7:29 pm

GLSL Shader in Java mit LWJGL

without comments

Shaderprogrammierung in GLSL, der Shadersprache unter OpenGL, war bisher ein Buch mit sieben Siegeln für mich. Aber da man ja alles lernen kann habe ich mich auf die Suche nach Tutorials gemacht und auch einige sehr gute entdeckt. Die Einführung von Lighthouse3d ist zum Beispiel sehr zu empfehlen. Hier wird wirklich mit den Grundlagen angefangen und erstmal eine Beschreibung geliefert wie die Pipeline der Grafikkarten aufgebaut sind und wo genau die verschiedenen Shader zum Einsatz kommen.

Natürlich muss man die geschriebenen (oder abgetippten) Shader auch irgendwie ausprobieren. Hier fand ich das Programm ShaderDesigner von Typhoon Labs ganz brauchbar. Leider scheint es die Firma nicht mehr zu geben, aber sowohl ShaderDesigner als auch ein ebenfalls super geschriebenes Tutorial für Shader lassen sich nach wie vor von der Seite runterladen.

Schließlich habe ich mich daran gemacht, die Shader auch in einem wirklichen Programm einzusetzen. Hierfür verwende ich die “Light Weight Java Games Library” (LWJGL), meinem Lieblingsbinding von OpenGL an Java. Es stellte sich heraus, dass wenn man mal einen funktionierenden Shader hat, diesen wirklich einfach in ein Programm einbinden kann. Wirklich geholfen hat mir der entsprechende Wikieintrag im LWJGL Wiki. Am besten speichert man Vertex- und Fragmentshader in einer Textdatei und legt sie irgendwo im Projektverzeichnis ab. Im Programm werden die Dateien dann mit ganz gewöhnlichen Hausmitteln erstmal geöffnet und in einem Bytearray gespeichert. Dies muss natürlich sowohl für Vertex- als auch für Fragmentshader passieren:

1
2
3
4
5
6
7
8
9
10
11
ClassLoader loader = ShaderTest.class.getClassLoader();
InputStream is = loader.getResourceAsStream(shadername);
byte[] shadercode = null;
try {
    DataInputStream dis = new DataInputStream(is);
    dis.readFully(shadercode = new byte[is.available()]);
    dis.close();
    is.close();
} catch (IOException e) {
    System.out.println(e.getMessage());
}

Anschließend werden die Bytearrays in einen ByteBuffer kopiert, den LWJGL lieber mag:

1
2
3
ByteBuffer shader = BufferUtils.createByteBuffer(shadercode.length);
shader.put(shadercode);
shader.flip();

Nicht vergessen die Buffer zu flippen!
Anschließend teilen wir OpenGL mit, dass wir zwei neue Shaderobjekte brauchen. Dies funktioniert genau wie wenn man eine Textur anlegt: Man teilt OpenGL mit, was man haben will und bekommt ein int zurück, mit dem man das neue Objekt referenzieren kann:

1
2
3
4
int vertexShaderID = ARBShaderObjects.glCreateShaderObjectARB(
ARBVertexShader.GL_VERTEX_SHADER_ARB);
int pixelShaderID = ARBShaderObjects.glCreateShaderObjectARB(
ARBFragmentShader.GL_FRAGMENT_SHADER_ARB);

Nachdem die entsprechenden Objekte nun OpenGL bekannt gemacht wurden müssen wir OpenGL nun mitteilen was die Shader genau machen sollen, sprich deren Quellcode übergeben. Danach werden die Shader kompiliert:

1
2
3
4
5
ARBShaderObjects.glShaderSourceARB(vertexShaderID, vertexShader);
ARBShaderObjects.glCompileShaderARB(vertexShaderID);
 
ARBShaderObjects.glShaderSourceARB(pixelShaderID, pixelShader);
ARBShaderObjects.glCompileShaderARB(pixelShaderID);

vertexShader und pixelShader sind die Variablen, die auf die ByteBuffer zeigen und den eingelesenen Quelltext enthalten.
Die beiden Shader werden nun zu einem Programm zusammengebunden. Ein Programm wird dabei ebenso wie ein Shaderobjekt erstellt: bei einem Methodenaufruf erhalten wir ein int mit dem wir das Programm in Zukunft referenzieren. Hat man nur einen Vertex- oder nur einen Fragmentshader zur Hand wird der jeweils andere Teil von OpenGL durch eine Standartimplementierung ersetzt. Zum Schluß werden die Teile ähnlich einem C Programm zusammengebunden.

1
2
3
4
int shaderProgramID = ARBShaderObjects.glCreateProgramObjectARB();
ARBShaderObjects.glAttachObjectARB(shaderProgramID, vertexShaderID);
ARBShaderObjects.glAttachObjectARB(shaderProgramID, pixelShaderID);
ARBShaderObjects.glLinkProgramARB(shaderProgramID);

Jetzt sind wir fertig und können den Shader beim Rendern benutzen. Hierzu ruft man im Renderloop bevor das Objekt das den Shader erhalten soll gezeichnet wird die folgende Methode auf

1
ARBShaderObjects.glUseProgramObjectARB(shaderProgramID);

Wird anstatt einem Shaderprogramm “0″ übergeben benutzt OpenGL die Standarteinstellungen (fixed Pipeline) zum Rendern.

Ein kleiner Test mit einem Toon-Shader aus dem Lighthouse Tutorial sieht dann zum Beispiel so aus:

Die Veränderung der Farbe des 3d Modells hängt nicht mit dem Licht zusammen sondern wird im Fragmentshader verursacht. Hierzu wird eine Variable vom Javaprogramm aus an den Shader übergeben, die die Zeit seit dem Beginn der Anwendung übergibt. Im Fragmentshader ist die Variable so definiert:

1
uniform float TIME_SINCE_INIT;

Bei jedem Durchlauf des Renderloops wird diese Variable vom Javaprogramm neu geschrieben. Um den Schreibvorgang durchzuführen wird vorher die Location der Variable bestimmt. Dazu wird OpenGL der mit 0 terminierte Name der Variablen übergeben. Existiert diese, dann liefert OpenGL eine Location in Form eines Integers zurück und man kann mit einem glUniform1fARB-Aufruf den Wert übergeben.

1
2
3
4
5
6
7
8
ByteBuffer buff = BufferUtils.createByteBuffer(
    "TIME_SINCE_INIT".length()+1);
buff.put( "TIME_SINCE_INIT".getBytes() );
buff.put((byte)0);
buff.flip();
int location = ARBShaderObjects.glGetUniformLocationARB(
    shaderProgramID, buff);
ARBShaderObjects.glUniform1fARB(location, gameLogicTimer.getTime());

Written by michi

December 29th, 2008 at 4:46 pm

Posted in Development, Java

Tagged with , , , , ,

Playing MootoX

with 2 comments

Kevin Glass neuestes Projekt MootoX nimmt langsam Formen an! Es handelt sich um ein 2D Racing Spiel bei dem man ein Fahrzeug, dass man von der Seite sieht durch ein Level steuern muss. Im Moment geht es nur darum alle Sterne einzusammeln bevor man ins Ziel kommt und dabei schneller zu sein als der Gegner, aber geplant sind wohl noch mehr Aufgaben.
Die Featureliste umfasst unter anderem eine eingebaute Physik, die das Spiel erst so richtig zur Herausforderung macht und den Wiederspielwert unglaublich erhöht. Ganz neu hinzugekommen ist jetzt die best-times Liste auf der ich im Moment auch verewigt bin, und zwar beim Level Underground. Dies liegt hauptsächlich daran, dass ich den Level selbst erstellt habe, denn die Konkurrenz ist extrem gut und scheint den ganzen Tag nichts anderes zu spielen ;)
Das Levelerstellen ist meiner Meinung nach fast das beste Feature am ganzen Spiel: Auf der Website ist es ganz genau beschrieben, deswegen hier nur in Kürze: Mit einem beliebigen SVG Tool zeichnet man einfach ein paar Polygone und hängt im Objektbezeichner ein Schlüsselwort dran und die Spielengine interpretiert die Zeichnung dann als Level. Das bedeutet, dass man die Levels fast im wörtlichen Sinne einfach nur hinmalen muss und schon kann man sie spielen.
Hier kann man das Spiel mit Java Webstart spielen.

mootox01.png
Screenshot aus einem Multiplayerspiel

Written by michi

February 28th, 2008 at 2:48 pm

Posted in Games, Java

Tagged with , , , , ,

NetBeans 6 endlich da

without comments

Endlich ist es soweit, NetBeans 6 ist fertig. Seit einigen wenigen Tagen steht nun die fertige Version zum Download bereit. Eines der neuen Features das mir besonders gefällt, ist dass man mit Alt-Insert ein kleines Fenster anzeigen kann in dem man mit nur ein paar Tastendrücken getter-/setter-Methoden oder auch Konstruktoren erzeugen kann ohne die Hände von der Tastatur nehmen zu müssen.
NetBeans 6.0 Feature 01
Ein zweites tolles Feature gibt es schon seit einigen Meilensteinen, aber es scheint noch nicht so ganz ausgereift zu sein: Unter den Projekteinstellungen findet man jetzt ein Feld für WebStart. In einer GUI kann man einige WebStart Parameter bequem festlegen und beim nächsten Build wird ein jnlp-Descriptor erzeugt und alles in ein jar-File verpackt. Leider scheint es noch nicht automatisch zu gehen, dass zum Beispiel native Dateien anderer Betriebssysteme mit im Descriptor angegeben werden können. Aber das ist ja eigentlich nur eine Kleinigkeit die sich schnell ändern lässt.
NetBeans 6.0 Feature 02

Written by michi

December 7th, 2007 at 10:04 am

Posted in Development, Java

Tagged with , ,

Roguelike Programmierung

with one comment

Seit einiger Zeit nun versuche ich mich selbst daran ein kleines roguelike zu schreiben. Noch gibt es nicht viel zu sehen, deswegen keine Screenshots. Nebenbei lese ich auch die entsprechende Newsgroup rec.games.roguelike.development um einen Überblick zu erhalten und Links zu Tutorials und so weiter zu finden. Eine Seite fand ich dabei besonders gut: Ascii Dreams. Der Autor entwickelt, soweit ich das richtig mitbekommen habe, ein altes Roguelike (Angband) weiter und dokumentiert dabei die wichtigsten Schritte und was ihm wichtig ist. Erst kürzlich hat er eine Reihe von Artikeln über die Levelgenerierung veröffentlicht, die sehr interessant waren.

Ich habe den ersten Schritt hinter mir und mich für eine Darstellung entschieden. Klassischerweise würde man wohl farbige Konsolenausgabe für die Grafik wählen, doch da ich mich für Java als Programmiersprache entschlossen habe fällt das flach. Java kennt keine Farbe in der Konsole und dies durch Tricks zu umgehen war mir zu aufwendig. Die zweite Möglichkeit ist eine der vielen Curses Bibliotheken zu benutzen die es so gibt. Da die meisten aber für C++ sind und ich nur eine für Java gefunden habe (JCurses) und mit dieser auch nicht besonders gut zurechtgekommen bin habe ich auch dies wieder verworfen. Entschieden habe ich mich dann für Alternative drei: Mit Hilfe von OpenGL zeichne ich einfach Quads auf den Bildschirm die die Ascii-Zeichen als Textur haben und habe somit auch gleich die volle Kontrolle über die Auflösung, verschiedene Zeichensätze usw.
Zeichnen lasse ich dann alles über VertexArrays, wobei sich nur die Arrays für die Farbe und die Textur ändern, die Geometrie ist statisch. Gerendert wird in zwei Schritten: Zuerst wird der Hintergrund ohne Textur mit Hintergrundfarbe gerendert und danach kommt nochmal ein Durchgang mit angeschalteten Texturen. In Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//render background
//fill color buffer
colorBuffer.position(0);
colorBuffer.put(colorArrayBackground);
colorBuffer.flip();
 
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
GL11.glVertexPointer(3, 0, vertexBuffer);
GL11.glColorPointer(3, 0, colorBuffer);
 
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, resX * resY * 6);
 
//render foreground
//fill colorbuffer
colorBuffer.position(0);
colorBuffer.put(colorArrayForeground);
colorBuffer.flip();
 
texCoordBuffer.position(0);
texCoordBuffer.put(texCoordArray);
texCoordBuffer.flip();
 
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
 
GL11.glTexCoordPointer(2, 0, texCoordBuffer);
 
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, resX * resY * 6);
 
GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);

Die Klasse die für das Rendern zuständig ist merkt sich die Farben und Texturen der einzelnen Tiles (also die Positionen an denen ein Buchstabe oder Zeichen stehen soll), sodass nicht in jedem Durchlauf alles erneut ausgelesen werden muss.

Sobald man mal mehr als nur ein paar Debugausgaben sehen kann werde ich auch einen Screenshot posten.

Written by michi

December 4th, 2007 at 10:30 pm

Posted in Development, Games, Java

Tagged with , , ,

Design Patterns in Spielen: State Pattern

with one comment

Beim Stöbern durch die Bibliotheken von ACM bin ich auf folgenden Artikel gestoßen: Computer games as motivation for design patterns. Paul V. Gestwicki beschreibt darin wie er mit Hilfe eines Computerspiels seine Studenten motiviert sich mit Design Patterns zu beschäftigen. Obwohl man ja gerade bei Spielen oft darauf aus ist noch die letzten FPS aus dem Code herauszuquetschen lohnt es sich doch nicht allen Code auf Performance auszulegen, sondern einen strukturierten Ansatz zu verfolgen. Die Vorteile liegen auf der Hand: Der Code wird lesbarer, leichter wartbar und besser erweiterbar.

Das erste Design Pattern in seinem Paper ist das State Pattern. Anhand einer Sprite Klasse, die zuständig für das Aussehen, die Größe und Position des Spielers ist, erläutert er das Pattern. Der Spieler kann sich in mehreren Zuständen(=States) befinden und das Verhalten der Sprite Klasse ändert sich mit jedem Zustand. Eine naive Implementation würde jedem Zustand einen int-Wert geben und dann in einer update() Methode später einen großen switch-Block durchlaufen in dem jedes Verhalten in jedem Zustand beschrieben ist.

Im Buch Design Patterns von Gamma et. al. wird jedoch genau dies als Grundlage der Anwendbarkeit des State Pattern angegeben:

  • An object’s behavior depends on its state, and it must change its behavior at run-time depending on that state
  • Operations hve large, multipart conditional statements that depend on the object’s state. This state is usually represented by one or more enumerated constants.

Wie sieht nun so ein State Pattern aus? Zu allererst brauchen wir ein Interface, dass einen Zustand beschreibt:

1
2
3
4
5
6
public interface State {
public void install();
public void uninstall();
public void draw();
public void update();
}

Die Spieler Klasse muss nun eine Variable vom Typ State besitzen mit der angegeben wird in welchem Zustand der Spieler sich gerade befindet. Außerdem müssen alle Aufrufe die den Zustand des Spielers betreffen an die State-Implementation deligiert werden. Skizzenhaft sieht der Spieler dann so aus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Spieler{
State aktuellerZustand;
 
...
 
public void update(){
aktuellerZustand.update();
}
 
public void draw(){
aktuellerZustand.draw();
}
 
...
}

Was nun noch fehlt sind tatsächliche Implementationen des State-Interfaces. Hier hat man mehrere Möglichkeiten. Zum einen kann man innere anonyme Klassen verwenden:

1
2
3
4
5
6
7
8
//Konstruktor
public Spieler(){
aktuellerZustand = new State(){
public void install(){...};
public void uninstall(){...};
public void update(){...};
public void draw(){...};
}

oder man verwendet einfache innere Klassen, d.h. in der Spieler Klasse werden weitere Klassen definiert die jeweils das State Interface implementieren. Beides hat den Vorteil, dass man die Logik und das Verhalten des Spielers sehr nahe am Spieler selbst hat. Die inneren Klassen können auf Variablen der äußeren Zugreifen und so mit dem Spieler interagieren. Weiterhin verbirgt man die konkreten Zustände vor der Außenwelt.

Das Spieler Objekt könnte nun selbst entscheiden wann es welchen Zustand braucht, einfacher und manchmal auch schöner ist es jedoch die Zustände selbst entscheiden zu lassen. Hierfür gibt es die Methoden install() und uninstall(), die einen Übergang von einem zum anderen Zustand erlauben indem sie einfach die State Variable des Spielers neu setzen. Denkbar ist natürlich auch, dass in diesen Methoden spezielle Animationen für die Übergänge ausgelöst werden usw.

Written by michi

October 31st, 2007 at 11:27 am