了解和探索GameApplication:FXGL17指南
最编程
2024-07-23 21:40:59
...
PS:禁止拷贝形式转载,转载请以URL形式
PS:FXGL 准备写成一个系列,所以在该系列未完成前,该系列文章除了目录会被修改其他内容均可能被删改。
1. 简介
本章主要总结游戏运行的大致流程以及相关函数的使用,最后编写一个简单的DEMO 达到认识FXGL表层是怎么运行和FXGL大致是怎么开发的。
2. GameApplication 运行流程
PS:本小节描述FXGL 规定下游戏的大致运行流程以及各个流程相关含义
2.1. 流程分析
graph LR
Start --> initSettings
subgraph 程序初始化
initSettings
--> initInput
--> onPreInit
end
onPreInit --> initGameVars
subgraph 游戏初始化
initGameVars
--> initGame
--> initPhysics
--> initUI
--> onUpdate -- 循环 --> onUpdate
end
onUpdate --> Stop
流程对应函数
- initSettings :游戏设置(全局的游戏设置如标题、版本、图标等)
- initInput :初始化绑定 输入/控制事件(游戏里面的按键事件绑定如
w
按键按下代表物体向上移动) - onPreInit :游戏预先资源初始化(游戏里面对大文件资源如地图的预先加载)
- initGameVars :初始化游戏变量(游戏里面使用到的变量如击杀敌人数量、死亡次数等相关变量的初始化)
- initGame :初始化游戏(游戏中需要创建的ENTITY玩家进行初始化)
- initPhysics :初始化绑定 碰撞事件(对具有可碰撞的相关ENTITY进行事件绑定处理 )
- initUI :初始化UI(界面的初始元素设置)
- onUpdate :游戏更新UI时调用的钩子函数,FXGL 每1帧动画的更新都会调用该函数
2.2. 涉及代码
代码
import com.almasb.fxgl.app.GameApplication;
import com.almasb.fxgl.app.GameSettings;
import com.almasb.fxgl.dsl.FXGL;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import java.util.Map;
/**
* @ClassName
* @Description
* @Author dyf
* @Date 2022/6/30
* @Version 1.0
*/
public class KnowGAApp extends GameApplication {
private int updateNums = 0;
@Override
protected void initSettings(GameSettings gameSettings) {
System.out.println("KnowGAApp.initSettings");
gameSettings.setTitle("KnowGAApp");
gameSettings.setVersion("1.0");
gameSettings.setMainMenuEnabled(true);
}
@Override
protected void initInput() {
System.out.println("KnowGAApp.initInput");
}
@Override
protected void onPreInit() {
System.out.println("KnowGAApp.onPreInit");
}
@Override
protected void initGameVars(Map<String, Object> vars) {
System.out.println("KnowGAApp.initGameVars");
}
@Override
protected void initGame() {
System.out.println("KnowGAApp.initGame");
}
@Override
protected void initPhysics() {
System.out.println("KnowGAApp.initPhysics");
}
@Override
protected void initUI() {
System.out.println("KnowGAApp.initUI");
Text text = FXGL.getUIFactoryService().newText("HELLO FXGL", Color.BLACK, 22);
FXGL.addUINode(text, FXGL.getAppCenter().getX(), FXGL.getAppCenter().getY());
}
@Override
protected void onUpdate(double tpf) {
if (updateNums<=2) {
System.out.println("KnowGAApp.onUpdate");
updateNums++;
}
}
public static void main(String[] args) {
launch(args);
}
}
输出
KnowGAApp.initSettings
16:09:51.059 [JavaFX Application Thread] INFO Engine - FXGL-17.1 (24.03.2022 17.34) on WINDOWS (J:17 FX:17.0.2-ea)
16:09:51.060 [JavaFX Application Thread] INFO Engine - Source code and latest versions at: https://github.com/AlmasB/FXGL
16:09:51.060 [JavaFX Application Thread] INFO Engine - Ask questions and discuss at: https://github.com/AlmasB/FXGL/discussions
16:09:51.061 [JavaFX Application Thread] INFO Engine - Join the FXGL chat at: https://gitter.im/AlmasB/FXGL
16:09:51.864 [FXGL Background Thread 1 ] INFO FXGLApplication - FXGL initialization took: 0.557 sec
KnowGAApp.initInput
KnowGAApp.onPreInit
KnowGAApp.initGameVars
KnowGAApp.initGame
KnowGAApp.initPhysics
KnowGAApp.initUI
16:09:53.013 [FXGL Background Thread 2 ] INFO FXGLApplication - Game initialization took: 0.001 sec
KnowGAApp.onUpdate
KnowGAApp.onUpdate
KnowGAApp.onUpdate
3. 拾取金币game
PS:本小节写一个demo将对应流程的函数串联使用起来,demo内容为展示游戏角色由用户控制拾取金币并显示当前金币数量
3.1 涉及代码
package priv.dyf.fxgl.helloworld;
import com.almasb.fxgl.app.GameApplication;
import com.almasb.fxgl.app.GameSettings;
import com.almasb.fxgl.core.math.FXGLMath;
import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.physics.CollisionHandler;
import javafx.geometry.Point2D;
import javafx.geometry.Rectangle2D;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.util.Duration;
import java.util.List;
import java.util.Map;
/**
* @ClassName
* @Description
* @Author dyf
* @Date 2022/6/30
* @Version 1.0
*/
public class KnowGAApp extends GameApplication {
static final String GOLD_KEY = "gold";
static final String FPS_KEY = "fps";
private ImageView background;
private int fps;
private Entity player;
enum GameObj {
PLAYER, GOLD;
}
@Override
protected void initSettings(GameSettings gameSettings) {
gameSettings.setTitle("KnowGAApp");
gameSettings.setVersion("1.0");
}
@Override
protected void initInput() {
//绑定按键,控制角色行动
FXGL.onKey(KeyCode.UP, () -> player.translateY(-5));
FXGL.onKey(KeyCode.DOWN, () -> player.translateY(5));
FXGL.onKey(KeyCode.LEFT, () -> player.translateX(-5));
FXGL.onKey(KeyCode.RIGHT, () -> player.translateX(5));
}
@Override
protected void onPreInit() {
//预先加载背景图片
Image image = FXGL.image("background.png");
background = new ImageView(image);
background.setFitHeight(FXGL.getAppHeight() - 22);
background.setFitWidth(FXGL.getAppWidth());
}
@Override
protected void initGameVars(Map<String, Object> vars) {
//初始化金币变量并赋值
vars.put(GOLD_KEY, 0);
vars.put(FPS_KEY, 0);
}
@Override
protected void initGame() {
//添加背景
FXGL.entityBuilder().view(background).at(0, 22).buildAndAttach();
//创建玩家
player = FXGL.entityBuilder()
.viewWithBBox(new Rectangle(40, 40, Color.BLUE)) //创建一个20*20的正方形,添加到视图场景并且设置其物理场景下大小也为20*20
.at(FXGL.getAppCenter()) //玩家创建后初始化的位置
.type(GameObj.PLAYER) //设置类型:不设置物理引擎无法识别
.collidable() //设置可碰撞:不设置物理引擎无法判断
.buildAndAttach(); //创建并且添加到游戏世界中
//间隔1S,定时生成金币,刷新FPS
Rectangle2D rectangle2D = new Rectangle2D(100, 100, FXGL.getAppWidth() - 200, FXGL.getAppHeight() - 200);
FXGL.getGameTimer().runAtInterval(() -> {
//刷新FPS
FXGL.set(FPS_KEY, fps);
fps = 0;
//查找现有金币数量
List<Entity> golds = FXGL.getGameWorld().getEntitiesByType(GameObj.GOLD);
//游戏世界里最多生成10枚金币
if (golds.size() < 10) {
//随机生成的金币不要和现有的金币产生位置冲突
Point2D point2D = FXGLMath.randomPoint(rectangle2D);
while (!FXGL.getGameWorld().getEntitiesInRange(new Rectangle2D(point2D.getX(), point2D.getY(), 10, 10)).isEmpty()) {
point2D = FXGLMath.randomPoint(rectangle2D);
}
//生成金币
FXGL.entityBuilder()
.viewWithBBox(new Circle(10, Color.RED)) //创建一个半径10的圆形,添加到视图场景并且设置其物理场景下大小也为10
.at(point2D) //创建后初始化的位置
.type(GameObj.GOLD) //设置类型:不设置物理引擎无法识别
.collidable() //设置可碰撞:不设置物理引擎无法判断
.buildAndAttach(); //创建并且添加到游戏世界中
}
}, Duration.seconds(1));
}
@Override
protected void initPhysics() {
FXGL.getPhysicsWorld().addCollisionHandler(new CollisionHandler(GameObj.PLAYER, GameObj.GOLD) {
// 类型的顺序与传入构造函数的顺序相同
@Override
protected void onCollisionBegin(Entity player, Entity gold) {
//删除金币
gold.removeFromWorld();
//增加分数
FXGL.inc(GOLD_KEY, 1);
}
});
}
@Override
protected void initUI() {
//创建UI并且添加到游戏场景
Text text = FXGL.getUIFactoryService().newText("", Color.BLACK, 22);
text.textProperty().bind(FXGL.getWorldProperties().intProperty(GOLD_KEY).asString("金币: %s"));
FXGL.addUINode(text, FXGL.getAppCenter().getX(), 22);
Text fps = FXGL.getUIFactoryService().newText("", Color.BLACK, 22);
fps.textProperty().bind(FXGL.getWorldProperties().intProperty(FPS_KEY).asString("FPS: %s"));
FXGL.addUINode(fps, 0, 22);
}
@Override
protected void onUpdate(double tpf) {
fps++;
}
public static void main(String[] args) {
launch(args);
}
}
3.2 效果展示
推荐阅读
-
探索排序算法:了解【打擂台算法】、【冒泡算法】和【选择排序】
-
深入了解BFGS和L-BFGS:机器学习系列探索
-
Android分辨率转换和屏幕适配指南:了解常见分辨率(mdpi、hdpi 、xhdpi、xxhdpi )的尺寸单位和相关调整方法
-
新手入门摸鱼指南:探索羊驼和有趣的代码注释
-
入门指南:了解Web 3D的三大引擎(Direct3D、OpenGL、Unreal Engine、Unity和Three.js)
-
Tomcat和JDK的版本搭配指南:探索各版本特性
-
全面了解和掌握CreateJs的入门指南
-
你知道WiFi和蓝牙的区别吗?这份5分钟速成指南让你快速了解!
-
论坛管理新手指南:了解和设置板块的O2OA教程
-
搞定前端代码!一文了解HTML、CSS、JavaScript和Vue的规范指南