Animate entities and JavaFX nodes in FXGL — translate, rotate, scale, and fade entities using AnimationBuilder DSL, play sprite sheet frame animations with AnimatedTexture and AnimationChannel, animate along bezier/path curves, animate JavaFX properties (color, opacity), chain sequential animations, apply easing interpolators, and spawn or despawn entities with built-in scale effects. Use this skill when adding movement tweens, character walk cycles, UI transitions, cutscene animations, or particle-like effects.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Animate entities and JavaFX nodes in FXGL — translate, rotate, scale, and fade entities using AnimationBuilder DSL, play sprite sheet frame animations with AnimatedTexture and AnimationChannel, animate along bezier/path curves, animate JavaFX properties (color, opacity), chain sequential animations, apply easing interpolators, and spawn or despawn entities with built-in scale effects. Use this skill when adding movement tweens, character walk cycles, UI transitions, cutscene animations, or particle-like effects.
All property animations use the builder. Chain options before calling a terminal method.
// Translate entity from A to B over 1 second
animationBuilder()
.duration(Duration.seconds(1))
.interpolator(Interpolators.SMOOTH.EASE_IN_OUT())
.translate(entity)
.from(newPoint2D(0, 0))
.to(newPoint2D(400, 300))
.buildAndPlay(); // starts immediately, fire-and-forget// Or store the Animation for manual controlAnimationanim= animationBuilder()
.duration(Duration.seconds(2))
.translate(entity)
.from(newPoint2D(0, 0))
.to(newPoint2D(600, 400))
.build();
anim.setOnFinished(() -> entity.removeFromWorld());
anim.start();
// anim.stop() / anim.pause() / anim.resume() when needed
// Define a cubic bezier pathCubicCurvepath=newCubicCurve(
100, 500, // start200, 100, // control point 1600, 100, // control point 2700, 500// end
);
animationBuilder()
.duration(Duration.seconds(3))
.alongPath(entity, path)
.buildAndPlay();
Animate JavaFX Property (Custom Value)
// Animate any double property — e.g., a custom shader parameter
AnimatedValue<Double> av = newAnimatedValue<>(0.0, 1.0);
animationBuilder()
.duration(Duration.seconds(2))
.animate(av)
.onProgress(value -> {
myShaderNode.setOpacity(value);
colorRect.setFill(Color.color(value, 0, 1 - value));
})
.buildAndPlay();
Animated String (Text Reveal)
Textlabel= getUIFactoryService().newText("", Color.WHITE, 20);
addUINode(label, 200, 100);
animationBuilder()
.duration(Duration.seconds(2))
.animateString(label, "Hello, World!") // reveals character by character
.buildAndPlay();
Interpolator Reference
// Smooth (S-curve, natural feel)
Interpolators.SMOOTH.EASE_IN()
Interpolators.SMOOTH.EASE_OUT()
Interpolators.SMOOTH.EASE_IN_OUT()
// Elastic (spring overshoot — great for UI pop-ins)
Interpolators.ELASTIC.EASE_OUT()
Interpolators.ELASTIC.EASE_IN()
// Bounce (impact at end)
Interpolators.BOUNCE.EASE_OUT()
// Back (slight overshoot before settle)
Interpolators.BACK.EASE_OUT()
// Exponential (very fast start, slow end or vice versa)
Interpolators.EXPONENTIAL.EASE_IN()
Interpolators.EXPONENTIAL.EASE_OUT()
// Linear (constant speed — rarely looks good for game animations)
Interpolators.LINEAR
// JavaFX built-in
Interpolator.EASE_BOTH // also accepted
Sprite Sheet Animation
// 1. Load texture (8 frames in a row, each 64x64)TexturespriteSheet= getAssetLoader().loadTexture("characters/player.png");
// 2. Create animation channelsAnimationChannelidleChannel=newAnimationChannel(spriteSheet, 4, // 4 cols64, 64, Duration.seconds(0.8), 0, 3); // frames 0-3, loop 0.8sAnimationChannelwalkChannel=newAnimationChannel(spriteSheet, 8, // 8 cols64, 64, Duration.seconds(0.6), 4, 11); // frames 4-11AnimationChanneljumpChannel=newAnimationChannel(spriteSheet, 8,
64, 64, Duration.seconds(0.4), 12, 14, false); // frames 12-14, no loop// 3. Create AnimatedTextureAnimatedTextureanimTex=newAnimatedTexture(idleChannel);
animTex.loop(); // start looping immediately// 4. Attach to entity
entityBuilder()
.view(animTex)
// ...
.buildAndAttach();
// 5. Switch channels on state change (in PlayerComponent)publicvoidstartWalking() {
animTex.loopAnimationChannel(walkChannel);
}
publicvoidstopWalking() {
animTex.loopAnimationChannel(idleChannel);
}
publicvoidjump() {
// Play once then return to idle
animTex.playAnimationChannel(jumpChannel);
animTex.setOnCycleFinished(() -> animTex.loopAnimationChannel(idleChannel));
}
AnimationChannel Constructor Variants
// All frames in a single rownewAnimationChannel(texture, frameCount, frameW, frameH, duration, startFrame, endFrame)
// With looping control (false = play once then stop)newAnimationChannel(texture, frameCount, frameW, frameH, duration, startFrame, endFrame, loop)
// From a list of specific framesnewAnimationChannel(List.of(frame0, frame2, frame5), duration)
// From Image (not Texture)newAnimationChannel(image, frames, frameW, frameH, duration, start, end)
Delay Before Animation
animationBuilder()
.delay(Duration.seconds(0.5)) // wait 0.5s then start
.duration(Duration.seconds(1))
.fadeIn(entity)
.buildAndPlay();
Gotchas
buildAndPlay() vs build().start(): buildAndPlay() is fire-and-forget with no
handle. Use build() when you need to stop, pause, or set an onFinished callback.
Animations do not block the game loop — all animations run asynchronously on the
JavaFX animation timer. Use setOnFinished() to sequence code after an animation.
translateX/Y in from/to are absolute world coordinates, not offsets. To offset
from current position: .from(entity.getPosition()).to(entity.getPosition().add(100, 0)).
AnimatedTexture must be the entity's view — you cannot reuse the same AnimatedTexture
instance across multiple entities. Create a new one per entity.
loopAnimationChannel vs playAnimationChannel: loop plays forever; play fires
onCycleFinished once the animation ends once.
Sprite sheet orientation: FXGL reads frames left-to-right, top-to-bottom. Frame index 0
is top-left. Frame (col, row) = index row * numCols + col.
animationBuilder(scene) variant: pass a specific Scene when animating UI nodes
that live in a GameSubScene rather than the main GameScene.