1. 简介
jMonkeyEngine 是一个现代化的、对开发者友好的游戏引擎,我们可以用它来构建游戏或其他 Java 3D 应用程序。
本教程将深入探讨 jMonkeyEngine,学习它的核心功能、应用场景以及使用方法。
2. 依赖管理
使用 jMonkeyEngine 前,需要将 最新版本 (目前是 3.7.0-stable)添加到构建文件中。
有两种主流管理方式:手动配置依赖,或使用 jMonkeyEngine 提供的初始化器(类似 Spring Initializr)生成现成项目。此外,jMonkeyEngine 还提供基于 NetBeans 的 SDK,集成了额外工具简化开发,但你可以自由选择其他 IDE。
2.1. 初始化器
最简单的方式是访问官方初始化页面 https://jmonkeyengine.org/start/:
只需填写几个关键选项:
- 应用名称
- 目标平台(桌面/Android/VR)
- 部署系统(桌面端可选择 Windows/macOS/Linux)
下载后即可获得开箱即用的项目结构:
├── README.txt
├── build.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── scripts
│ └── desktopDeployment
│ ├── BaeldungTesting.bat
│ ├── BaeldungTesting.command
│ └── BaeldungTesting.sh
├── settings.gradle
└── src
└── main
└── java
└── com
└── baeldung
└── jmonkeyengine
└── BaeldungTesting.java
通过 ./gradlew build
构建项目,使用 ./gradlew run
运行:
2.2. 手动管理项目
也可自行创建项目结构并添加依赖,获得更高的灵活性。
桌面端至少需要这些依赖:
<dependency>
<groupId>org.jmonkeyengine</groupId>
<artifactId>jme3-core</artifactId>
<version>3.7.0-stable</version>
</dependency>
<dependency>
<groupId>org.jmonkeyengine</groupId>
<artifactId>jme3-desktop</artifactId>
<version>3.7.0-stable</version>
</dependency>
<dependency>
<groupId>org.jmonkeyengine</groupId>
<artifactId>jme3-lwjgl3</artifactId>
<version>3.7.0-stable</version>
</dependency>
⚠️ **启动时必须添加 JVM 参数 -XstartOnFirstThread
**,否则会收到错误提示。手动启动方式为执行主类。
3. 创建第一个应用
现在我们有了 jMonkeyEngine 基础框架,开始构建第一个应用。
应用核心是继承 SimpleApplication
的类:
public class FirstApplication extends SimpleApplication {
@Override
public void simpleInitApp() {
}
}
必须重写 simpleInitApp()
方法(稍后说明其用途)。启动应用:
public static void main(String[] args) {
FirstApplication app = new FirstApplication();
app.start();
}
SimpleApplication
自动提供:
- 左下角的调试信息
- 场景漫游的飞行相机
- 默认窗口标题/尺寸/位置
- Esc 退出快捷键
3.1. 默认行为
查看 SimpleApplication
默认构造函数,发现它依赖多个 AppState
实例:
public SimpleApplication() {
this(new StatsAppState(), new FlyCamAppState(), new AudioListenerState(), new DebugKeysAppState(),
new ConstantVerifierState());
}
这些类在应用主循环中执行,包括:
StatsAppState
:渲染左下角调试统计FlyCamAppState
:实现场景飞行控制AudioListenerState
:更新音频监听器位置DebugKeysAppState
:设置按键映射(如打印相机位置)ConstantVerifierState
:检查引擎常量是否被违反
Esc 键处理是单独实现的。可传入自定义 AppState
替代默认配置:
public FirstApplication() {
super(new StatsAppState());
}
3.2. 应用设置
创建应用时可配置窗口参数,通过 setSettings()
方法覆盖默认值:
AppSettings settings = new AppSettings(true);
setSettings(settings);
AppSettings
构造参数 true
表示先加载默认设置,后续可覆盖:
settings.setWidth(1024);
settings.setHeight(768);
settings.setCenterWindow(false);
settings.setWindowXPosition(0);
settings.setWindowYPosition(0);
settings.setTitle("Our First Application");
这会将窗口定位到屏幕左上角,尺寸设为 1024×768,并更新标题。
4. 渲染几何体
有了应用窗口,现在渲染内容。
在 simpleInitApp()
方法中创建几何体。该方法在引擎完全初始化后执行,是初始化场景的理想位置。
渲染步骤:
创建网格(jMonkeyEngine 提供
Box
/Sphere
/Torus
等内置形状):Box mesh = new Box(1, 2, 3);
创建一个 x 轴长度 1、y 轴 2、z 轴 3 的长方体。网格也可以是从文件加载的复杂模型。
将网格包装为
Geometry
:Geometry geometry = new Geometry("Box", mesh);
必须为几何体指定材质,否则无法正确渲染:
Material material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); material.setColor("Color", ColorRGBA.Red); geometry.setMaterial(material);
创建无光照材质,设置颜色为红色。材质可按需调整复杂度。
将几何体添加到场景根节点:
rootNode.attachChild(geometry);
实际是长方体,但因正对视角所以显示为矩形。
4.1. 几何体变换
目前几何体直接添加到根节点,未应用任何变换。通常需要平移/旋转/缩放几何体。
通过 Node
应用变换:
Node rotation = new Node("rotation");
rotation.rotate(0.2f, 0.4f, 0.6f);
rotation.attachChild(geometry);
rootNode.attachChild(rotation);
将几何体绕 x 轴旋转 0.2 弧度、y 轴 0.4 弧度、z 轴 0.6 弧度。渲染后可见长方体结构:
构建场景时,可创建 Node
树结构,每个节点应用独立变换,变换会作用于整个子树。
5. 更新循环
除 simpleInitApp()
初始化外,可通过 simpleUpdate()
执行每帧更新:
@Override
public void simpleUpdate(float timePerFrame) {
}
每帧渲染时调用一次,timePerFrame
参数表示距上一帧的时间(秒)。在方法内访问并更新场景:
@Override
public void simpleUpdate(float timePerFrame) {
Spatial rotation = rootNode.getChild("rotation");
rotation.rotate(0, timePerFrame, 0);
}
通过名称获取 "rotation" 节点,根据帧时间更新旋转,使长方体持续自转:
可在此循环中处理几何体更新或其他每帧逻辑。
6. 处理用户输入
除固定运行的场景外,还能响应用户输入(键盘/鼠标/手柄等)。
jMonkeyEngine 提供 InputManager
管理输入。首先为输入操作注册名称:
inputManager.addMapping("Rotate", new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_J));
inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_K));
允许修改输入绑定或使用多个按键触发同一操作。然后绑定监听器:
inputManager.addListener(actionListener, "Rotate");
inputManager.addListener(analogListener, "Left", "Right");
注册了两种监听器类型:
ActionListener
响应离散动作(如单次按键):
ActionListener actionListener = new ActionListener() {
@Override
public void onAction(String name, boolean isPressed, float tpf) {
if (name.equals("Rotate") && !isPressed) {
rotationEnabled = !rotationEnabled;
}
}
};
空格键("Rotate")在释放时切换旋转状态。
AnalogListener
响应持续动作(如长按按键):
AnalogListener analogListener = new AnalogListener() {
@Override
public void onAnalog(String name, float value, float tpf) {
if (name.equals("Left")) {
rotation.rotate(0, -tpf, 0);
} else if (name.equals("Right")) {
rotation.rotate(0, tpf, 0);
}
}
};
J 键("Left")和 K 键("Right")长按时控制场景旋转方向。
7. 总结
本文快速介绍了 jMonkeyEngine 的核心功能。这个库能做的事情远不止于此,下次想用 Java 开发游戏时,不妨试试它!