开源精选 | 一个基于JavaFX的2D游戏引擎

《开源精选》是我们分享Github、Gitee等开源社区中优质项目的栏目,包括技术、学习、实用与各种有趣的内容。本期推荐的是使用JavaFX / Kotlin开发的2D和3D游戏引擎——FXGL。

开源精选 | 一个基于JavaFX的2D游戏引擎

FXGL是一个基于JavaFX的2D和3D游戏引擎,适合开发任何类型的2D游戏,包括横向卷轴、平台、街机、RPG等。并提供了大量的游戏示例来帮助我们掌握游戏开发技能。

FXGL特性:

  • 无需安装,开箱即用,支持Java 8-15、Win/Mac/Linux/Android 8+/iOS 11.0+/Web

  • 简单干净的API,比其他引擎更高效

  • JavaFX的超集:无需学习新的UI API

  • 真实世界的游戏开发技术:实体组件、插值动画、粒子等等

  • 游戏很容易打包成单个可执行文件 .jar 或本机映像

依赖

Maven

<dependency>

<groupId>com.github.almasb</groupId>

<artifactId>fxgl</artifactId>

<version>11.17</version>

</dependency>

Gradle

compile 'com.github.almasb:fxgl:11.17'

简单示例:一个乒乓球游戏

默认情况下,FXGL 将游戏大小设置为 800×600,这适用于我们的游戏。您可以通过 更改这些设置和各种其他设置settings.setXXX()。现在,我们将只设置标题并添加入口点 – main()。

public class PongApp extends GameApplication {

