Archive for category Java

MMO mit Java – Charakter Auswahl

Nachdem die Schwierigkeiten mit FengGui ausgestanden sind, lief die Erstellung des Charakter Auswahlbildschirms deutlich schneller. Einzig die Liste zur Auswahl der einzelnen Charaktere verursachte zunächst einige Schwierigkeiten. Wird bei FengGui nicht explizit ein Theme ausgewählt, so bleiben Schriftarten und Hintergründe schwarz.

Das Setzen der Farbe und Hover-Farbe erfolgt folgendermaßen:


DecoratorLayer underlay = new DecoratorLayer();
PlainBackground plainBackground = new PlainBackground(new Color(0.97f, 0.89f, 0.52f, 0.5f));
RoundedBorder roundedBorder = new RoundedBorder(new Color(0.97f, 0.89f, 0.52f, 0.5f), 3, 3);
underlay.add(plainBackground, roundedBorder);
list.getAppearance().setHoverUnderlay(underlay);
list.getAppearance().setSelectionUnderlay(underlay);

Die erste Version des Auswahlbildschirms verfügt nur über ein statisches Hintergrundbild. Professionelle MMO’s verwenden hier entweder eine reine 3D Landschaft, eine 3D Landschaft kombiniert mit einer Skybox (z.B. GuildWars) oder ein Hintergrundbild, dessen Himmel animiert ist. Die einzelnen Gui’s sind mittels GameStates separiert, wichtig ist, dass aus den States sämtliche Widgets entfernt werden, damit diese nicht die nächste Maske beeinflussen. Hier nun das Ergebnis:

Charakter-Auswahlbildschirm

Eine erfreuliche Erkenntnis ergab sich noch: Der Text der GameButtons kann programmatisch eingefügt werden, damit erübrigen sich spezifische Bilder für jeden einzelnen Buttons und reduzieren die Malarbeit.

No Comments

MMO mit Java – Login Client mit FengGui

Nach dem ich jede Menge Inkompatibilitäten zwischen der JMonkeyEngine und FengGui beseitigt hatte und ich zweitweise dachte es funktioniert doch nicht ist die erste Version des Login Clients jetzt fertig. Schlussendlich ist es aber doch geschafft und alle Bibliotheken sind kompatibel im Maven Repository verstaut.

Nach einem Login mit den richtigen Daten werden die Account Informationen vom Server abgeholt. Fehlt also noch die Oberfläche zur Auswahl und Erstellung der Charaktere.

No Comments

MMO mit Java – JMonkeyEngine Client

Nachdem die Performance mit Java2D auf hohen Auflösungen zu wünschen übrig lies, ging ich über, den Client mit Java3D neu zu erstellen. Die Bücher Killer Game Programming in Java und Pro Java 6 3D Game Development sehr hilfreich.
Da Java3D aber nicht mehr weiterentwickelt wird, bzw. nur mehr im Rahmen für JavaFX war es sinnvoller auf eine für Spieleentwicklung spezialisierte Szene Graph API einzusetzen. Hier bot sich die JME – JmonkeyEngine 2 an. Die Ergebnisse können sich sehen lassen und die Einarbeitung fällt dank des umfangreichen Tutorials und der regen Forumaktivität – ganz im Gegensatz zu Java3D – ziemlich einfach aus.

Hier der erste Prototyp des Clients, der Avatar ist übrigens aus Neverwinter Nights, das Modell mit Hilfe eines eigenen Parsers,erzeugt mit antlr, eingelesen.

Impressionen einer virtuellen Welt

Hier ein weiteres Bild:

Impressionen einer virtuellen Welt

Auch wenn optisch schon ein ansprechendes Ergebnis da ist, so ist noch einiges zu tun, gerade hinsichtlich der Animationen, animiert Laufen kann der Avatar, aber es gibt noch einige Schwierigkeiten bei Sitzen und Aufstehen. Derzeit ist aber die Anbindung an den Application Server mit JMS interessanter.

No Comments

MMO mit Java/J2EE? (Teil 3) – Action Kommunikation

