FXGL JAVA游戏引擎 教程 02.组件

本文介绍了如何在FXGL游戏框架中通过创建组件来赋予实体移动功能。详细展示了如何编写MoveComponent,包括设置移动速度、方向,并为组件添加向上、向下、向左、向右及停止的方法。最后,将组件绑定到实体,并通过键盘输入控制飞机的移动。
摘要由CSDN通过智能技术生成

FXGL 攻略 02.组件

在FXGL中,实体的各种功能和表现都通过组件来进行实现。这很好理解,一个汽车实体,通过添加移动组件来使之具有移动能力,添加物理组件来监听碰撞效果等。

  1. 创建一个组件
    新建一个moveComponent 作为飞机的移动功能组件。编写这个组件前,我们需要理解一个新的概念坐标
    移动的本质是在每次游戏刷新时将实体坐标更新,我们可以通过改变在X轴与Y轴的速度来作为每次游戏刷新时移动的坐标。对此可以写出
public class MoveComponent extends Component {
    private double speedX = 0d;
    private double speedY = 0d;
    private double maxSpeed = 4d;
    @Override
    public void onUpdate(double tpf) {
            if (speedX != 0d) {
            //计算出该速度在x轴上每次刷新移动后的坐标
                    Vec2 dir = Vec2.fromAngle(entity.getRotation() - 360)
                            .mulLocal(speedX);
                            //改变实体的坐标
                    entity.translate(dir);
            }
            if (speedY != 0d) {
                    Vec2 dir = Vec2.fromAngle(entity.getRotation() - 90)
                            .mulLocal(speedY);
                    entity.translate(dir);
            }
    }


}
  1. 为组件添加方法
    我们上面已经写好了一个可以在更新时移动的方法,那么接下来就需要将其扩展,我们知道我们需要有向上移动,向下移动,向左移动,向右移动等在移动中的方法。还需要有一个停止方法。
public class MoveComponent extends Component {
    private double speedX = 0d;
    private double speedY = 0d;
    private double maxSpeed = 4d;
    @Override
    public void onUpdate(double tpf) {
            if (speedX != 0d) {
                    Vec2 dir = Vec2.fromAngle(entity.getRotation() - 360)
                            .mulLocal(speedX);
                    entity.translate(dir);
            }
            if (speedY != 0d) {
                    Vec2 dir = Vec2.fromAngle(entity.getRotation() - 90)
                            .mulLocal(speedY);
                    entity.translate(dir);
            }
    }

    public void up() {
        speedY = maxSpeed;
    }
    public void left() {
        speedX = -maxSpeed;
    }
    public void right() {
        speedX = maxSpeed;
    }
    public void down(){
        speedY = -maxSpeed;
    }
    public void stop() {
        speedX = 0d;
        speedY = 0d;
    }


}
  1. 将组件绑定至实体
    修改实体工厂类,注意,我们给实体的新增了移动组件以外,我们还为其新增了一个type属性,方便后面获取。
/**
 1. 实体静态工厂
 */
public class CustomerEntityFactory {
    public static Entity createEntity(EntityType type){
        switch (type) {
            case PLANE -> {
               Entity entity = FXGL.entityBuilder().view("player.png").with(new MoveComponent()).build();
               entity.setType(EntityType.PLANE);
               return entity;
            }
            default -> {
                return null;
            }

    }
}
}
  1. 接下来是测试阶段,注意,按钮绑定将在下一章详细讲解,这里只做展示。修改主程序。
public class GameApp extends GameApplication {

    /**
     * Initialize game objects.
     */
    @Override
    protected void initGame() {
        FXGL.getGameWorld().addEntity(CustomerEntityFactory.createEntity(EntityType.PLANE));
        FXGL.getInput().addAction(new UserAction("up") {
            @Override
            protected void onAction() {
                super.onAction();
            }

            @Override
            protected void onActionBegin() {
                List<Entity> entitiesByType = FXGL.getGameWorld().getEntitiesByType(EntityType.PLANE);
                entitiesByType.get(0).getComponent(MoveComponent.class).up();

            }

            @Override
            protected void onActionEnd() {
                List<Entity> entitiesByType = FXGL.getGameWorld().getEntitiesByType(EntityType.PLANE);
                entitiesByType.get(0).getComponent(MoveComponent.class).stop();
            }
        }, KeyCode.W);

        FXGL.getInput().addAction(new UserAction("down") {
            @Override
            protected void onAction() {
                super.onAction();
            }

            @Override
            protected void onActionBegin() {
                List<Entity> entitiesByType = FXGL.getGameWorld().getEntitiesByType(EntityType.PLANE);
                entitiesByType.get(0).getComponent(MoveComponent.class).down();

            }

            @Override
            protected void onActionEnd() {
                List<Entity> entitiesByType = FXGL.getGameWorld().getEntitiesByType(EntityType.PLANE);
                entitiesByType.get(0).getComponent(MoveComponent.class).stop();
            }
        }, KeyCode.S);

        FXGL.getInput().addAction(new UserAction("left") {
            @Override
            protected void onAction() {
                super.onAction();
            }

            @Override
            protected void onActionBegin() {
                List<Entity> entitiesByType = FXGL.getGameWorld().getEntitiesByType(EntityType.PLANE);
                entitiesByType.get(0).getComponent(MoveComponent.class).left();

            }

            @Override
            protected void onActionEnd() {
                List<Entity> entitiesByType = FXGL.getGameWorld().getEntitiesByType(EntityType.PLANE);
                entitiesByType.get(0).getComponent(MoveComponent.class).stop();
            }
        }, KeyCode.A);


        FXGL.getInput().addAction(new UserAction("right") {
            @Override
            protected void onAction() {
                super.onAction();
            }

            @Override
            protected void onActionBegin() {
                List<Entity> entitiesByType = FXGL.getGameWorld().getEntitiesByType(EntityType.PLANE);
                entitiesByType.get(0).getComponent(MoveComponent.class).right();

            }

            @Override
            protected void onActionEnd() {
                List<Entity> entitiesByType = FXGL.getGameWorld().getEntitiesByType(EntityType.PLANE);
                entitiesByType.get(0).getComponent(MoveComponent.class).stop();
            }
        }, KeyCode.D);
    }

