Phaser 补间动画 #
补间概述 #
补间动画(Tween)是 Phaser 中实现平滑动画效果的核心工具,通过插值计算实现属性的变化。
text
┌─────────────────────────────────────────────────────────────┐
│ 补间动画流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 起始值 ──────────────────────────────────► 目标值 │
│ │
│ x: 0 ──────── 插值计算 ────────► x: 400 │
│ │
│ 时间轴: │
│ ├── delay: 延迟开始 │
│ ├── duration: 动画时长 │
│ ├── repeat: 重复次数 │
│ ├── yoyo: 往返播放 │
│ └── hold: 完成后保持 │
│ │
└─────────────────────────────────────────────────────────────┘
基本补间 #
创建补间 #
javascript
this.tweens.add({
targets: this.player,
x: 400,
duration: 1000
});
const tween = this.tweens.add({
targets: this.player,
x: 400,
y: 300,
alpha: 0.5,
scaleX: 2,
scaleY: 2,
angle: 360,
duration: 2000,
ease: 'Power2'
});
补间配置 #
javascript
this.tweens.add({
targets: this.player,
x: 400,
duration: 2000,
ease: 'Power2',
delay: 0,
repeat: 0,
repeatDelay: 0,
yoyo: false,
hold: 0,
paused: false,
props: {
x: { value: 400, duration: 1000, ease: 'Power2' },
y: { value: 300, duration: 2000, ease: 'Bounce.easeOut' }
}
});
缓动函数 #
内置缓动 #
javascript
this.tweens.add({
targets: this.player,
x: 400,
ease: 'Linear',
duration: 1000
});
this.tweens.add({
targets: this.player,
x: 400,
ease: 'Power0',
duration: 1000
});
this.tweens.add({
targets: this.player,
x: 400,
ease: 'Power1',
duration: 1000
});
this.tweens.add({
targets: this.player,
x: 400,
ease: 'Power2',
duration: 1000
});
this.tweens.add({
targets: this.player,
x: 400,
ease: 'Power3',
duration: 1000
});
this.tweens.add({
targets: this.player,
x: 400,
ease: 'Power4',
duration: 1000
});
this.tweens.add({
targets: this.player,
x: 400,
ease: 'Quad.easeIn',
duration: 1000
});
this.tweens.add({
targets: this.player,
x: 400,
ease: 'Quad.easeOut',
duration: 1000
});
this.tweens.add({
targets: this.player,
x: 400,
ease: 'Quad.easeInOut',
duration: 1000
});
this.tweens.add({
targets: this.player,
x: 400,
ease: 'Cubic.easeOut',
duration: 1000
});
this.tweens.add({
targets: this.player,
x: 400,
ease: 'Bounce.easeOut',
duration: 1000
});
this.tweens.add({
targets: this.player,
x: 400,
ease: 'Elastic.easeOut',
duration: 1000
});
this.tweens.add({
targets: this.player,
x: 400,
ease: 'Back.easeOut',
duration: 1000
});
this.tweens.add({
targets: this.player,
x: 400,
ease: 'Sine.easeInOut',
duration: 1000
});
this.tweens.add({
targets: this.player,
x: 400,
ease: 'Expo.easeOut',
duration: 1000
});
this.tweens.add({
targets: this.player,
x: 400,
ease: 'Circular.easeInOut',
duration: 1000
});
this.tweens.add({
targets: this.player,
x: 400,
ease: 'Stepped',
duration: 1000
});
自定义缓动 #
javascript
this.tweens.add({
targets: this.player,
x: 400,
ease: (t) => t * t,
duration: 1000
});
const customEase = (t) => {
return t < 0.5
? 4 * t * t * t
: 1 - Math.pow(-2 * t + 2, 3) / 2;
};
this.tweens.add({
targets: this.player,
x: 400,
ease: customEase,
duration: 1000
});
补间控制 #
播放控制 #
javascript
const tween = this.tweens.add({
targets: this.player,
x: 400,
duration: 2000
});
tween.pause();
tween.resume();
tween.stop();
tween.stop(0);
tween.stop(1);
tween.restart();
tween.complete();
tween.complete(1);
进度控制 #
javascript
const tween = this.tweens.add({
targets: this.player,
x: 400,
duration: 2000
});
tween.seek(0.5);
tween.setProgress(0.5);
const progress = tween.progress;
tween.setElapsed(1000);
const elapsed = tween.elapsed;
时间缩放 #
javascript
const tween = this.tweens.add({
targets: this.player,
x: 400,
duration: 2000
});
tween.setTimeScale(2);
const timeScale = tween.timeScale;
this.tweens.setTimeScale(0.5);
const globalTimeScale = this.tweens.timeScale;
补间属性 #
常用属性 #
javascript
this.tweens.add({
targets: this.player,
x: 400,
y: 300,
duration: 1000
});
this.tweens.add({
targets: this.player,
alpha: 0,
duration: 1000
});
this.tweens.add({
targets: this.player,
scaleX: 2,
scaleY: 2,
duration: 1000
});
this.tweens.add({
targets: this.player,
angle: 360,
duration: 1000
});
this.tweens.add({
targets: this.player,
rotation: Math.PI * 2,
duration: 1000
});
this.tweens.add({
targets: this.player,
tint: 0xff0000,
duration: 1000
});
this.tweens.add({
targets: this.player,
displayWidth: 100,
displayHeight: 100,
duration: 1000
});
相对值 #
javascript
this.tweens.add({
targets: this.player,
x: '+=100',
duration: 1000
});
this.tweens.add({
targets: this.player,
x: '-=50',
y: '+=100',
duration: 1000
});
this.tweens.add({
targets: this.player,
scaleX: '*=1.5',
scaleY: '*=1.5',
duration: 1000
});
自定义属性 #
javascript
const obj = { value: 0 };
this.tweens.add({
targets: obj,
value: 100,
duration: 1000,
onUpdate: () => {
console.log('Value:', obj.value);
}
});
this.tweens.add({
targets: this.player,
props: {
x: {
value: 400,
duration: 1000,
ease: 'Power2'
},
y: {
value: 300,
duration: 2000,
ease: 'Bounce.easeOut',
delay: 500
}
}
});
多目标补间 #
数组目标 #
javascript
this.tweens.add({
targets: [this.player, this.enemy, this.npc],
x: 400,
y: 300,
duration: 2000
});
const enemies = this.enemies.getChildren();
this.tweens.add({
targets: enemies,
alpha: 0,
duration: 1000
});
交错动画 #
javascript
const items = this.add.group();
for (let i = 0; i < 10; i++) {
items.create(100 + i * 60, 300, 'item');
}
this.tweens.add({
targets: items.getChildren(),
y: 200,
duration: 500,
delay: (target, key, value, index) => index * 100
});
this.tweens.add({
targets: items.getChildren(),
alpha: 0,
scale: 0,
duration: 300,
delay: this.tweens.stagger(100)
});
循环与重复 #
无限循环 #
javascript
this.tweens.add({
targets: this.player,
x: 400,
duration: 1000,
repeat: -1
});
有限重复 #
javascript
this.tweens.add({
targets: this.player,
x: 400,
duration: 1000,
repeat: 3
});
往返动画 #
javascript
this.tweens.add({
targets: this.player,
x: 400,
duration: 1000,
yoyo: true
});
this.tweens.add({
targets: this.player,
x: 400,
duration: 1000,
repeat: -1,
yoyo: true
});
重复延迟 #
javascript
this.tweens.add({
targets: this.player,
x: 400,
duration: 1000,
repeat: 3,
repeatDelay: 500
});
this.tweens.add({
targets: this.player,
x: 400,
duration: 1000,
repeat: -1,
yoyo: true,
hold: 500
});
补间事件 #
事件回调 #
javascript
this.tweens.add({
targets: this.player,
x: 400,
duration: 2000,
onStart: (tween, targets) => {
console.log('Tween started');
},
onUpdate: (tween, targets) => {
console.log('Progress:', tween.progress);
},
onComplete: (tween, targets) => {
console.log('Tween completed');
},
onRepeat: (tween, targets) => {
console.log('Tween repeated');
},
onYoyo: (tween, targets) => {
console.log('Tween yoyo');
},
onPause: (tween, targets) => {
console.log('Tween paused');
},
onResume: (tween, targets) => {
console.log('Tween resumed');
},
onLoop: (tween, targets) => {
console.log('Tween looped');
},
onActive: (tween, targets) => {
console.log('Tween active');
}
});
时间线 #
创建时间线 #
javascript
const timeline = this.tweens.createTimeline();
timeline.add({
targets: this.player,
x: 400,
duration: 1000
});
timeline.add({
targets: this.player,
y: 300,
duration: 1000
});
timeline.add({
targets: this.player,
alpha: 0,
duration: 500
});
timeline.play();
时间线配置 #
javascript
const timeline = this.tweens.timeline({
targets: this.player,
tweens: [
{
x: 400,
duration: 1000
},
{
y: 300,
duration: 1000
},
{
alpha: 0,
duration: 500
}
],
onComplete: () => {
console.log('Timeline complete');
}
});
并行补间 #
javascript
const timeline = this.tweens.timeline();
timeline.add({
targets: this.player,
x: 400,
duration: 1000
});
timeline.add({
targets: this.enemy,
x: 200,
duration: 1000,
offset: 0
});
timeline.play();
时间线控制 #
javascript
timeline.play();
timeline.pause();
timeline.resume();
timeline.stop();
timeline.restart();
timeline.seek(0.5);
const progress = timeline.progress;
补间管理 #
获取补间 #
javascript
const tweens = this.tweens.getAllTweens();
const tweens = this.tweens.getTweensOf(this.player);
const isTweening = this.tweens.isTweening(this.player);
全局控制 #
javascript
this.tweens.pauseAll();
this.tweens.resumeAll();
this.tweens.stopAll();
this.tweens.killTweensOf(this.player);
this.tweens.killAll();
实用动画 #
UI 动画 #
javascript
class UIAnimations {
static fadeIn(scene, target, duration = 500) {
target.setAlpha(0);
scene.tweens.add({
targets: target,
alpha: 1,
duration: duration,
ease: 'Linear'
});
}
static fadeOut(scene, target, duration = 500, destroy = false) {
scene.tweens.add({
targets: target,
alpha: 0,
duration: duration,
ease: 'Linear',
onComplete: () => {
if (destroy) target.destroy();
}
});
}
static slideIn(scene, target, from, duration = 500) {
const originalX = target.x;
const originalY = target.y;
if (from === 'left') target.x = -target.width;
if (from === 'right') target.x = scene.scale.width + target.width;
if (from === 'top') target.y = -target.height;
if (from === 'bottom') target.y = scene.scale.height + target.height;
scene.tweens.add({
targets: target,
x: originalX,
y: originalY,
duration: duration,
ease: 'Power2'
});
}
static popIn(scene, target, duration = 300) {
target.setScale(0);
scene.tweens.add({
targets: target,
scaleX: 1,
scaleY: 1,
duration: duration,
ease: 'Back.easeOut'
});
}
static shake(scene, target, intensity = 10, duration = 100) {
const originalX = target.x;
const originalY = target.y;
scene.tweens.add({
targets: target,
x: originalX + intensity,
y: originalY + intensity,
duration: duration,
yoyo: true,
repeat: 3,
ease: 'Linear',
onComplete: () => {
target.setPosition(originalX, originalY);
}
});
}
}
游戏动画 #
javascript
class GameAnimations {
static jump(scene, target, height = 100, duration = 500) {
const originalY = target.y;
scene.tweens.add({
targets: target,
y: originalY - height,
duration: duration / 2,
ease: 'Quad.easeOut',
yoyo: true,
ease: 'Quad.easeIn'
});
}
static collect(scene, target, destination, duration = 500) {
scene.tweens.add({
targets: target,
x: destination.x,
y: destination.y,
scaleX: 0,
scaleY: 0,
duration: duration,
ease: 'Power2',
onComplete: () => target.destroy()
});
}
static float(scene, target, distance = 10, duration = 1000) {
scene.tweens.add({
targets: target,
y: target.y - distance,
duration: duration,
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut'
});
}
static pulse(scene, target, minScale = 0.9, maxScale = 1.1, duration = 500) {
scene.tweens.add({
targets: target,
scaleX: maxScale,
scaleY: maxScale,
duration: duration,
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut'
});
}
static rotate(scene, target, duration = 2000) {
scene.tweens.add({
targets: target,
angle: 360,
duration: duration,
repeat: -1,
ease: 'Linear'
});
}
}
下一步 #
现在你已经掌握了补间动画,接下来学习 粒子系统,了解如何创建炫酷的粒子效果!
最后更新:2026-03-29