前言
学习使用java开发游戏。FXGL是基于javaFX的一个游戏引擎框架。对于java开发来说,上手简单。本笔记为记录FXGL中常用的一些API和注意要点。后续自己开发过程中,如果发现问题或者描述不对的地方,再进行修改。
学习过程参考 LeeWyatt 的 FXGL基础入门教程
环境
- JDK:openjdk-17
- fxgl: 17
依赖
xml
<dependency>
<groupId>com.github.almasb</groupId>
<artifactId>fxgl</artifactId>
<version>17</version>
</dependency>
正文
编写一个最简单的游戏启动类,
- 创建一个maven项目
- 添加fxgl依赖
- 编写TestApp主类(一般启动类使用App结尾)
- 在module-info.java模块类中,开启并引入fxgl
代码
java
package com.cah.api;
import com.almasb.fxgl.app.GameApplication;
import com.almasb.fxgl.app.GameSettings;
import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.time.LocalTimer;
import javafx.util.Duration;
import java.util.Map;
/**
* <p> Api主类 </p>
*
* @author hongtool
* @date 2023/8/13
*/
public class ApiApp extends GameApplication {
/** 计时器 */
private LocalTimer timer;
public static void main(String[] args) {
// 开始执行
launch(args);
}
/** 最先执行 */
public ApiApp() {
System.out.println("构造器==》" + Thread.currentThread().getName());
}
/** 第二步,执行游戏初始化设置 */
@Override
protected void initSettings(GameSettings gameSettings) {
// 可以设置 游戏的 标题、图标、版本、宽度、高度等,具体的内容稍后参考《GameSettings》学习资料
// 图标资源,参考 《FXGL 资源分类》学习资料
System.out.println("ApiApp.initSettings==》" + Thread.currentThread().getName());
// 注意:在此方法中,不要执行"FXGL."的静态方法。会出错。因为这时候FXGL的相关属性引擎尚未加载
}
/** 第三步,执行游戏的输入监听 */
@Override
protected void initInput() {
// 包括键盘输入,鼠标输入等
System.out.println("ApiApp.initInput==》" + Thread.currentThread().getName());
}
/** 第四步,资源预加载初始化 */
@Override
protected void onPreInit() {
// 预加载游戏背景音乐,设置是否开启背景音乐和音效等。
System.out.println("ApiApp.onPreInit==》" + Thread.currentThread().getName());
}
/** 第五步,初始化游戏参数 */
@Override
protected void initGameVars(Map<String, Object> vars) {
// 通过map的形式,保存游戏中的通用参数。
// 在其他地方使用 FXGL.getip(key)的方式进行获取,FXGL.set(key,value)的方式进行重新赋值
System.out.println("ApiApp.initGameVars==》" + Thread.currentThread().getName());
}
/** 第六步,初始化游戏(重点) */
@Override
protected void initGame() {
// 初始化计时器(为什么要在这里初始化呢?因为)
timer = FXGL.newLocalTimer();
System.out.println("ApiApp.initGame==》" + Thread.currentThread().getName());
}
/** 第七步,初始化游戏物理引擎(重点) */
@Override
protected void initPhysics() {
// 物理碰撞事件等
System.out.println("ApiApp.initPhysics==》" + Thread.currentThread().getName());
}
/** 第八步,初始化UI界面 */
@Override
protected void initUI() {
System.out.println("ApiApp.initUI==》" + Thread.currentThread().getName());
}
/** 最后一步,游戏每一帧都会调用改方法。默认为60帧 */
@Override
protected void onUpdate(double tpf) {
// 如果计时器走过1秒,则打印
if(timer.elapsed(Duration.seconds(1))) {
// 重置计时器
timer.capture();
System.out.println("ApiApp.onUpdate==》" + Thread.currentThread().getName());
}
}
}
结果
运行main方法,查看执行结果
txt
构造器==》main
ApiApp.initSettings==》main
ApiApp.initInput==》JavaFX Application Thread
ApiApp.onPreInit==》JavaFX Application Thread
ApiApp.initGameVars==》FXGL Background Thread 1
ApiApp.initGame==》FXGL Background Thread 1
ApiApp.initPhysics==》FXGL Background Thread 1
ApiApp.initUI==》FXGL Background Thread 1
22:50:57.515 [FXGL Background Thread 1 ] INFO FXGLApplication - Game initialization took: 0.002 sec
ApiApp.onUpdate==》JavaFX Application Thread
ApiApp.onUpdate==》JavaFX Application Thread
ApiApp.onUpdate==》JavaFX Application Thread
ApiApp.onUpdate==》JavaFX Application Thread
开发菜单页面
在initSettings
方法中,添加开启菜单代码
java
@Override
protected void initSettings(GameSettings gameSettings) {
gameSettings.setMainMenuEnabled(true);
System.out.println("ApiApp.initSettings==》" + Thread.currentThread().getName());
}
操作过程
- 运行
main
方法 - 等待游戏启动,观察日志为运行了四分方法,顺序为:
构造器
>initSettings
>initInput
>onPreInit
;其他的方式都没有执行 - 点击【NEW GAME】按钮,发现执行了
initGameVars
>initGame
>initPhysics
>initUI
>一直调用onUpdate
- 这时按【Esc】按键,暂停游戏,发现
onUpdate
没有执行 - 点击【MAIN MENU】按钮,返回主菜单界面。
- 再次点击【NEW GAME】按钮,发现也是执行了第3点的方法。但是
线程名称
名称不一样,说明启动了新线程执行,但是onUpdate
还是主线程在执行。
总结
通过重写方法,打印日志,和操作分析,可以观察 GameApplication 各个方法的执行顺序与用途。