用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/feliperyba/ralph-orchestra --skill dev-phaser-animations命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
基于 SOC 职业分类
| name | dev-phaser-animations |
| description | Sprite animations, tweens, animation chains, and timeline sequences |
"Bring your sprites to life with smooth animations and tweens."
// Manual sprite animation without Phaser
class SpriteAnimator {
private currentFrame = 0;
private frameTimer = 0;
private frameDuration = 83; // ~12 FPS
private isPlaying = false;
private frames: HTMLImageElement[] = [];
constructor(private sprite: HTMLElement) {
// Load all frames manually
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})`;
}
}
// Manual tween for position
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);
// Linear interpolation only - no easing options
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);
}
}
// Problems:
// - Manual frame timing is error-prone
// - No built-in easing functions
// - Manual sprite sheet management
// - No animation state management
// - Chained animations require nested callbacks
// - No timeline support
// Phaser handles all animation automatically
export class GameScene extends Phaser.Scene {
create() {
const player = this.add.sprite(400, 300, 'player');
// Create sprite sheet animation - ONE config!
this.anims.create({
key: 'walk',
frames: this.anims.generateFrameNumbers('player', {
start: 0,
end: 7
}),
frameRate: 12,
repeat: -1 // Infinite loop
});
// Play animation - ONE line!
player.play('walk');
// Tween with easing - ONE call!
this.tweens.add({
targets: player,
x: 600,
y: 400,
duration: 1000,
ease: 'Power2',
: {
.();
}
});
..({
: player,
: [
{ : , : , : },
{ : , : , : },
{ : , : , : }
]
});
}
}
Use when:
create() {
// Create animation from sprite sheet
this.anims.create({
key: 'walk',
frames: this.anims.generateFrameNumbers('player', { start: 0, end: 7 }),
frameRate: 12,
repeat: -1
});
// Play animation
const player = this.add.sprite(400, 300, 'player');
player.play('walk');
}
| 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() |
export class GameScene extends Phaser.Scene {
create() {
// Create animations from sprite sheet
this.anims.create({
key: "idle",
frames: this.anims.generateFrameNumbers("player", {
start: 0,
end: 3,
}),
frameRate: 8,
repeat: -1, // Infinite loop
yoyo: false, // Don't play backwards
});
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.(, );
}
}
create() {
const box = this.add.rectangle(400, 300, 50, 50, 0xff0000);
// Basic tween
this.tweens.add({
targets: box,
x: 600,
duration: 1000,
ease: 'Power2'
});
// Multiple properties
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!');
}
});
// Yoyo tween (ping-pong)
this.tweens.add({
targets: box,
y: 100,
duration: ,
: ,
: -
});
}
create() {
const sprite = this.add.sprite(400, 300, 'player');
// Chain tweens
this.tweens.add({
targets: sprite,
y: 200,
duration: 500,
ease: 'Linear',
onComplete: () => {
// Second tween
this.tweens.add({
targets: sprite,
x: 600,
duration: 500,
ease: 'Linear',
onComplete: () => {
// Third tween
this.tweens.add({
targets: sprite,
scale: 2,
duration: 300,
ease: 'Back.easeOut'
});
}
});
}
});
// Better approach: Timeline
const timeline = this.tweens.timeline({
: sprite,
: [
{
: ,
: ,
:
},
{
: ,
: ,
:
},
{
: ,
: ,
:
}
]
});
..({
: [
{
: sprite,
: ,
: ,
:
},
{
: otherSprite,
: ,
: ,
:
}
]
});
}
class AnimationController {
private sprite: Phaser.GameObjects.Sprite;
private currentAnim = '';
constructor(sprite: Phaser.GameObjects.Sprite) {
this.sprite = sprite;
// Listen for animation completion
this.sprite.on('animationcomplete', this.onAnimComplete, this);
}
play(animKey: string, ignoreIfPlaying = false) {
if (ignoreIfPlaying && this.currentAnim === animKey) {
return;
}
// Don't interrupt non-looping animations
const current = this.sprite.anims.currentAnim;
if (current && !current.repeat && current.isPlaying) {
return;
}
this.sprite.play(animKey);
this.currentAnim = animKey;
}
() {
(event. === ) {
.();
} (event. === ) {
..();
}
}
(: ): {
... && ...?. === animKey;
}
(): {
...();
}
}
() {
. = ..(, , );
. = (.);
..();
}
() {
(... || ...) {
..();
} {
..();
}
(.. && !..()) {
..();
}
}
export class GameScene extends Phaser.Scene {
private animManager!: AnimationManager;
create() {
this.animManager = new AnimationManager(this);
// Define animation states
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.);
}
}
}
}
❌ DON'T:
tweens.chain() for simple sequences - use timeline✅ DO:
// Check if animation is playing
if (sprite.anims.isPlaying) {
console.log("Playing:", sprite.anims.currentAnim?.key);
}
// Get animation progress (0-1)
const progress = sprite.anims.getProgress();
// Pause/resume animation
sprite.anims.pause();
sprite.anims.resume();
// Stop animation
sprite.anims.stop();
// Restart animation
sprite.anims.restart();
// Linear
this.tweens.add({ targets: obj, x: 100, ease: "Linear" });
// Power easing
this.tweens.add({ targets: obj, x: 100, ease: "Power0" }); // Linear
this.tweens.add({ targets: obj, x: 100, ease: "Power1" }); // Smooth
this.tweens.add({ targets: obj, x: 100, ease: "Power2" }); // Accelerating
this.tweens.add({ targets: obj, x: 100, ease: "Power3" }); // More accelerating
this.tweens.add({ targets: obj, x: 100, ease: "Power4" }); // Most accelerating
..({ : obj, : , : });
..({ : obj, : , : });
..({ : obj, : , : });
..({ : obj, : , : });
const tween = this.tweens.add({
targets: sprite,
alpha: 0,
duration: 1000,
});
// Pause tween
tween.pause();
// Resume tween
tween.resume();
// Stop tween
tween.stop();
// Complete tween immediately
tween.complete();
| 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 |