FXGL Tutorial: Bilder und Soundeffekte in ein JavaFX-Spiel einfügen

© Shutterstock / Patinya_P_ang/
Im zweiten Teil unseres FXGL-11-Tutorials werden wir auf Basis unseres einfachen Spiels weiterarbeiten. Hier können Sie den ersten Teil des Tutorials nachholen, falls Sie es noch nicht erledigt haben. Es ist zu beachten, dass dieses Tutorial für FXGL 11.0+ und Java 11+ gedacht ist.
Wie im vorhergehenden Teil des Tutorials, gibt es ein paar zu definierende Eckpunkte. Wir werden uns den folgenden drei Aufgaben widmen:
- Die Spielfigur soll durch ein Bild dargestellt werden.
- Dem UI des Spiels soll ein Bild hinzugefügt werden.
- Ein Sound soll abgespielt werden, wenn die Zahl der bewegten Pixel durch 100 teilbar ist.
Zum Schluss des Tutorials sollte der folgende Zustand erreicht werden:

Quelle: GitHub
Vorbereitung
Bevor wir durchstarten können, erstellen wir mithilfe des Projekts aus dem vorherigen Teil das Verzeichnis für die assets
in:
src/main/resources/
, wenn wir Maven oder Gradle verwenden.src
, wenn wur Uber-Jars (als externe Bibliothek) einsetzen.
Achtung! Auf GitHub habe ich weitere Informationen über die Standardverzeichnisstruktur zusammengetragen.
Nun erstellen wir die Verzeichnisse textures
und sounds
in assets
. Ich werde exemplarisch dieses Bild und diesen Sound in unserem Tutorial verwenden. Zum Herunterladen klicken Sie einfach auf den Link und dann auf „Download“. Es spielt aber keine Rolle, ob sie meine Beispieldateien verwenden: Sie können gerne auch Ihre eigenen nutzen.
Ist das getan, platzieren wir das Bild und den Sound, den wir in unserem Spiel verwenden möchten, in textures
bzw. sounds
.
Feature 1: Spielfigur
Zuerst ersetzen wir das blaue Rechteck, das aktuell noch den Spieler darstellt, durch ein Bild unserer Wahl. Das lässt sich leicht erledigen, wenn man mit einem Fluent API arbeitet. Tatsächlich gibt es nur eine Zeile Code aus dem vorherigen Teil, die wir ersetzen müssen:
@Override protected void initGame() { player = FXGL.entityBuilder() .at(300, 300) //.view(new Rectangle(25, 25, Color.BLUE)) .view("brick.png") .buildAndAttach(); }
Die Bilddatei, die ich verwendet habe, heißt brick.png
und befindet sich unter assets/textures/
. Daher weiß FXGL, dass es sich um eine Textur handelt und so können wir einfach nur den Namen verwenden. Wenn die Datei einen anderen Namen hat, dann verwendet man stattdessen entsprechend diesen Namen.
Wir sollten nun in der Lage sein, den Spieler zu bewegen (der nun nicht mehr durch ein blaues Rechteck, sondern durch ein Ziegelbild dargestellt wird). War doch nicht zu schwer, oder? 👍
Feature 2: UI-Bild
Erinnern Sie sich daran, wo wir den UI-Code platziert haben? Genau, er ist in initUI()
. Lassen Sie uns das Folgende hinzufügen (Achtung! Da wir mit Java 11 arbeiten, können wir var
verwenden):
var brickTexture = FXGL.getAssetLoader().loadTexture("brick.png"); brickTexture.setTranslateX(50); brickTexture.setTranslateY(450); FXGL.getGameScene().addUINode(brickTexture);
Allein durch Lesen des Codes, sollte ziemlich einfach zu verstehen sein. Wir können jedes Asset laden, indem wir FXGL.getAssetLoader().load ...
aufrufen. Da wir sie von textures/
aus laden, wird dann loadTexture()
angehängt. Die vollständige Liste der von FXGL unterstützten Asset-Typen finden sich auf GitHub.
Achtung! Eine Texture
ist gleichzeitig auch ein JavaFX Node
, sodass sie nun problemlos im User Interface verwendet und von UI-Methoden wie setTranslate()
aufgerufen werden kann. Wir sind fast fertig! 😃
Feature 3: Sound
Also, wir wollen einen Sound abspielen! Das können wir machen, indem wir FXGL.play("drop.wav")
aufrufen. Dieser Befehl ruft wiederum den AssetLoader
auf, um den Sound zu laden und abzuspielen, daher ist es eine sogenannte Convenience-Methode. Damit uns mit initInput()
nicht langweilig wird, können wir folgendes hinzufügen:
input.addAction(new UserAction("Play Sound") { @Override protected void onActionBegin() { FXGL.play("drop.wav"); } }, KeyCode.F);
Es sollte kein zu großes Rätsel sein, was das bewirkt, wenn man sich den Code anschaut. Beim Drücken von F
wird der Sound abgespielt. Vergleichen wir onActionBegin
mit onAction
: Ersteres bedeutet, die Aktion nur einmal innerhalb desselben Frames auszuführen, sobald die Taste gedrückt wird.
Wir könnten, wie wir es auch bei den Texture
-Objekten gemacht haben, FXGL.getAssetLoader().loadSound("drop.wav")
aufrufen, einige Einstellungen vornehmen und dann die Datei abspielen. Wenn wir jedoch einen Sound nur einmal mit Standardeinstellungen abspielen möchten, dann ist FXGL.play("drop.wav")
viel prägnanter.
Jetzt ost klar, wie wir dem Spiel Bilder und Sounds hinzufügen können. Yeah!
Der vollständige Quellcode ist, wie immer, unten aufgeführt:
package tutorial; import com.almasb.fxgl.app.GameApplication; import com.almasb.fxgl.app.GameSettings; import com.almasb.fxgl.dsl.FXGL; import com.almasb.fxgl.entity.Entity; import com.almasb.fxgl.input.Input; import com.almasb.fxgl.input.UserAction; import javafx.scene.input.KeyCode; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.scene.text.Text; import java.util.Map; public class BasicGameApp extends GameApplication { @Override protected void initSettings(GameSettings settings) { settings.setWidth(600); settings.setHeight(600); settings.setTitle("Basic Game App"); settings.setVersion("0.1"); } @Override protected void initInput() { Input input = FXGL.getInput(); input.addAction(new UserAction("Move Right") { @Override protected void onAction() { player.translateX(5); // move right 5 pixels FXGL.getGameState().increment("pixelsMoved", +5); } }, KeyCode.D); input.addAction(new UserAction("Move Left") { @Override protected void onAction() { player.translateX(-5); // move left 5 pixels FXGL.getGameState().increment("pixelsMoved", +5); } }, KeyCode.A); input.addAction(new UserAction("Move Up") { @Override protected void onAction() { player.translateY(-5); // move up 5 pixels FXGL.getGameState().increment("pixelsMoved", +5); } }, KeyCode.W); input.addAction(new UserAction("Move Down") { @Override protected void onAction() { player.translateY(5); // move down 5 pixels FXGL.getGameState().increment("pixelsMoved", +5); } }, KeyCode.S); input.addAction(new UserAction("Play Sound") { @Override protected void onActionBegin() { FXGL.play("drop.wav"); } }, KeyCode.F); } @Override protected void initGameVars(Map<String, Object> vars) { vars.put("pixelsMoved", 0); } private Entity player; @Override protected void initGame() { player = FXGL.entityBuilder() .at(300, 300) //.view(new Rectangle(25, 25, Color.BLUE)) .view("brick.png") .buildAndAttach(); } @Override protected void initUI() { Text textPixels = new Text(); textPixels.setTranslateX(50); // x = 50 textPixels.setTranslateY(100); // y = 100 textPixels.textProperty().bind(FXGL.getGameState().intProperty("pixelsMoved").asString()); FXGL.getGameScene().addUINode(textPixels); // add to the scene graph var brickTexture = FXGL.getAssetLoader().loadTexture("brick.png"); brickTexture.setTranslateX(50); brickTexture.setTranslateY(450); FXGL.getGameScene().addUINode(brickTexture); } public static void main(String[] args) { launch(args); } }
Viel Spaß!
Lust auf mehr? Im nächsten Tutorial geht es um darum, wie wir zum Spiel Kollisionen hinzufügen können. Stay tuned! Wer mehr über die Kernfunktionen wissen oder vorgefertigten Spielen experimentieren will, findet dazu alles auf GitHub.
Hinterlasse einen Kommentar
Hinterlasse den ersten Kommentar!