    @Override
    protected void initSettings(GameSettings settings) {
        settings.setTitle("Pong");
    }

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

接下来,我们将定义一些不言自明的常量。

private static final int PADDLE_WIDTH = 30;
private static final int PADDLE_HEIGHT = 100;
private static final int BALL_SIZE = 20;
private static final int PADDLE_SPEED = 5;
private static final int BALL_SPEED = 5;

我们有三个游戏对象,特别是两个桨和一个球。FXGL 中的游戏对象称为Entity. 所以,让我们定义我们的实体。

private Entity paddle1;
private Entity paddle2;
private Entity ball;

接下来,我们将查看输入。与某些框架不同,不需要手动查询输入状态。在 FXGL 中,我们通过定义动作(游戏应该做什么)并将它们绑定到输入触发器(按下某物时)来处理输入。例如:

@Override
protected void initInput() {
    getInput().addAction(new UserAction("Up 1") {
        @Override
        protected void onAction() {
            paddle1.translateY(-PADDLE_SPEED);
        }
    }, KeyCode.W);

    // ...
}

上面的意思是,当W被按下时,paddle在 Y 轴上移动-PADDLE_SPEED,这实际上意味着向上移动桨。剩下的输入:

getInput().addAction(new UserAction("Down 1") {
    @Override
    protected void onAction() {
        paddle1.translateY(PADDLE_SPEED);
    }
}, KeyCode.S);

getInput().addAction(new UserAction("Up 2") {
    @Override
    protected void onAction() {
        paddle2.translateY(-PADDLE_SPEED);
    }
}, KeyCode.UP);

getInput().addAction(new UserAction("Down 2") {
    @Override
    protected void onAction() {
        paddle2.translateY(PADDLE_SPEED);
    }
}, KeyCode.DOWN);

我们现在将添加游戏变量来记录玩家 1 和玩家 2 的分数。我们可以使用int score1;. 但是,FXGL 提供了一个强大的属性概念,它建立在 JavaFX 属性之上。澄清一下,FXGL 中的每个变量都在内部存储为 JavaFX 属性,因此是可观察和可绑定的。我们声明变量如下:

@Override
protected void initGameVars(Map<StringObject> vars) {
    vars.put("score1"0);
    vars.put("score2"0);
}

FXGL 将根据默认值推断每个变量的类型。在这种情况下 0 是 type int,因此score1将被分配int类型。稍后我们将看到这些变量与原始 Java 类型相比有多么强大。

@Override
protected void initGame() {
    paddle1 = spawnBat(0, getHeight() / 2 - PADDLE_HEIGHT / 2);
    paddle2 = spawnBat(getWidth() - PADDLE_WIDTH, getHeight() / 2 - PADDLE_HEIGHT / 2);

    ball = spawnBall(getWidth() / 2 - BALL_SIZE / 2, getHeight() / 2 - BALL_SIZE / 2);
}

private Entity spawnBat(double x, double y) {
    return Entities.builder()
            .at(x, y)
            .viewFromNodeWithBBox(new Rectangle(PADDLE_WIDTH, PADDLE_HEIGHT))
            .buildAndAttach();
}

private Entity spawnBall(double x, double y) {
    return Entities.builder()
            .at(x, y)
            .viewFromNodeWithBBox(new Rectangle(BALL_SIZE, BALL_SIZE))
            .with("velocity"new Point2D(BALL_SPEED, BALL_SPEED))
            .buildAndAttach();

我们要求Entities建造者:

1、在给定的 x, y 创建一个新实体
2、使用我们提供的视图
3、从视图生成边界框
4、将创建的实体添加到游戏世界中
5、添加了一个名为“速度”的 Point2D 类型的新实体属性

此后,我们设计了由两个Text对象组成的 UI 。重要的是,我们将这些对象的 text 属性绑定到我们之前创建的两个变量。这是 FXGL 变量提供的强大功能之一。更具体地说,当score1更新时,textScore1UI 对象的文本将自动更新。

@Override
protected void onUpdate(double tpf) {
    Point2D velocity = ball.getObject("velocity");
    ball.translate(velocity);

    if (ball.getX() == paddle1.getRightX()
            && ball.getY() < paddle1.getBottomY()
            && ball.getBottomY() > paddle1.getY()) {
        ball.setProperty("velocity"new Point2D(-velocity.getX(), velocity.getY()));
    }

    if (ball.getRightX() == paddle2.getX()
            && ball.getY() < paddle2.getBottomY()
            && ball.getBottomY() > paddle2.getY()) {
        ball.setProperty("velocity"new Point2D(-velocity.getX(), velocity.getY()));
    }

    if (ball.getX() <= 0) {
        getGameState().increment("score2", +1);
        resetBall();
    }

    if (ball.getRightX() >= getWidth()) {
        getGameState().increment("score1", +1);
        resetBall();
    }

    if (ball.getY() <= 0) {
        ball.setY(0);
        ball.setProperty("velocity"new Point2D(velocity.getX(), -velocity.getY()));
    }

    if (ball.getBottomY() >= getHeight()) {
        ball.setY(getHeight() - BALL_SIZE);
        ball.setProperty("velocity"new Point2D(velocity.getX(), -velocity.getY()));

我们获取球的“速度”属性并使用它在每一帧上平移(移动)球。然后,我们对球相对于游戏窗口和球拍的位置进行各种检查。如果球击中窗口的顶部或底部,则我们在 Y 轴上反转。类似地,如果球击中桨,那么我们会反转 X 轴。最后,如果球未击中球拍并击中屏幕的一侧,则相反地球拍得分并重置球。复位方法如下:

private void resetBall() {
    ball.setPosition(getWidth() / 2 - BALL_SIZE / 2, getHeight() / 2 - BALL_SIZE / 2);
    ball.setProperty("velocity"new Point2D(BALL_SPEED, BALL_SPEED));
}

运行后游戏将如下所示:

开源精选 | 一个基于JavaFX的2D游戏引擎

更多示例

另外,FXGL还提供了大量的完整游戏示例,包括炸弹人、飞翔的小鸟、马里奥、太空游侠、吃豆人等,如果你想学习如何开发一个2D游戏,可以参考一下这些示例。

项目地址:
https://github.com/AlmasB/FXGLGames

开源精选 | 一个基于JavaFX的2D游戏引擎


—END—

开源地址:github.com/AlmasB/FXGL


原文始发于微信公众号(开源技术专栏):开源精选 | 一个基于JavaFX的2D游戏引擎

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/53966.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!