In einem früheren Artikel haben wir bereits FXGL verwendet, um ein JavaFX-Spiel für den Raspberry Pi zu erstellen und es mit einem Joystick zu steuern [1]. Und in einem anderen Artikel [2] haben wir JBang verwendet, um eine Ein-Datei-Java-Anwendung mit Abhängigkeiten zu erstellen, ohne ein vollständiges Maven- oder Gradle-Projekt verwenden zu müssen. Jetzt wollen wir beides kombinieren. Ja, Sie können ein ganzes Spiel mit Java, JavaFX und FXGL in einer einzigen Datei erstellen!
Fangen wir mit einer Zusammenfassung an: Was sind JBang und FXGL? JBang ist ein Werkzeug, das sich vor allem an Studenten, Lehrkräfte und Entwickler richtet, um eigenständige Java-Programme zu erstellen, zu bearbeiten und auszuführen, die nur aus dem Quellcode bestehen. Da Sie die Abhängigkeiten (Java-Bibliotheken) innerhalb der Datei selbst definieren können, benötigen Sie kein Maven- oder Gradle-Projekt und können Ihren gesamten Code in einer einzigen Datei unterbringen. Das macht es zur idealen Spielwiese für kleine Testprojekte oder zur Erstellung eines einfach auszuführenden Beispielprojekts, wie das in diesem Artikel. Wenn Sie die Installationsanweisungen auf der JBang-Website [3] befolgen, wird das Tool installiert und sogar die Java-Laufzeitumgebung, falls das noch nicht geschehen ist.
Bei FXGL [4] handelt es sich um ein Framework, das auf JavaFX aufbaut, um Java-basierte Spiele zu entwickeln. Es wurde von Almas Baimagambetov [5], Senior Lecturer in Game Development an der University of Brighton, entwickelt. Das Projekt ist vollständig quelloffen und hat eine klare Beschreibung, wie Sie dazu beitragen können [6]. Sie fügen zunächst FXGL als Abhängigkeit zu Ihrem Java-Projekt hinzu und brauchen keine zusätzliche Installation oder Einrichtung. Es funktioniert out of the box auf allen Plattformen. Dank des einfachen und sauberen API kann die Erstellung von Spielen mit minimalem Code durchgeführt werden. Das Endergebnis kann als ein einziges ausführbares JAR oder natives Image ausgeliefert werden. Grundlegende Beispiele sind Teil des Hauptprojekts auf GitHub und komplexere Spiele werden in einem separaten Projekt [7] bereitgestellt. Neben 2D-Spielen kann es auch für Geschäftsanwendungen mit komplexen UI-Steuerungen und 3D-Schnittstellen verwendet werden (im Moment noch experimentell).
Das Beispiel in diesem Artikel stammt aus einem Online-Code-Walkthrough, der von Almas und mir während der Weihnachtsferien Ende 2023 aufgezeichnet wurde [8]. Basierend auf einem früher erstellten Spiel mit einem Java Duke, der auf Cloud-Server schießt, sind wir in den Code eingetaucht und haben einige Animationen hinzugefügt (Abb. 1). Das fertige Projekt, eine einzelne Java-Datei mit einigen Bildern, findet ihr auf GitHub [9].
Abb. 1: Das Beispielprojekt
Der vollständige Code passt nicht wirklich in einen Java-Magazin-Artikel, daher sind nur die wichtigsten Elemente in diesem Artikel enthalten und wir laden Sie ein, die vollständige Version im GitHub-Repository in Augenschein zu nehmen. Lassen Sie uns nun in die Schlüsselelemente eintauchen.
Jede JBang-Datei beginnt mit der gleichen Zeile, ///usr/bin/env jbang "$0" "$@" ; exit $?, um JBang mitzuteilen, wie es die Datei behandeln soll. In unserem Fall benötigen wir außerdem zwei zusätzliche Konfigurationszeilen, um die FXGL-Abhängigkeit im Gradle-Format und den Speicherort der Ressourcen zu definieren, in denen die Bilder gespeichert werden. FXGL erwartet standardmäßig, dass sich die Texturen für Game-Sprites in "/resources/assets/textures/" befinden, und wir müssen für JBang den Stammordner "resources/" angeben. Von hier an finden wir normalen Java-Code, beginnend mit den Importen (Listing 1).
Listing 1
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS com.github.almasb:fxgl:17.3
//FILES resources/
import static com.almasb.fxgl.dsl.FXGL.*;
import static com.almasb.fxgl.dsl.FXGLForKtKt.getGameScene;
import com.almasb.fxgl.app.GameApplication;
import com.almasb.fxgl.app.GameSettings;
...
Die vollständige Klasse besteht aus mehreren Elementen:
Die Hauptklasse, die GameApplication erweitert:
Die Hauptmethode, die die Anwendung startet
Alle Überschreibungen, die von GameApplication zum Initialisieren, Konfigurieren und Starten des Spiels bereitgestellt werden
Eine innere Klasse GameFactory, die EntityFactory implementiert:
Sie definiert alle Elemente (BACKGROUND, CENTER, DUKE, CLOUD, BULLET), die im Spiel erzeugt werden können
Mehrere innere Klassen, die Component erweitern:
Diese werden in der GameFactory in einigen Elementen während deren Erstellung verwendet
PlayerComponent definiert alles für die Duke-Player-Entität
CloudComponent definiert alles für ...