Teil 2: Neue Features einarbeiten

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

Almas Baimagambetov

© 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:

  1. Die Spielfigur soll durch ein Bild dargestellt werden.
  2. Dem UI des Spiels soll ein Bild hinzugefügt werden.
  3. 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:

<a href="https://github.com/AlmasB/FXGL/wiki/Adding-Images-and-Sounds-%28FXGL-11%29">Quelle</a>

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.

Verwandte Themen:

Geschrieben von
Almas Baimagambetov
Almas Baimagambetov
Almas is engaged with research in the field of Automated Diagram Generation. He also teaches Computer Science. In his spare time, he enjoys playing video games as well as designing and developing them.
Kommentare

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
4000
  Subscribe  
Benachrichtige mich zu: