欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

FXGL17 - 探索物理之路:预告——FXGL 系列进行中,敬请留意,目录会定期更新,但文章内容在未完结前可能会有调整和删减哦!

最编程 2024-07-23 21:18:12
...

1. 简介

本章介绍如何将实体添加到物理世界中并如何添加处理其物理碰撞事件

2. 添加物理世界

  • view():将实体添加到视图场景并标识其大小和形状
  • bbox():将实体添加到物理世界并标识其大小和形状
FXGL.entityBuilder()
        .view(new Rectangle(20, 20, Color.AQUA))
        .bbox(BoundingShape.box(20,20))
        .buildAndAttach();

上述代码可以简写为

  • viewWithBBox():将实体添加到视图场景和物理世界中并标识其大小和形状
FXGL.entityBuilder()
        .at(FXGL.getAppCenter())
        .viewWithBBox(new Rectangle(20, 20, Color.AQUA))
        .buildAndAttach();

3. 物理对象调试

setDeveloperMenuEnabled(boolean enable):开启时,按键1打开开发者菜单

@Override
protected void initSettings(GameSettings gameSettings) {
    gameSettings.setDeveloperMenuEnabled(true);
}

调试:实体添加到物理世界但是没有添加到场景中时,

public class PhysicsWorldApp extends GameApplication {

    @Override
    protected void initSettings(GameSettings gameSettings) {
        gameSettings.setDeveloperMenuEnabled(true);
    }

    @Override
    protected void initGame() {
        FXGL.entityBuilder()
                .at(FXGL.getAppCenter())
                //.view(new Rectangle(20, 20, Color.AQUA))
                .bbox(BoundingShape.box(20,20))
                //.viewWithBBox(new Rectangle(20, 20, Color.AQUA))
                .buildAndAttach();
    }

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

1.gif

调试:实体添加到物理世界和游戏场景中但是物理世界位置和游戏场景的位置不一致

HitBox(Point2D orgin,BoundingShape shape):orgin 该物理世界下物体偏移坐标,shape 物理世界下的形状大小

public class PhysicsWorldApp extends GameApplication {

    @Override
    protected void initSettings(GameSettings gameSettings) {
        gameSettings.setDeveloperMenuEnabled(true);
    }

    @Override
    protected void initGame() {
        FXGL.entityBuilder()
                .at(FXGL.getAppCenter())
                .view(new Rectangle(20, 20, Color.AQUA))
                .bbox(new HitBox(new Point2D(20,20),BoundingShape.box(20,20)))
                .buildAndAttach();
    }

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

1.gif

2. 简单碰撞

一个实体代表一个物理形状与其他添加到物理世界中实体的碰撞处理

  • type():设置实体类型,用于物理碰撞检测的必要条件
  • viewWithBBox():设置游戏场景以及物理对象大小和形状。必须设置BBox其物理世界下的形状大小,用于物理碰撞检测的必要条件
  • collidable():可碰撞。用于物理碰撞检测的必要条件
public class PhysicsWorldApp extends GameApplication {
    
    public enum Type {
        BLUE, RED;
    }

    Entity blue;

    @Override
    protected void initSettings(GameSettings gameSettings) {
        gameSettings.setDeveloperMenuEnabled(true);
    }

    @Override
    protected void initInput() {
        FXGL.onKey(KeyCode.LEFT, () -> blue.translateX(-3));
        FXGL.onKey(KeyCode.RIGHT, () -> blue.translateX(3));
    }

    @Override
    protected void initGameVars(Map<String, Object> vars) {
        vars.put("status", "未接触");
    }

    @Override
    protected void initGame() {
        FXGL.entityBuilder()
                .at(FXGL.getAppCenter())
                .type(Type.RED)
                .viewWithBBox(new Rectangle(20, 20, Color.RED))
                .collidable()
                .buildAndAttach();

        blue = FXGL.entityBuilder()
                .at(FXGL.getAppCenter().getX() + 50, FXGL.getAppCenter().getY())
                .type(Type.BLUE)
                .viewWithBBox(new Rectangle(20, 20, Color.BLUE))
                .collidable()
                .buildAndAttach();
    }


    @Override
    protected void initPhysics() {
        FXGL.getPhysicsWorld().addCollisionHandler(new CollisionHandler(Type.RED, Type.BLUE) {
            @Override
            protected void onCollisionBegin(Entity a, Entity b) {
                FXGL.set("status", "已接触");
            }

            @Override
            protected void onCollisionEnd(Entity a, Entity b) {
                FXGL.set("status", "未接触");
            }
        });
    }
    
    @Override
    protected void initUI() {
        Text text = FXGL.getUIFactoryService().newText("", Color.BLACK, 22);
        text.textProperty().bind(FXGL.getWorldProperties().stringProperty("status"));
        FXGL.addUINode(text, FXGL.getAppCenter().getX(), 22);
    }

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

1.gif

3. 复杂碰撞

一个实体包含多个物理形状与其他物理实体的碰撞处理

  • onHitBoxTrigger():判断触碰的具体是哪一个HitBox物理模型
  • PS:如果已经接触到了upBox 没有离开所属实体再去触碰downBox是不会触发onHitBoxTrigger事件的
public class PhysicsWorld2App extends GameApplication {

    public enum Type {
        BLUE, RED;
    }

    Entity blue;

    @Override
    protected void initSettings(GameSettings gameSettings) {
    }

    @Override
    protected void initInput() {
        FXGL.onKey(KeyCode.LEFT, () -> blue.translateX(-3));
        FXGL.onKey(KeyCode.RIGHT, () -> blue.translateX(3));
        FXGL.onKey(KeyCode.UP, () -> blue.translateY(-3));
        FXGL.onKey(KeyCode.DOWN, () -> blue.translateY(3));
    }

    @Override
    protected void initGameVars(Map<String, Object> vars) {
        vars.put("status", "未接触");
    }

    @Override
    protected void initGame() {
        Rectangle up = new Rectangle(20, 60, Color.BLACK);
        Rectangle down = new Rectangle(20, 60, Color.BROWN);
        down.setTranslateY(60);
        HitBox upBox = new HitBox("up", BoundingShape.box(20, 60));
        HitBox downBox = new HitBox("down", new Point2D(0, 60), BoundingShape.box(20, 60));
        FXGL.entityBuilder()
                .at(FXGL.getAppCenter().getX() + 100, FXGL.getAppCenter().getY())
                .type(Type.RED)
                .view(up)
                .view(down)
                .bbox(upBox)
                .bbox(downBox)
                .collidable()
                .buildAndAttach();

        blue = FXGL.entityBuilder()
                .at(FXGL.getAppCenter().getX() + 50, FXGL.getAppCenter().getY())
                .type(Type.BLUE)
                .viewWithBBox(new Rectangle(20, 20, Color.BLUE))
                .collidable()
                .buildAndAttach();
    }

    @Override
    protected void initPhysics() {
        FXGL.getPhysicsWorld().addCollisionHandler(new CollisionHandler(Type.RED, Type.BLUE) {
            @Override
            protected void onHitBoxTrigger(Entity a, Entity b, HitBox boxA, HitBox boxB) {
                FXGL.set("status", "击中了" + boxA.getName());
            }
        });
    }

    @Override
    protected void initUI() {
        Text text = FXGL.getUIFactoryService().newText("", Color.BLACK, 22);
        text.textProperty().bind(FXGL.getWorldProperties().stringProperty("status"));
        FXGL.addUINode(text, FXGL.getAppCenter().getX(), 22);
    }

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

1.gif