FXGL Tutorial: Kollisionen hinzufügen mit JavaFX

© Shutterstock / pixeldreams.eu
Willkommen zum dritten Teil unseres FXGL-11-Tutorials! Nachdem wir unser Spiel mit Grafiken und Soundeffekten ausgestattet haben, werden wir uns in diesem Teil dem Hinzufügen von Kollisionen widmen. Hier können Sie den zweiten Teil des Tutorials nachholen, falls Sie das noch nicht gemacht haben sollten. Wie zuvor gilt, dass dieses Tutorial auf FXGL 11.0+ und Java 11+ ausgelegt ist.
Legen wir los – dieses Mal haben wir zwei Aufgaben zu erledigen. Wir werden zunächst eine weitere Entität hinzufügen. Anschließend werden wir einen Handler erstellen, der sich zwischen der Spielfigur und der neuen Entität befinden wird. Damit sehen unsere Aufgaben wie folgt aus:
- Hinzufügen der Münzen-Entität
- Hinzufügen des Collision Handlers, der die Interaktion zwischen Spielfigur und Münze verwaltet
Zum Schluss dieses Tutorials sollten Sie folgendes erhalten:

Quelle: GitHub
Vorbereitung
Damit unsere Kollisionen auch funktionieren können, müssen wir zuerst FXGL darüber informieren, was für Typen von Entitäten vorhanden sind. Im Falle unseres Spiels wären das die Entitäten der Spielfigur und der Münze. Hier empfiehlt es sich, den Typ durch ein enum (enumerated Type; Aufzählungstyp) darzustellen. Also machen wir uns daran, den Aufzählungstyp EntityType
zu erstellen.
public enum EntityType { PLAYER, COIN }
Aufgabe 1: Hinzufügen der Münzen-Entität
Jetzt werden wir eine brandneue Entität hinzufügen – die Münze. Das machen wir in initGame()
:
FXGL.entityBuilder() .type(EntityType.COIN) .at(500, 200) .viewWithBBox(new Circle(15, Color.YELLOW)) .with(new CollidableComponent(true)) .buildAndAttach();
Wir können den Typ der Entität durch einen Aufruf von .type()
festlegen. Danach verwenden wir viewWithBBox()
, damit FXGL die Entity Bounding Box aus deren Ansicht erstellen kann, bei der es sich um einen gelben Kreis handelt. Und schließlich fügen wir CollidableComponent
hinzu, um die Entität so zu markieren, dass sie an der Kollisionserkennung und -behandlung teilnehmen können.
Aufgabe 2: Hinzufügen des Collision Handlers
Jetzt werden wir unsere Spielfigur-Entität leicht modifizieren. Mittlerweile sollte genug Wissen vorhanden sein, um die folgenden Methodenaufrufe zu verstehen.
player = Entities.builder() .type(EntityType.PLAYER) .at(300, 300) .viewFromTextureWithBBox("brick.png") .with(new CollidableComponent(true)) .buildAndAttach(getGameWorld());
Nun sind die Spielfigur und die Münze dazu bereit, an der Kollisionserkennung teilzunehmen. Zum Schluss müssen wir noch den eigentlichen Handler hinzufügen, d. h. den Code, der ausgeführt wird, wenn Spielfigur und Münze miteinander kollidieren.
@Override protected void initPhysics() { FXGL.getPhysicsWorld().addCollisionHandler(new CollisionHandler(EntityType.PLAYER, EntityType.COIN) { // order of types is the same as passed into the constructor @Override protected void onCollisionBegin(Entity player, Entity coin) { coin.removeFromWorld(); } }); }
Wir fügen den Handler an die physics-Komponente an (Vergesst nicht, import com.almasb.fxgl.physics.CollisionHandler;
auszuführen). Der Handler-Konstruktor nimmt zwei Entitätstypen: Wir haben zuerst PLAYER
übergeben und dann COIN
. Demzufolge wird die Reihenfolge der Entitäten in onCollisionBegin()
dem gleichen Schema folgen, also zuerst player
und dann coin
. In diesem Beispiel rufen wir lediglich coin.removeFromWorld()
auf, das die Münzen-Entität aus der Spielwelt entfernt.
Jetzt wissen wir, wie man zwei Entitäten miteinander kollidieren lassen kann und wie man nach deren Kollision-Events Ausschau halten kann. Gut gemacht!
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.entity.components.CollidableComponent; import com.almasb.fxgl.input.Input; import com.almasb.fxgl.input.UserAction; import com.almasb.fxgl.physics.CollisionHandler; import javafx.scene.input.KeyCode; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.scene.text.Text; import java.util.Map; /** * @author Almas Baimagambetov (almaslvl@gmail.com) */ 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"); } public enum EntityType { PLAYER, COIN } @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() .type(EntityType.PLAYER) .at(300, 300) .viewWithBBox("brick.png") .with(new CollidableComponent(true)) .buildAndAttach(); FXGL.entityBuilder() .type(EntityType.COIN) .at(500, 200) .viewWithBBox(new Circle(15, Color.YELLOW)) .with(new CollidableComponent(true)) .buildAndAttach(); } @Override protected void initPhysics() { FXGL.getPhysicsWorld().addCollisionHandler(new CollisionHandler(EntityType.PLAYER, EntityType.COIN) { // order of types is the same as passed into the constructor @Override protected void onCollisionBegin(Entity player, Entity coin) { coin.removeFromWorld(); } }); } @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); } }
Stay tuned! Wer mehr über die Kernfunktionen wissen oder vorgefertigten Spielen experimentieren will, findet dazu alles auf GitHub.
Hinterlasse einen Kommentar