animations について
Phaser 4 の Sprite アニメーションを定義・制御するスキルリファレンスです。スプライトシートやアトラス、再生タイミング、イベントを扱うゲーム開発者向けです。
主な機能
- 01グローバルおよび Sprite ごとの定義
- 02スプライトシートとアトラスのフレーム生成
- 03再生、逆再生、一時停止、連結の制御
- 04アニメーションイベントとフレームコールバック
- 05JSON と Aseprite アニメーションのインポート
活用シーン
- 01キャラクターのループアニメーション作成
- 02攻撃、落下、着地アニメーションの連結
- 03特定フレームでゲームロジックを実行
- 04Aseprite のアニメーションタグを取り込み
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ phaserjs/ phaser --skill animationsインストール後、Claude Code で/animationsを入力して読み込まれたか確認します。
詳細
Phaser 4 -- スプライトアニメーション
AnimationManager(グローバル)、AnimationState(スプライトごと)、スプライトシートとアトラスからのアニメーション作成、再生/一時停止/チェーン、アニメーションイベント、フレームコールバック。
関連スキル: ../sprites-and-images/SKILL.md, ../loading-assets/SKILL.md
クイックスタート
// In preload -- load a spritesheet
this.load.spritesheet('explosion', 'explosion.png', {
frameWidth: 64,
frameHeight: 64
});
// In create -- define a global animation
this.anims.create({
key: 'explode',
frames: this.anims.generateFrameNumbers('explosion', { start: 0, end: 11 }),
frameRate: 24,
repeat: 0
});
// Play it on a sprite
const sprite = this.add.sprite(400, 300, 'explosion');
sprite.play('explode');
コアコンセプト
AnimationManager と AnimationState
Phaser には 2 つの異なるアニメーションオブジェクトがあります。
| 項目 | AnimationManager | AnimationState |
|---|---|---|
| アクセス | this.anims(Scene 内)または this.game.anims | sprite.anims |
| スコープ | グローバル -- すべての Scene で共有 | スプライトインスタンスごと |
| 目的 | アニメーション定義の作成と保存 | 1 つのゲームオブジェクト上の再生制御 |
| クラス | Phaser.Animations.AnimationManager | Phaser.Animations.AnimationState |
AnimationManager は Game が所有するシングルトンです。そこで登録されたアニメーションはすべての Scene で利用できます。AnimationState は各 Sprite 上に存在し、その特定のオブジェクトの再生を処理します。
Animation は AnimationFrame オブジェクトのシーケンスとタイミングデータです。this.anims.create(config)(グローバル)または sprite.anims.create(config)(1 つのスプライトに対してローカル)で作成します。
ローカルアニメーションとグローバルアニメーション
sprite.anims.play(key) が呼び出されると、まずそのキーを持つローカルアニメーションを確認し、次にグローバルの AnimationManager にフォールバックします。スプライト固有のアニメーションにはローカルを、スプライト間で共有する場合にはグローバルを使用します。
// Global animation -- available to all sprites
this.anims.create({ key: 'walk', frames: 'player_walk', frameRate: 12, repeat: -1 });
// Local animation -- only on this sprite
sprite.anims.create({ key: 'walk', frames: 'npc_walk', frameRate: 10, repeat: -1 });
// This plays the LOCAL version because local takes priority
sprite.play('walk');
一般的なパターン
スプライトシートアニメーション
スプライトシート(数値のフレームインデックス)には generateFrameNumbers を使用します。
this.load.spritesheet('dude', 'dude.png', { frameWidth: 32, frameHeight: 48 });
// All frames
this.anims.create({
key: 'run',
frames: this.anims.generateFrameNumbers('dude', { start: 0, end: 7 }),
frameRate: 10,
repeat: -1
});
// Custom frame sequence
this.anims.create({
key: 'idle',
frames: this.anims.generateFrameNumbers('dude', { frames: [0, 1, 2, 1] }),
frameRate: 6,
repeat: -1
});
generateFrameNumbers の設定:
start(デフォルト0)-- 最初のフレームインデックスend(デフォルト-1、つまり最後のフレーム)-- 最後のフレームインデックスfirst-- 範囲の前に追加する単一のフレームframes-- フレームインデックスの明示的な配列(start/end を上書き)
アトラスアニメーション
テクスチャアトラス(文字列ベースのフレーム名)には generateFrameNames を使用します。
this.load.atlas('gems', 'gems.png', 'gems.json');
this.anims.create({
key: 'ruby_sparkle',
frames: this.anims.generateFrameNames('gems', {
prefix: 'ruby_',
start: 1,
end: 6,
zeroPad: 4 // produces ruby_0001 through ruby_0006
}),
frameRate: 12,
repeat: -1
});
generateFrameNames の設定:
prefix-- 各フレーム番号の前に付加suffix-- 各フレーム番号の後に付加start、end-- 数値範囲zeroPad-- 数値をこの長さまでゼロで左詰めframes-- フレーム番号の明示的な配列(start/end を上書き)
設定なしで generateFrameNames(key) を呼び出すと、アトラスのすべてのフレームが返されます。
文字列をフレームとして使用
テクスチャキーの文字列を frames として渡すと、そのテクスチャのすべてのフレームをデフォルトで数値順に並べて使用します。並べ替えを無効にするには sortFrames: false を設定します。
this.anims.create({ key: 'walk', frames: 'player_walk', frameRate: 12, repeat: -1 });
ヨーヨーとリピート
this.anims.create({
key: 'pulse',
frames: this.anims.generateFrameNumbers('orb', { start: 0, end: 5 }),
frameRate: 10,
yoyo: true, // plays forward then backward
repeat: -1, // -1 = forever
repeatDelay: 500 // ms pause between each repeat cycle
});
yoyo が true の場合、アニメーションは順方向に再生された後に逆方向に再生されます。1 サイクル全体で 1 回の再生としてカウントされます。
アニメーションのチェーン
sprite.play('attack');
sprite.chain('idle'); // play idle after attack completes
sprite.chain(['fall', 'land', 'idle']); // chain multiple
sprite.anims.chain(); // clear the chain queue
チェーンはスプライトごとです。チェーンされたアニメーションは animationcomplete または animationstop の後に開始されます。repeat: -1 のアニメーションは決して完了しないため、チェーンをトリガーするには stop() を呼び出します。
逆再生
// Play an animation from last frame to first
sprite.playReverse('walk');
// Reverse direction mid-playback
sprite.anims.reverse();
playReverse は forward = false と inReverse = true を設定します。reverse() メソッドは再生中に方向を切り替えます。
再生のバリエーション
sprite.play('walk', true); // ignoreIfPlaying = true
sprite.anims.playAfterDelay('walk', 1000); // play after 1s delay
sprite.anims.playAfterRepeat('walk', 2); // play after current anim repeats 2x
アニメーションミックス
2 つの特定のアニメーション間の遷移遅延を追加し、AnimationManager にグローバルに設定します。
this.anims.addMix('idle', 'walk', 200);
this.anims.addMix('walk', 'idle', 300);
sprite.play('idle');
sprite.play('walk'); // 200ms mix delay applied automatically
this.anims.removeMix('idle', 'walk'); // remove specific pair
this.anims.removeMix('idle'); // remove all mixes for 'idle'
ミックス遅延は sprite.play() でのみ適用され、playAfterDelay や playAfterRepeat では適用されません。
一時停止、再開、停止
sprite.anims.pause(); // pause per-sprite
sprite.anims.resume(); // resume per-sprite
this.anims.pauseAll(); // global pause
this.anims.resumeAll(); // global resume
sprite.anims.stop(); // stop immediately
sprite.anims.stopAfterDelay(2000); // stop after 2 seconds
sprite.anims.stopAfterRepeat(1); // stop after 1 more repeat
sprite.anims.stopOnFrame(frame); // stop when a specific frame is reached
すべての停止メソッドは animationstop を発火します(animationcomplete ではありません)。チェーンされたアニメーションは停止後にトリガーされます。
アニメーションイベント
sprite.on('animationcomplete', (anim, frame, gameObject, frameKey) => {
console.log('completed:', anim.key);
});
// Key-specific complete -- only fires for the named animation
sprite.on('animationcomplete-explode', (anim, frame, gameObject, frameKey) => {
gameObject.destroy();
});
利用可能なイベント: animationstart、animationcomplete、animationcomplete-{key}、animationupdate、animationstop、animationrepeat、animationrestart。すべて同じコールバックシグネチャ (animation, frame, gameObject, frameKey) を共有します。
animationupdate によるフレームレベルのコールバック
sprite.on('animationupdate', (anim, frame, gameObject, frameKey) => {
if (anim.key === 'attack' && frame.index === 4) {
this.checkHit(gameObject);
}
});
フレームごとの再生時間
個々のフレームには、ベースの msPerFrame に加算される duration(ミリ秒)を設定できます。
this.anims.create({
key: 'combo',
frames: [
{ key: 'fighter', frame: 'punch1', duration: 50 },
{ key: 'fighter', frame: 'kick', duration: 200 }, // hold longer
{ key: 'fighter', frame: 'recover', duration: 100 }
],
frameRate: 24
});
可視性、ランダム開始、TimeScale
// Visibility control
this.anims.create({
key: 'appear', frames: 'sparkle', frameRate: 12,
showOnStart: true, // sprite.visible = true when anim starts (after delay)
hideOnComplete: true, // sprite.visible = false when anim completes
showBeforeDelay: true // show first frame immediately even during delay
});
// Random start frame -- each sprite begins on a different frame
this.anims.create({
key: 'ambient', frames: 'fire', frameRate: 10, repeat: -1,
randomFrame: true
});
// TimeScale -- per-sprite or global speed control
sprite.anims.timeScale = 2; // 2x speed
sprite.play({ key: 'walk', timeScale: 0.5 }); // half speed via config
this.anims.globalTimeScale = 0.5; // affects ALL animations
ずらした再生
const enemies = this.add.group({ key: 'enemy', repeat: 9 });
this.anims.staggerPlay('walk', enemies.getChildren(), 100);
// Each sprite starts 100ms after the previous. Pass staggerFirst: false to skip delay on first.
JSON のエクスポートとインポート
// Export all global animations to JSON
const data = this.anims.toJSON();
// Import animations from JSON (pass true to clear existing animations first)
this.anims.fromJSON(data);
this.anims.fromJSON(data, true);
// Check before creating to avoid duplicate warning
if (!this.anims.exists('walk')) {
this.anims.create({ key: 'walk', frames: 'player_walk', frameRate: 12, repeat: -1 });
}
実行時のアニメーションフレームの変更
const anim = this.anims.get('walk');
// Add frames to the end
anim.addFrame(this.anims.generateFrameNumbers('player', { start: 8, end: 10 }));
// Insert frames at a specific index
anim.addFrameAt(this.anims.generateFrameNumbers('player', { frames: [5] }), 2);
// Remove a specific frame object
const frame = anim.frames[3];
anim.removeFrame(frame);
// Remove frame at index
anim.removeFrameAt(0);
Aseprite サポート
this.load.aseprite('paladin', 'paladin.png', 'paladin.json');
// In create:
this.anims.createFromAseprite('paladin'); // all tags
this.anims.createFromAseprite('paladin', ['walk']); // specific tags only
sprite.play('walk'); // play by tag name
設定リファレンス
AnimationConfig (this.anims.create() で使用)
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
key | string | -- | アニメーションの一意の識別子 |
frames | string または AnimationFrame[] | [] | テクスチャキー文字列 (すべてのフレームを使用) またはフレーム設定オブジェクトの配列 |
sortFrames | boolean | true | 文字列キーを使用する場合にフレームを数値でソートする |
defaultTextureKey | string | null | フレームごとに設定されていない場合のフォールバックテクスチャキー |
frameRate | number | 24 | 1 秒あたりのフレーム単位の再生レート (duration が null の場合に使用) |
duration | number | null | アニメーションの合計長 (ミリ秒単位) (設定されている場合は frameRate を導出) |
skipMissedFrames | boolean | true | 遅延している場合にフレームをスキップする |
delay | number | 0 | 再生開始前の遅延 (ミリ秒) |
repeat | number | 0 | 最初の再生後に繰り返す回数 (-1 = 無限) |
repeatDelay | number | 0 | 各リピート前の遅延 (ミリ秒) |
yoyo | boolean | false | リピート前に逆再生して先頭に戻る |
showBeforeDelay | boolean | false | 遅延期間中に最初のフレームを即座に表示する |
showOnStart | boolean | false | アニメーション開始時に visible=true に設定する |
hideOnComplete | boolean | false | アニメーション完了時に visible=false に設定する |
randomFrame | boolean | false | ランダムなフレームから開始する |
PlayAnimationConfig (sprite.play() で使用)
すべての AnimationConfig のタイミングプロパティが利用可能です。さらに:
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
key | string または Animation | -- | 再生するアニメーションのキーまたはインスタンス |
startFrame | number | 0 | 再生を開始するフレームインデックス |
timeScale | number | 1 | この再生の速度倍率 |
PlayAnimationConfig の値は、この特定の再生インスタンスに対してアニメーション定義を上書きします。
Duration と FrameRate の優先順位
durationとframeRateの両方が null の場合: デフォルトで 24 fps になります。durationのみが設定されている場合: frameRate はtotalFrames / (duration / 1000)として計算されます。frameRateが設定されている場合 (duration も設定されている場合でも): frameRate が優先され、duration は(totalFrames / frameRate) * 1000として導出されます。
イベント
スプライトイベントの流れ
animationstart-- 遅延が経過した後、最初の更新の前animationupdate-- フレームが変わるたびanimationrepeat-- 各リピートサイクルanimationcomplete-- 自然な終了 (有限リピート)animationcomplete-{key}-- 同上、アニメーションキーが付加される
手動で停止した場合: complete の代わりに animationstop が発火します。再生中に再開した場合: animationrestart が発火します。
すべてのコールバック: (animation, frame, gameObject, frameKey)。
AnimationManager イベント
this.anims で発火します: addanimation、removeanimation、pauseall、resumeall。
API クイックリファレンス
AnimationManager (this.anims)
| メソッド | 説明 |
|---|---|
create(config) | グローバルアニメーションを作成して登録します |
remove(key) | キーを指定してグローバルアニメーションを削除します |
get(key) | キーを指定して Animation インスタンスを取得します |
exists(key) | キーがすでに登録されているかを確認します |
generateFrameNumbers(key, config) | スプライトシートからフレーム配列を生成します |
generateFrameNames(key, config) | アトラスからフレーム配列を生成します |
play(key, children) | Game Object の配列に対してアニメーションを再生します |
staggerPlay(key, children, stagger) | 複数の Game Object にわたって時間差で再生します |
pauseAll() / resumeAll() | すべてのアニメーションをグローバルに一時停止/再開します |
addMix(animA, animB, delay) | 2 つのアニメーション間の遷移遅延を設定します |
removeMix(animA, animB?) | ミックスのペアリングを削除します |
getMix(animA, animB) | 2 つのアニメーション間のミックス遅延を取得します |
createFromAseprite(key, tags?, target?) | Aseprite JSON からアニメーションを作成します |
toJSON() | すべてのアニメーションを JSON データとしてエクスポートします |
fromJSON(data, clear?) | JSON データからアニメーションを読み込みます(既存を先にクリアするには true を渡します) |
AnimationState (sprite.anims)
| メソッド | 説明 |
|---|---|
play(key, ignoreIfPlaying?) | アニメーションを再生します |
playReverse(key, ignoreIfPlaying?) | アニメーションを逆再生します |
playAfterDelay(key, delay) | ミリ秒単位の遅延後に再生します |
playAfterRepeat(key, repeatCount?) | 現在のアニメーションが N 回繰り返された後に再生します |
chain(key) | 現在のアニメーションの後に再生するアニメーションをキューに追加します |
stop() | 即座に停止します |
stopAfterDelay(delay) | ミリ秒単位の遅延後に停止します |
stopAfterRepeat(repeatCount?) | さらに N 回繰り返した後に停止します |
stopOnFrame(frame) | 特定のフレームに到達したときに停止します |
pause(atFrame?) | 再生を一時停止します |
resume(fromFrame?) | 再生を再開します |
restart(includeDelay?, resetRepeats?) | 最初から再開します |
reverse() | 再生中に方向を反転します |
getName() | 現在のアニメーションキーを取得します |
getFrameName() | 現在のフレームキーを取得します |
getProgress() | 進行状況を 0〜1 で取得します |
setProgress(value) | 進行状況を 0〜1 で設定します |
setRepeat(value) | 再生中に繰り返し回数を変更します |
getTotalFrames() | 総フレーム数を取得します |
create(config) | このスプライトにローカルアニメーションを作成します |
exists(key) | ローカルアニメーションが存在するかを確認します |
get(key) | キーを指定してローカルアニメーションを取得します |
主なプロパティ: isPlaying、hasStarted、currentAnim、currentFrame、forward、inReverse、timeScale。
注意点
- アニメーションはデフォルトでグローバルです。
this.anims.create()はすべての Scene にまたがって登録されます。各 Scene で再作成しないでください -- 警告がログに出力され、既存のものが返されます。 repeat: -1ではanimationcompleteが発生しません。 無限アニメーションを終了するにはstop()を使用します。代わりにanimationstopをリッスンしてください。frameRateはdurationより優先されます。 両方が設定されている場合、frameRate が優先されます。合計の長さを制御するにはdurationのみを設定してください(frameRate は null のままにします)。- フレームごとの
durationは加算されます。 基本の msPerFrame に上乗せされるものであり、置き換えるものではありません。 play()は現在のアニメーションを停止します(animationstopが発生します)。すでに再生中の場合はスキップするにはplay(key, true)を使用します。- ミックス遅延は
play()でのみ機能します。playAfterDelay/playAfterRepeatはミックスをバイパスします。 - ローカルアニメーションはグローバルより優先されます。 スプライトのローカルマップにある同じキーが優先されます。
- スプライトの省略メソッド。
sprite.play()、sprite.playReverse()、sprite.chain()、sprite.stop()はsprite.anims.*をラップしたものです。 - チェーンされたアニメーションは停止後にも発生します。 不要な場合は、停止する前に
sprite.anims.chain()でキューをクリアしてください。 generateFrameNumbersの end=-1 は最後のフレームを意味します。__BASEフレームは自動的に除外されます。
ソースファイルマップ
| ファイル | 目的 |
|---|---|
src/animations/AnimationManager.js | グローバルシングルトン -- create、remove、get、generateFrame*、mix、staggerPlay |
src/animations/Animation.js | アニメーション定義 -- フレーム、タイミング、yoyo、リピートロジック |
src/animations/AnimationState.js | スプライトごとのコンポーネント -- play、stop、pause、chain、イベント |
src/animations/AnimationFrame.js | 単一フレームのデータ -- textureKey、textureFrame、duration、progress |
src/animations/events/index.js | すべてのアニメーションイベント定数 |
src/animations/typedefs/Animation.js | AnimationConfig の typedef |
src/animations/typedefs/PlayAnimationConfig.js | PlayAnimationConfig の typedef |
src/animations/typedefs/GenerateFrameNumbers.js | generateFrameNumbers の設定 |
src/animations/typedefs/GenerateFrameNames.js | generateFrameNames の設定 |