| name | dev-phaser-animations |
| description | Sprite animations, tweens, animation chains, and timeline sequences |
Phaser Animations
"Bring your sprites to life with smooth animations and tweens."
Before/After: Manual Animation vs Phaser Animation System
❌ Before: Manual Frame Animation
class SpriteAnimator {
private currentFrame = 0;
private frameTimer = 0;
private frameDuration = 83;
private isPlaying = false;
private frames: HTMLImageElement[] = [];
constructor(private sprite: HTMLElement) {
for (let i = 0; i < 8; i++) {
const img = document.createElement('img');
img.src = `assets/walk/frame${i}.png`;
this.frames.push(img);
}
}
play(animationName: string) {
this.isPlaying = true;
this.currentFrame = 0;
}
update(dt: number) {
if (!this.isPlaying) return;
this.frameTimer += dt;
if (this.frameTimer >= this.frameDuration) {
this.frameTimer = 0;
this.currentFrame = (this.currentFrame + 1) % this.frames.length;
this.sprite.style.backgroundImage = `url(${this.frames[this.currentFrame].src})`;
}
}
moveTo(targetX: number, targetY: number, duration: number) {
const startX = parseFloat(this.sprite.style.left) || 0;
const startY = parseFloat(this.sprite.style.top) || 0;
const startTime = performance.now();
const animate = (currentTime: number) => {
const elapsed = currentTime - startTime;
const progress = Math.min(elapsed / duration, 1);
this.sprite.style.left = (startX + (targetX - startX) * progress) + 'px';
this.sprite.style.top = (startY + (targetY - startY) * progress) + 'px';
if (progress < 1) {
requestAnimationFrame(animate);
}
};
requestAnimationFrame(animate);
}
}
✅ After: Phaser Animation System
export class GameScene extends Phaser.Scene {
create() {
const player = this.add.sprite(400, 300, 'player');
this.anims.create({
key: 'walk',
frames: this.anims.generateFrameNumbers('player', {
start: 0,
end: 7
}),
frameRate: 12,
repeat: -1
});
player.play('walk');
this.tweens.add({
targets: player,
x: 600,
y: 400,
duration: 1000,
ease: 'Power2',
: {
.();
}
});
..({
: player,
: [
{ : , : , : },
{ : , : , : },
{ : , : , : }
]
});
}
}
When to Use This Skill
Use when:
- Creating sprite animations
- Building tween sequences
- Implementing timeline-based animations
- Animating UI elements
- Creating visual effects and transitions
Quick Start
create() {
this.anims.create({
key: 'walk',
frames: this.anims.generateFrameNumbers('player', { start: 0, end: 7 }),
frameRate: 12,
repeat: -1
});
const player = this.add.sprite(400, 300, 'player');
player.play('walk');
}
Decision Framework
| Need | Use |
|---|
| Frame-based animation | anims.create() + sprite.play() |
| Property animation | tweens.add() |
| Sequenced animations | timeline |
| Single tween | tweens.add() once |
| Delayed action | time.delayedCall() |
Progressive Guide
Level 1: Sprite Animations
export class GameScene extends Phaser.Scene {
create() {
this.anims.create({
key: "idle",
frames: this.anims.generateFrameNumbers("player", {
start: 0,
end: 3,
}),
frameRate: 8,
repeat: -1,
yoyo: false,
});
this.anims.create({
key: "walk",
frames: this.anims.generateFrameNumbers("player", {
start: 4,
end: 11,
}),
frameRate: 12,
repeat: -1,
});
this.anims.create({
key: ,
: ..(, {
: ,
: ,
}),
: ,
: ,
});
player = ..(, , );
player.();
player.(, );
}
}
Level 2: Tweening Properties
create() {
const box = this.add.rectangle(400, 300, 50, 50, 0xff0000);
this.tweens.add({
targets: box,
x: 600,
duration: 1000,
ease: 'Power2'
});
this.tweens.add({
targets: box,
x: 200,
y: 400,
alpha: 0.5,
angle: 180,
scale: 2,
duration: 2000,
ease: 'Elastic.easeOut',
onComplete: () => {
console.log('Tween complete!');
}
});
this.tweens.add({
targets: box,
y: 100,
duration: ,
: ,
: -
});
}
Level 3: Tween Chains and Callbacks
create() {
const sprite = this.add.sprite(400, 300, 'player');
this.tweens.add({
targets: sprite,
y: 200,
duration: 500,
ease: 'Linear',
onComplete: () => {
this.tweens.add({
targets: sprite,
x: 600,
duration: 500,
ease: 'Linear',
onComplete: () => {
this.tweens.add({
targets: sprite,
scale: 2,
duration: 300,
ease: 'Back.easeOut'
});
}
});
}
});
const timeline = this.tweens.timeline({
: sprite,
: [
{
: ,
: ,
:
},
{
: ,
: ,
:
},
{
: ,
: ,
:
}
]
});
..({
: [
{
: sprite,
: ,
: ,
:
},
{
: otherSprite,
: ,
: ,
:
}
]
});
}
Level 4: Animation State Management
class AnimationController {
private sprite: Phaser.GameObjects.Sprite;
private currentAnim = '';
constructor(sprite: Phaser.GameObjects.Sprite) {
this.sprite = sprite;
this.sprite.on('animationcomplete', this.onAnimComplete, this);
}
play(animKey: string, ignoreIfPlaying = false) {
if (ignoreIfPlaying && this.currentAnim === animKey) {
return;
}
const current = this.sprite.anims.currentAnim;
if (current && !current.repeat && current.isPlaying) {
return;
}
this.sprite.play(animKey);
this.currentAnim = animKey;
}
() {
(event. === ) {
.();
} (event. === ) {
..();
}
}
(: ): {
... && ...?. === animKey;
}
(): {
...();
}
}
() {
. = ..(, , );
. = (.);
..();
}
() {
(... || ...) {
..();
} {
..();
}
(.. && !..()) {
..();
}
}
Level 5: Advanced Animation Systems
export class GameScene extends Phaser.Scene {
private animManager!: AnimationManager;
create() {
this.animManager = new AnimationManager(this);
this.animManager.registerState("player", "idle", {
frames: { start: 0, end: 3 },
frameRate: 8,
loop: true,
});
this.animManager.registerState("player", "walk", {
frames: { start: 4, end: 11 },
frameRate: 12,
loop: true,
});
this.animManager.registerState("player", "jump", {
frames: { start: 12, end: 15 },
: ,
: ,
: ,
});
..(, , {
: { : , : },
: ,
: ,
: ,
: .,
});
..(, , ,
.(),
);
..(
,
,
,
!.(),
);
..(, , ,
.(),
);
. = ..(, , );
..(, .);
}
() {
..();
}
() {
... || ...;
}
() {
...(.);
}
() {
.();
}
}
{
states = <, <, >>();
sprites = <, ..>();
: <{
: ;
: ;
: ;
: ;
}> = [];
() {}
() {
(!..(sprite)) {
..(sprite, ());
}
stateConfig = {
...config,
: ,
};
...({
: stateConfig.,
: ...(sprite, config.),
: config.,
: config. ? - : ,
: config. || ,
});
..(sprite)!.(key, stateConfig);
}
() {
..(spriteKey, sprite);
sprite.();
}
() {
..({ sprite, , to, condition });
}
() {
sprite = ..(spriteKey);
(!sprite) ;
currentAnim = sprite..?..(
,
,
);
states = ..(spriteKey);
( transition .) {
(
transition. === spriteKey &&
transition. === currentAnim &&
transition.()
) {
.(spriteKey, transition.);
;
}
}
}
() {
sprite = ..(spriteKey);
state = ..(spriteKey)?.(stateKey);
(sprite && state) {
sprite.(state.);
(state.) {
sprite.( + state., state.);
}
}
}
}
Anti-Patterns
❌ DON'T:
- Create animations in update() - do it once in create()
- Override playing animation without checking
- Use tweens for simple value changes
- Forget to clean up event listeners
- Use
tweens.chain() for simple sequences - use timeline
- Ignore animation repeat/yoyo properties
✅ DO:
- Create animations once in create()
- Check current animation before changing
- Use tweens for property animation
- Clean up listeners on shutdown
- Use timeline for sequences
- Configure repeat and yoyo appropriately
Code Patterns
Animation Playback Control
if (sprite.anims.isPlaying) {
console.log("Playing:", sprite.anims.currentAnim?.key);
}
const progress = sprite.anims.getProgress();
sprite.anims.pause();
sprite.anims.resume();
sprite.anims.stop();
sprite.anims.restart();
Tween Easing Functions
this.tweens.add({ targets: obj, x: 100, ease: "Linear" });
this.tweens.add({ targets: obj, x: 100, ease: "Power0" });
this.tweens.add({ targets: obj, x: 100, ease: "Power1" });
this.tweens.add({ targets: obj, x: 100, ease: "Power2" });
this.tweens.add({ targets: obj, x: 100, ease: "Power3" });
this.tweens.add({ targets: obj, x: 100, ease: "Power4" });
..({ : obj, : , : });
..({ : obj, : , : });
..({ : obj, : , : });
..({ : obj, : , : });
Tween Controls
const tween = this.tweens.add({
targets: sprite,
alpha: 0,
duration: 1000,
});
tween.pause();
tween.resume();
tween.stop();
tween.complete();
Common Easing Functions
| Ease | Description |
|---|
Linear | Constant speed |
Power0 | Same as Linear |
Power1 | Gentle ease |
Power2 | Medium ease |
Power3 | Strong ease |
Power4 | Strongest ease |
Elastic | Bouncy effect |
Bounce | Bounce at end |
Back | Overshoot slightly |
Sine | Smooth sine curve |
Checklist
Reference