前言 {#前言}
上一章我们讲了变量与UI,这章我们讲FXGL的计时器。
函数说明 {#函数说明}
在一秒钟之后执行一次 {#在一秒钟之后执行一次}
runOnce(()->{
// ...
}, Duration.seconds(1));
每隔0.5秒执行一次 {#每隔05秒执行一次}
run(()->{
// ...
},Duration.seconds(0.5));
实例 {#实例}
目标效果 {#目标效果}
每隔一秒在游戏的上方随机位置生成一个敌人,并向下移动; 当Player与敌方实体碰撞时扣除1分。
敌方实体 {#敌方实体}
首先我们需要定义一个敌方实体类型,并初始化敌方实体的生成工厂。
/**
* 实体类型
* @author lhDream
*/
public enum EntityType {
PLAYER,GOLD,ENEMY
}
敌方实体
/**
* 创建Enemy实体
* @return Enemy实体
*/
@Spawns("Enemy")
public Entity newEnemy(SpawnData data){
// 移动速度, 200 - 400 内随机
var speed = FXGLMath.random(200,400);
return FXGL.entityBuilder(data)
//声明设备类型
.type(EntityType.ENEMY)
// 根据UI大小自动生成碰撞体积
.collidable()
.with(new ProjectileComponent(new Point2D(0, 1), speed))
// 宽 50px 高 50px 颜色蓝色
.viewWithBBox(new Rectangle(50,50, Color.BLUE))
// 超出边界移除实体
.with(new OffscreenCleanComponent())
.build();
}
定时创建敌方实体 {#定时创建敌方实体}
// 每秒生成一个敌方实体
run(()->{
// 生成坐标
var x = FXGLMath.random(0,getAppWidth()-50);
var y = FXGLMath.random(-50,0);
spawn(<span class="hljs-string">"Enemy"</span>,x,y);
`},Duration.seconds(`1`));
`
碰撞效果 {#碰撞效果}
onCollisionBegin(EntityType.PLAYER, EntityType.ENEMY,(player, enemy)->{
inc("integral",-1);
});
效果展示 {#效果展示}
完整代码 {#完整代码}
HelloWorldApp.java {#helloworldappjava}
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.scene.input.KeyCode;
import javafx.scene.paint.Color;
import javafx.util.Duration;
import java.util.Map;
import static com.almasb.fxgl.dsl.FXGL.\*;
import static com.almasb.fxgl.dsl.FXGL.onCollisionBegin;
/**
`
`
* `
`@author lhDream
*/
public class HelloWorldApp extends GameApplication {
`
`
/**
`
`
* 玩家实体
*/
private Entity player;
`
`
/**
`
`
*
初始化设置
*
@param settings 配置对象
*/
@Override
protected void initSettings(GameSettings settings) {
settings.setTitle("Hello world");
settings.setWidth(600);
settings.setHeight(600);
settings.setMainMenuEnabled(true);
settings.setGameMenuEnabled(true);
}
`
`
/**
`
`
*
初始化游戏内容
*/
@Override
protected void initGame() {
// 注册实体工厂
FXGL.getGameWorld().addEntityFactory(new DemoEntityFactory());
// 在界面正中间生成玩家实体
player = FXGL.spawn("Player",FXGL.getAppWidth()/2,FXGL.getAppHeight()/2);
// 在界面200,200位置生成一个Gold实体
spawn("Gold", 200,200);
// 每秒生成一个敌方实体
run(()->{
// 生成坐标
var x = FXGLMath.random(0,getAppWidth()-50);
var y = FXGLMath.random(-50,0);
spawn(<span class="hljs-string">"Enemy"</span>,x,y);
},Duration.seconds(1));
}
`
`
/**
`
`
* 初始化输入
*/
@Override
protected void initInput() {
onKey(KeyCode.W,"上",()->{
player.translateY(-5);
});
onKey(KeyCode.S,"下",()->{
player.translateY(+5);
});
onKey(KeyCode.A,"左",()->{
player.translateX(-5);
});
onKey(KeyCode.D,"右",()->{
player.translateX(+5);
});
}
`
`
/**
`
`
*
初始化物理引擎(碰撞效果)
*/
@Override
protected void initPhysics() {
getPhysicsWorld().addCollisionHandler(new CollisionHandler(EntityType.PLAYER,EntityType.GOLD){
@Override
protected void onCollisionBegin(Entity player, Entity gold) {
//将gold对象从游戏中移除
gold.removeFromWorld();
// 设置参数+1
inc("integral",+1);
// 在界面内随机位置生成一个 Gold对象
spawn("Gold", FXGLMath.random(0,getAppWidth()-50),FXGLMath.random(0,getAppHeight()-50));
}
});
onCollisionBegin(EntityType.PLAYER, EntityType.ENEMY,(player, enemy)->{
inc("integral",-1);
});
}
`
`
/**
`
`
* 初始化参数
* @param vars
*/
@Override
protected void initGameVars(Map<String, Object> vars) {
vars.put("integral",0);
}
`
`
/**
`
`
* 初始化UI
*/
@Override
protected void initUI() {
// 初始化 Text 字体大小18 颜色 粉色
var scoreText = getUIFactoryService().newText("", Color.PINK, 18);
scoreText.textProperty().bind(getip("integral").asString("分数: %d"));
addUINode(scoreText, 10, 30);
}
`
`
/**
`
``
`
* main 程序的开始
* @param` args 参数
*/``
`public` `static` `void` `main(String[] args)` {
launch(args);
}
}
`
DemoEntityFactory.java {#demoentityfactoryjava}
import com.almasb.fxgl.core.math.FXGLMath;
import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.dsl.components.OffscreenCleanComponent;
import com.almasb.fxgl.dsl.components.ProjectileComponent;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.entity.EntityFactory;
import com.almasb.fxgl.entity.SpawnData;
import com.almasb.fxgl.entity.Spawns;
import javafx.geometry.Point2D;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
/**
*
实体工厂
*
@author lhDream
\*/
public class DemoEntityFactory implements EntityFactory {
/**
* 创建玩家实体
* @return 玩家实体
*/
@Spawns("Player")
public Entity newPlayer(SpawnData data){
return FXGL.entityBuilder(data)
// 声明设备类型
.type(EntityType.PLAYER)
// 将实体标记为可碰撞,并根据UI大小自动生成碰撞体积
.collidable()
// 宽 10px 高 10px 颜色黑色
.viewWithBBox(new Rectangle(50,50, Color.BLACK))
.build();
}
/**
* 创建Gold实体
* @return Gold实体
/
@Spawns("Gold")
public Entity newGold(SpawnData data){
return FXGL.entityBuilder(data)
//声明设备类型
.type(EntityType.GOLD)
// 根据UI大小自动生成碰撞体积
.collidable()
// 宽 50px 高 50px 颜色红色
.viewWithBBox(new Rectangle(50,50, Color.RED))
.build();
}
/*
* 创建Enemy实体
* @return Enemy实体
*/
@Spawns("Enemy")
public Entity newEnemy(SpawnData data){
// 移动速度, 200 - 400 内随机
var speed = FXGLMath.random(200,400);
return FXGL.entityBuilder(data)
//声明设备类型
.type(EntityType.ENEMY)
// 根据UI大小自动生成碰撞体积
.collidable()
.with(new ProjectileComponent(new Point2D(0, 1), speed))
// 宽 50px 高 50px 颜色蓝色
.viewWithBBox(new Rectangle(50,50, Color.BLUE))
// 超出边界移除实体
.with(new OffscreenCleanComponent())
.build();
}
`}
`
EntityType.java {#entitytypejava}
/**
* 实体类型
* @author lhDream
*/
public enum EntityType {
PLAYER,GOLD,ENEMY
}
完整项目 {#完整项目}
https://github.com/lhDream/lhDreamGameDemo/tree/master/HelloWorld