Nachdem es notwendig war, die gesamte Clientdarstellung zu überarbeiten, um auf veschiedenen Rechnertypen akzeptable und gleichmäßig performante Darstellung zu erreichen bin ich nun endlich dazu gekommen, mir Gedanken über die Action-Kommunikation zu machen. Doch zunächst zur Begriffserklärung. In einem MMO Game wie es hier entwickelt wird folgendes unter Aktionen verstanden:

  • Flüchtige Aktionen: Sind Aktionen die eine Übertragung von sich schnell ändernden Statusinformationen zwischen Client und Server auslösen und keine oder nur eine periodische Persistierung benötigen. Zu derartigen Aktionen gehören z.B. die Bewegungen von Spielfiguren, die schnell und kontinuierlich zwischen Clients im Anzeige, bzw. Aktionsradius synchronisiert werden müssen. Der Verlust eines gewissen Prozentsatzes der Informationen kann bei dieser Informationsübertragung in Kauf genommen werden.
  • Transaktionsichere Aktionen: Sind Aktionen, die eine Übertragung von Statusinformationen zwischen Client und Server auslösen und dabei eine sichere Persistierung verlangen. Zu solchen Aktionen gehören z.B. Handelssitzungen zwischen Spielfiguren oder das Aufnehmen von Gegenständen in das Inventar der Spielfigur.
  • Action Kommunikation

    Action Kommunikation

    Der erste Ansatz einer solchen Informationsübertragung wird mit einem QueueRequestor durchgeführt, welcher einen request/reply Mechanismus via JMS zur Verfügung stellt. Das Senden einer Message erfolgt dabei über eine definierte Queue, während die Rückantwort über eine temporäre Queue verschickt wird. Ob sich dieser Ansatz als praktikabel und performant erweist, muss noch erprobt werden. Um die Datenbank nicht mit flüchtigen Statusinformationen zuzumüllen werden diese zunächst in einen Informationscache gespeichert und so für einen schnellen Zugriff vorgehalten. Die Überführung der Informationen in einen persistenten Zustand kann dann periodisch oder anhand einer geeigneten Eviction Policy erfolgen.

    No Comments

    MMO mit Java/J2EE? (Teil 2)

    Aktives Rendern zur Darstellung von Animationen

    Zur Darstellung der Clientgrafiken und Animationen für den MMO Prototyp verwende ich ein eigenes Canvas, welches mit einem Thread die Grafiken in kurzen Zeitabständen zyklisch neuzeichnet, dadurch lassen sich durch den Austausch der Grafiken animationen erzielen. Der Austausch kann an die Eingabe des Clients, oder an die Aktualisierung der Spieldaten des Servers für NSP’s (Nicht-Spieler Charaktere) gekoppelt sein.

    Exemplarische (nicht vollständige) Animationssequenz

    Exemplarische (nicht vollständige) Animationssequenz

    Mein bisheriges Canvas rief in run()-Methode des Threads periodisch repaint() auf. Da repaint() aber keinesfalls garantiert von der JVM aufgerufen wird, sondern in eine Queue eingestellt wird, ist eine reibungslose Animationsdarstellung nicht gewährleistet. Hier ergibt sich eine Verbesserung durch den Einsatz des sog. Active Rendering, die (vereinfachte) Implementierung dazu sieht folgendermaßen aus:


    1 private void activeRendering() {
    2   Graphics g = this.getGraphics();
    3   if (g != null) {
    4     g.drawImage(offscreenImage, 00null);
    5     Toolkit.getDefaultToolkit().sync();
    6     g.dispose();
    7   }
    8 }

    Toolkit.getDefaultToolkit().sync(); Stellt die Aktualisierung des Displays unter Linux sicher. (Quelle: Killer Game Programming, Andrew Davidson)

    No Comments

    MMO mit Java/J2EE? (Teil 1)

    MMO, oder Massively Multiplayer Online Games auf Basis von Java und J2EE? Die Antwort auf diese Frage werde ich in einer Reihe von Artikeln versuchen zu beantworten. Ziel ist eine Machbarkeitsstudie auf Basis eines Prototypen zu entwickeln.

    1.1 Einführung

    Ein Massively Multiplayer Online Game ist ein Computerspiel, welches ausschließlich über das Internet gespielt werden kann und bei dem gleichzeitig mehrere hundert oder tausend Spieler sich in einer persistenten Spielumgebung treffen und interagieren können. Vertreter bekannter Spiele sind z.B. World of Warcraft, Guildwars oder Warhammer Online.

    1.2. Architektur, Komponenten

    Ein MMO Game besteht grob aus den Schichten Präsentation (Client), Geschäftslogik (Server) und Datenhaltung (Server), also der klassischen Architektur die mit J2EE realisierbar ist. Folgende Grafik beschreibt die Architektur eines MMO Games:

    MMO Architektur

    MMO Architektur

    Clientseite
    Die Präsentationsschicht wird durch den Gameclient repräsentiert. Der Gameclient beinhaltet grob folgende Funktionen:

    • Login Funktionalität, zum Einloggen in die Spielwelt
    • Patch Funktionalität, zum automatischen Bezug und Installation von Softwareupdates
    • Darstellung der Spielwelt und der Interaktionen

    Serverseite
    Die Serverseite umfasst eine Reihe von Servern mit unterschiedlichen Aufgaben. Die folgende Trennung ist aufgrund der Lastverteilung üblich und wird bei den bekannten MMO’s so praktiziert:

    • Accountserver: Üblicherweise mit Web-basierter Oberfläche zur Verwaltung der Accountdaten, abgelegt in der Accountdatenbank
    • Loginserver: Server zum Überprüfen der Accountdaten und des Patchstandes
    • Sessionserver: Server zum Überprüfen der Gültigkeit der aktiven Session und zur Weiterleitung der Anfragen an den Patch- und Gameserver
    • Patchserver: Server zur Verteilung von Softwareupdates, hier sind mehrere Möglichkeiten denkbar, der Download von Patches über http oder ftp. Auch verteilte Ansätze sind denkbar, so benutzt World of Warcraft Bittorrent als Verteilungssystem.
    • Gameserver: Der eigentliche Spielserver, der die Spielewelt hostet und die Interaktionen der Spieler verwaltet und die Spielzustände in der Game-DB festhält.

    1.3. Ausblick

    Vorweg würde ich behaupten, dass sich J2EE für die Umsetzung eines MMO’s prinzipiell eignet, die entscheidende Frage stellt sich meines Erachtens, ob eine akzeptable Performance des Gameservers erreicht werden kann oder nicht. Von dieser Fragestellung ist die Anzahl der gleichzeitig bedienbaren Clients pro Server abhängig und damit beantwortet sich die Frage, ob ein MMO realisiert werden kann.

    No Comments

    jClaim – ICQ mit Java

    Freie ICQ Implementierungen gibt es mittlerweile einige, jedoch kaum welche in Java. Ein Vertreter ist jClaim, neben einer Bibliothek zum Erstellen einer eigenen Anwendung bietet jClaim auch einen fertigen Client, der direkt über Webstart gestartet werden kann. Ein simpler Client ist schnell realisiert:


    01 package messaging;
    02 
    03 import com.itbs.aimcer.commune.joscar.ICQConnection;
    04 import com.itbs.util.GeneralUtils;
    05 import controller.MessengerGroupFactory;
    06 import controller.MessengerContactFactory;
    07 import controller.LogEventHandler;
    08 
    09 public class JavaICQ {
    10 
    11   public static void main(String[] argsthrows Exception {
    12     try {
    13       ICQConnection conn = new ICQConnection();
    14       conn.assignGroupFactory(new MessengerGroupFactory());
    15       conn.assignContactFactory(new MessengerContactFactory());
    16       conn.setUserName("icqnumber");
    17       conn.setPassword("icqpass");
    18       conn.addEventListener(new LogEventHandler());
    19       conn.connect();
    20       while (true) {
    21         GeneralUtils.sleep(60 60 1000);
    22       }
    23     catch (Exception e) {
    24       throw new RuntimeException(e);
    25     }
    26   }
    27 
    28 }

    Statt des LogEventHandlers kann auch der BotEventHandler, der standardmäßig in der Bilbliothek enthalten ist, verwendet werden.
    Bei der Einfachheit dieser Implementierung bleibt es aber auch, so ist es z.B. mit der Bibliothek derzeit nur möglich vom Online Status auf den Away Status zu schalten. Die umfangreichen Funktionen, die der offizielle ICQ Client bietet, sind mit jClaim leider nicht zugänglich.

    No Comments

    Levenshtein Distanz mit linearem Speicherverbrauch

    Folgendes Groovy Skript berechnet die Levenshtein Distanz zweier Zeichenketten. Die Levenshtein Distanz ist ein Maß bezüglich der Operationen Ersetzen, Einfügen und Löschen, um die Gleichheit beider Zeichenketten zu erreichen. In anderen Worten, die Levenshtein Distanz ist ein Maß für die Ähnlichkeit zweier Zeichenketten. Der Algorithmus benötigt im Gegensatz zur normalen Implementierung nur linearen Speicherplatz.


    01 /**
    02  * Berechnet die Levensthein Distanz der beiden Strings x und y.
    03  
    04  @param x String x des Vergleichs, nicht null.
    05  @param y String y des Vergleichs, nicht null.
    06  @return die Levensthein Distanz der beiden Strings x und y
    07  */
    08 int linearLD(String x, String y) {
    09   int n = y.length();
    10   int m = x.length();
    11  
    12   if (n == 0return m;
    13   if (m == 0return n;
    14  
    15   def T = [];
    16   T[00;
    17   for (j in 1..n) {
    18     T[j= T[j-11;
    19   }
    20   for (i in 1..m) {
    21     def s = T[0];
    22     T[0= T[01;
    23     def c = T[0];
    24     for (j in 1..n) {
    25       def sub = s + (x.charAt(i-1== y.charAt(j-11);
    26       def del = T[j1;
    27       def ins = c + 1;
    28       c = Math.min(Math.min(sub, del), ins);
    29       s = T[j];
    30       T[j= c;
    31     }
    32   }
    33   return T[n];
    34 }
    35 
    36 println linearLD("Lin""Lang");

    Das Ergebnis des Aufrufs lautet 2, da zwei Operationen zum Angleichen der Zeichenketten notwendig wären.

    Hier der Algorithmus nochmal in Java:


    01 public class LinearLD {
    02 
    03   /**
    04    * Berechnet die Levensthein Distanz der beiden Strings x und y.
    05    
    06    @param x String x des Vergleichs, nicht null.
    07    @param y String y des Vergleichs, nicht null.
    08    @return die Levensthein Distanz der beiden Strings x und y
    09    */
    10   public static int linearLD(String x, String y) {
    11     int n = y.length();
    12     int m = x.length();
    13    
    14     if (n == 0return m;
    15     if (m == 0return n;
    16    
    17     int[] T = new int[n+1];
    18     T[00;
    19     for (int j=1; j <= n; j++) {
    20       T[j= T[j-11;
    21     }
    22     for (int i=1; i<=m; i++) {
    23       int s = T[0];
    24       T[0= T[01;
    25       int c = T[0];
    26       for (int j=1; j<=n; j++) {
    27         int sub = s + (x.charAt(i-1== y.charAt(j-11);
    28         int del = T[j1;
    29         int ins = c + 1;
    30         c = Math.min(Math.min(sub, del), ins);
    31         s = T[j];
    32         T[j= c;
    33       }
    34     }
    35     return T[n];
    36   }
    37   
    38   public static void main(String[] args) {
    39     System.out.println(LinearLD.linearLD("""Tier"));
    40   }
    41 }

    Ein praktischer Anwendungsfall für die Berechnung der Levenshtein Distanz ist z.B. im Falle der automatisierten Zusammenführung von unterschiedlichen Stammdatenbeständen gegeben, in denen etwa Vergleiche auf Personen- oder Ortsnamen durchgeführt werden müssen, und in denen Umlaute unterschiedliche dargestellt (z.B. ü und ue) werden.

    6 Comments

    Java3D auf Vista 64

    Nachdem meine Versuche die JMonkeEngine auf Grund der darunterliegenden Bibliothek lwjgl mit Vista 64 zu laufen zu bringen gescheitert sind, bin ich für meine Versuche wieder auf Java 3D ausgewichen. Java 3D läuft sowohl mit der 32bit Variante des JDK’s als auch mit der 64bit Variante problemlos auf Vista 64. Wie früher auch ziehen die Beispiele einiges an Prozessorleistung.

    Tags:

    No Comments

    3D Java: JMonkeyEngine

    Was die JMonkeyEngine angeht, so scheint diese auf den ersten Blick ziemlich professionelle Anwendungen, zumindest Demos, hervorzubringen. Diverse Screenshots und Videos auf youtube führen zunächst zu ungläubigen Staunen, was mittlerweile mit Java alles möglich ist. Klar, die Grafik kann sich nicht mit der gängiger Spieletitel messen, aber mit der Optik populärer MMO’s wie World of Warcraft kann Java mittlerweile mithalten.

    Die JMonkeyEngine in eigenen Projekten zu verwenden gestaltet sich jedoch schwieriger als zunächst erwartet. Für Version 1 gibt es die Libraries zum Download, jedoch lässt die Dokumentation zu wünschen übrig. Die Wiki Anleitung empfiehlt das Open Source Projekt bei java.net mittels cvs auszuchecken. Dies läuft relativ problemlos, doch scheiterte ich am compillieren der Sourcen. Es schien, als wäre gerade jemand dabei gewesen, Code einzuchecken, hatte aber dabei einige Dateien vergessen, was mich in eine Sackgasse führte. Also Versuch 2 mit Version 2 des Projekts, diesmal aber als svn Projekt. Auschecken wieder kein Problem, jedoch streikte diesesmal der Compiler mit einem OutOfMemory, was aber an meinem Vista 64 System liegen kann. Diverse Kommentare im svn log führten mich auf die richtige Fährte, das Problem behob sich mittels höherer Memory Einstellungen im ant Buildfile. Der Test führte mich dann dennoch in eine Sackgasse, denn die benötigten lwjgl Bibliotheken, auf die JMonkeyEngine aufbaut bringt eigene .dll Bibliotheken für den Zugriff auf opengl mit, die jedoch nur für die 32bit Version von Windows zur Verfügung stehen.

    Fazit: Die Probleme mit 64bit Systemen und die mangelhafte Dokumentation lassen mich derzeit vor dem Einsatz der JMonkeyEngine abraten, ich rate hier doch zu dem bewährten Java3d, welches sowohl unter 32bit als auch 64bit Systemen einwandfrei arbeitet.

    Tags: ,

    No Comments