在FXGL游戏引擎中,使用Texture组件可以非常方便地为游戏中的实体对象设置外观。一个非常常见的需求是随机改变对象的颜色,这对于生成多样化的游戏世界或产生不同的视觉效果非常有用。本文将介绍如何在FXGL引擎中实现这一功能,通过随机改变对象的颜色来丰富游戏的表现。
1.核心概念
在FXGL引擎中,Texture用于为实体设置图像或图形外观。通过对Texture应用颜色变换,开发者可以改变其外观效果。FXGL提供了multiplyColor()方法,该方法允许将一个颜色乘到纹理上,从而实现颜色的修改。
2.实现随机颜色变化
我们将通过创建一个Tank实体来展示如何为Texture对象应用随机颜色。在ImageEntityFactory类中,我们使用FXGLMath.randomColor()生成一个随机颜色,并将其应用到Tank的纹理上。为了使颜色更加鲜亮,我们还使用了brighter()方法来加深效果。
package com.alatus.game;
import com.almasb.fxgl.core.math.FXGLMath;
import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.dsl.components.ExpireCleanComponent;
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 com.almasb.fxgl.physics.BoundingShape;
import com.almasb.fxgl.texture.AnimatedTexture;
import com.almasb.fxgl.texture.AnimationChannel;
import com.almasb.fxgl.texture.Texture;
import javafx.util.Duration;
public class ImageEntityFactory implements EntityFactory {
// 创建Car实体
@Spawns("Car")
public Entity newCar(SpawnData data) {
Texture carLeft = FXGL.texture("car.png");
Texture carRight = carLeft.copy();
carRight.setScaleX(-1);
carRight.setTranslateX(carLeft.getWidth());
return FXGL.entityBuilder(data)
.view(carLeft)
.view(carRight)
.bbox(BoundingShape.box(carLeft.getWidth() * 2, carLeft.getHeight()))
.build();
}
// 创建FatCar实体
@Spawns("FatCar")
public Entity newFatCar(SpawnData data) {
Texture leftCar = FXGL.texture("fat_car.png");
Texture rightCar = leftCar.copy();
rightCar.setScaleX(-1);
rightCar.setTranslateX(leftCar.getWidth());
return FXGL.entityBuilder(data)
.view(leftCar)
.view(rightCar)
.bbox(BoundingShape.box(leftCar.getWidth() * 2, leftCar.getHeight()))
.build();
}
// 创建Boom实体
@Spawns("Boom")
public Entity newBoom(SpawnData data) {
AnimationChannel animationChannel = new AnimationChannel(FXGL.image("Boom.png"),
Duration.seconds(2),
13);
AnimatedTexture animatedTexture = new AnimatedTexture(animationChannel);
animatedTexture.play();
return FXGL.entityBuilder(data)
.view(animatedTexture)
.with(new ExpireCleanComponent(Duration.seconds(2.5)))
.build();
}
// 创建Warrior实体
@Spawns("Warrior")
public Entity newWarrior(SpawnData data) {
AnimationChannel animationChannel = new AnimationChannel(FXGL.image("warrior.png"),
4, 32, 48, Duration.seconds(0.8), 0, 3);
AnimatedTexture animatedTexture = new AnimatedTexture(animationChannel);
animatedTexture.loop();
return FXGL.entityBuilder(data)
.view(animatedTexture)
.build();
}
// 创建Tank实体并应用随机颜色
@Spawns("Tank")
public Entity newTank(SpawnData data) {
// 加载Tank纹理
Texture tank = FXGL.texture("Tank.png", 100, 100);
// 应用随机颜色
Texture tank1 = tank.multiplyColor(FXGLMath.randomColor()).brighter();
return FXGL.entityBuilder(data)
.view(tank1) // 将随机颜色应用到Tank实体
.build();
}
}
在newTank()方法中,我们通过FXGLMath.randomColor()生成一个随机颜色,并使用multiplyColor()方法将其应用到Tank的纹理上。为了让颜色更加鲜亮,调用了brighter()方法。
3.生成随机位置的实体
我们通过spawn()方法生成多个Tank实体,并让它们随机出现在屏幕上的不同位置。通过FXGLMath.randomPoint()方法生成一个随机坐标,使得每次生成的坦克的位置不同。
package com.alatus.game;
import com.almasb.fxgl.app.GameApplication;
import com.almasb.fxgl.app.GameSettings;
import com.almasb.fxgl.core.math.FXGLMath;
import com.almasb.fxgl.entity.SpawnData;
import javafx.geometry.Rectangle2D;
import static com.almasb.fxgl.dsl.FXGL.*;
public class ImageGame extends GameApplication {
@Override
protected void initSettings(GameSettings gameSettings) {
// 设置游戏窗口大小等
}
@Override
protected void initGame() {
// 向游戏世界添加实体工厂
getGameWorld().addEntityFactory(new ImageEntityFactory());
// 创建不同的实体
spawn("Car", new SpawnData(100, 100));
spawn("FatCar", new SpawnData(350, 350));
spawn("Boom", new SpawnData(200, 200));
spawn("Warrior", new SpawnData(300, 300));
// 随机生成5个Tank实体
for (int i = 0; i < 5; i++) {
spawn("Tank", FXGLMath.randomPoint(
new Rectangle2D(0, 0, 500, 500) // 随机生成位置
));
}
}
public static void main(String[] args) {
launch(args); // 启动游戏
}
}
在initGame()方法中,我们使用了spawn("Tank", FXGLMath.randomPoint(new Rectangle2D(0, 0, 500, 500)))来随机生成5个坦克,每个坦克都有一个随机的颜色和随机的生成位置。
4.总结
通过以上代码,我们已经在FXGL引擎中实现了随机改变Texture颜色的功能。通过FXGLMath.randomColor()生成随机颜色并应用到实体的纹理上,我们能够为每个实体带来独特的视觉效果,增加了游戏世界的多样性和趣味性。
这种方式不仅适用于简单的图像变换,还可以用于生成具有不同外观的敌人、道具等,提供更多的视觉变化和随机性。
完整代码示例
package com.alatus.game;
import com.almasb.fxgl.core.math.FXGLMath;
import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.dsl.components.ExpireCleanComponent;
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 com.almasb.fxgl.physics.BoundingShape;
import com.almasb.fxgl.texture.AnimatedTexture;
import com.almasb.fxgl.texture.AnimationChannel;
import com.almasb.fxgl.texture.Texture;
import javafx.util.Duration;
public class ImageEntityFactory implements EntityFactory {
@Spawns("Car")
public Entity newCar(SpawnData data){
// 一般就是在这里读取图片的时候就设置一波像素大小,节省内存,而且后面也不用缩放那么麻烦
Texture carLeft = FXGL.texture("car.png");
Texture carRight = carLeft.copy();
// 翻转-1就是水平镜像翻转,虽然我不懂原理
carRight.setScaleX(-1);
carRight.setTranslateX(carLeft.getWidth());
return FXGL.entityBuilder(data)
.view(carLeft)
.view(carRight)
.bbox(BoundingShape.box(carLeft.getWidth()*2,carLeft.getHeight()))
.build();
}
@Spawns("FatCar")
public Entity newFatCar(SpawnData data){
Texture leftCar = FXGL.texture("fat_car.png");
Texture rightCar = leftCar.copy();
rightCar.setScaleX(-1);
rightCar.setTranslateX(leftCar.getWidth());
return FXGL.entityBuilder(data)
.view(leftCar)
.view(rightCar)
.bbox(BoundingShape.box(leftCar.getWidth()*2,leftCar.getHeight()))
.build();
}
@Spawns("Boom")
public Entity newBoom(SpawnData data){
AnimationChannel animationChannel = new AnimationChannel(FXGL.image("Boom.png"),
Duration.seconds(2),
13);
AnimatedTexture animatedTexture = new AnimatedTexture(animationChannel);
animatedTexture.play();
return FXGL.entityBuilder(data)
.view(animatedTexture)
.with(new ExpireCleanComponent(Duration.seconds(2.5)))
.build();
}
@Spawns("Warrior")
public Entity newWarrior(SpawnData data){
AnimationChannel animationChannel = new AnimationChannel(FXGL.image("warrior.png"),
4,32,48,Duration.seconds(0.8),0,3);
AnimatedTexture animatedTexture = new AnimatedTexture(animationChannel);
animatedTexture.loop();
return FXGL.entityBuilder(data)
.view(animatedTexture)
.build();
}
@Spawns("Tank")
public Entity newTank(SpawnData data){
Texture tank = FXGL.texture("Tank.png", 100, 100);
Texture tank1 = tank.multiplyColor(FXGLMath.randomColor()).brighter();
return FXGL.entityBuilder(data)
.view(tank1)
.build();
}
}
package com.alatus.game;
import com.almasb.fxgl.app.GameApplication;
import com.almasb.fxgl.app.GameSettings;
import com.almasb.fxgl.core.math.FXGLMath;
import com.almasb.fxgl.entity.SpawnData;
import javafx.geometry.Rectangle2D;
import static com.almasb.fxgl.dsl.FXGL.*;
public class ImageGame extends GameApplication {
@Override
protected void initSettings(GameSettings gameSettings) {
}
@Override
protected void initGame() {
getGameWorld().addEntityFactory(new ImageEntityFactory());
spawn("Car",new SpawnData(100,100));
spawn("FatCar",new SpawnData(350,350));
spawn("Boom",new SpawnData(200,200));
spawn("Warrior",new SpawnData(300,300));
for (int i = 0; i < 5; i++) {
spawn("Tank", FXGLMath.randomPoint(
new Rectangle2D(0,0,500,500)
));
}
}
public static void main(String[] args) {
launch(args);
}
}