《开源精选》是我们分享Github、Gitee等开源社区中优质项目的栏目,包括技术、学习、实用与各种有趣的内容。本期推荐的是使用JavaFX / Kotlin开发的2D和3D游戏引擎——FXGL。
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>
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<String, Object> 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));
}
运行后游戏将如下所示:
更多示例
另外,FXGL还提供了大量的完整游戏示例,包括炸弹人、飞翔的小鸟、马里奥、太空游侠、吃豆人等,如果你想学习如何开发一个2D游戏,可以参考一下这些示例。
项目地址:
https://github.com/AlmasB/FXGLGames
—END—
开源地址:github.com/AlmasB/FXGL
原文始发于微信公众号(开源技术专栏):开源精选 | 一个基于JavaFX的2D游戏引擎
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/53966.html