    @Override
    protected void initSettings(GameSettings settings) {
        settings.setTitle("demo");
        settings.setHeight(720);
        settings.setWidth(1080);
    }

    public static void main(String[] args) {
        launch(args);
    }
}

运行一下! 这个飞机它会动啦!

FXGL 总目录

FXGL 中,可以通过 `FXGL.getSceneService().pushScene(targetScene)` 方法来跳转到目标场景。为了方便起见,我们可以创建一个自定义的组件来实现场景跳转功能。 首先,创建一个名为 `SceneSwitchComponent` 的类,继承 `com.almasb.fxgl.entity.component.Component` 类,代码如下: ```java import com.almasb.fxgl.core.serialization.Bundle; import com.almasb.fxgl.entity.component.Component; public class SceneSwitchComponent extends Component { private String targetScene; public SceneSwitchComponent(String targetScene) { this.targetScene = targetScene; } @Override public void onUpdate(double tpf) { // 空实现,不需要实现 onUpdate 方法 } @Override public void onAdded() { // 点击实体时跳转到目标场景 entity.getViewComponent().addEventHandler(MouseEvent.MOUSE_CLICKED, event -> { FXGL.getSceneService().pushScene(targetScene); }); } @Override public void onRemoved() { // 移除事件监听器 entity.getViewComponent().removeEventHandler(MouseEvent.MOUSE_CLICKED, event -> { FXGL.getSceneService().pushScene(targetScene); }); } @Override public void write(Bundle bundle) { bundle.put("targetScene", targetScene); } @Override public void read(Bundle bundle) { targetScene = bundle.get("targetScene"); } } ``` 这个组件包含一个 `targetScene` 字段,表示要跳转的目标场景名称。在 `onAdded()` 方法中,我们为实体的 `ViewComponent` 添加了一个鼠标点击事件监听器,当用户点击实体时,就会自动跳转到目标场景。`onRemoved()` 方法用于在移除组件时移除事件监听器。 接下来,在需要使用场景跳转功能的实体上添加 `SceneSwitchComponent` 组件即可。例如,我们可以创建一个名为 `Button` 的实体,代码如下: ```java import com.almasb.fxgl.entity.Entities; import com.almasb.fxgl.entity.Entity; import javafx.geometry.Pos; import javafx.scene.paint.Color; import javafx.scene.text.Font; import javafx.scene.text.Text; public class Button extends Entity { public Button(String text, String targetScene) { Text textNode = new Text(text); textNode.setFont(Font.font(24)); textNode.setFill(Color.WHITE); setViewFromNode(textNode); setAlignment(Pos.CENTER); addComponent(new SceneSwitchComponent(targetScene)); } } ``` 这个实体包含一个用于显示文本的 `Text` 节点,并且添加了一个 `SceneSwitchComponent` 组件。创建实体时需要传入两个参数,分别是文本内容和目标场景名称。 最后,在游戏场景中添加这个 `Button` 实体,代码如下: ```java import com.almasb.fxgl.app.scene.GameScene; import com.almasb.fxgl.entity.Entity; import com.almasb.fxgl.entity.Entities; public class MyGameScene extends GameScene { public MyGameScene() { Entity button = Entities.builder() .at(400, 300) .viewFromNode(new Button("跳转到场景2", "scene2")) .build(); addEntities(button); } } ``` 这里创建了一个名为 `MyGameScene` 的游戏场景,并且添加了一个 `Button` 实体。当用户点击这个实体时,就会自动跳转到名为 `scene2` 的场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值