Phaser系列课程初步分成《基础篇上》、《基础篇下》、《动画篇》、《交互篇》、《物理引擎篇》、《图形绘制篇》、《场景篇》。

了解如何创建不同物体和认识物体的常用属性之后,我们在前面知识的基础上对物体添加动画。物体的动画分成两大类:Tween和Animation。

Tween补间动画

通过改变物体的属性创建的动画。

1
var tween = game.add.tween(target);

重要属性

属性 类型 默认值 说明
onStart Phaser.Signal 监听动画开始时
onLoop Phaser.Signal 监听动画含括子动画循环时
onRepeat Phaser.Signal 监听动画含括子动画重复时
onComplete Phaser.Signal 监听动画含括子动画结束时
repeatCounter Number 0 动画重复次数,-1代表无限循环
reverse Boolean false 是否反向
timeScale Number 1 动画速率缩放倍数,0.5代表原来速率的一半,耗时加倍
totalDuration Phaser.TweenData 单程动画的时间

例如,监听动画开始时(如果设置了延时,会等延时完成再回调):

1
2
3
tween.onStart.add(function(){
console.log('动画开始时')
})

重要方法

from(properties, duration, ease, autoStart, delay, repeat, yoyo) 从某个状态去到当前状态

to(properties, duration, ease, autoStart, delay, repeat, yoyo) 从当前状态去到某个状态

属性 类型 是否必选 默认值 说明
properties object 想要改变的动画属性
duration number 1000 动画播放时长
ease function或string null 缓动函数
autoStart boolean false 是否自动播放
delay number 0 延时毫秒数
repeat number 0 动画重复次数,-1无限循环
yoyo boolean false 是否反向

start() 播放动画

pause() 暂停动画

stop(complete) 结束动画

参数 类型 是否必选 默认值 说明
complete boolean false 设置true触发Tween.onComplete signal

resume() 继续播动画

loop(value) 循环动画

参数 类型 是否必选 默认值 说明
value boolean true 是否循环

repeat(total, duration) 重复动画

参数 类型 是否必选 默认值 说明
total number 动画重复次数
duration number 0 动画每次重复之间的时间间隔

delay(duration) 动画延迟播放毫秒数

easing(easing) 动画缓动函数,如线性easing(Phaser.Easing.Linear.None)

chain(tweens) 动画链,该动画播完后播另外的动画tweens,多个用英文逗号隔开

Animation帧动画

该内容属于Phaser中相对比较复杂的部分,写法丰富多样,根据不用的使用场景有不一样的写法,为遇到的首个需要重点克服的内容。

我们用艾斯的行走和跳跃动作作为案例。素材下载

当我们的Sprite图每个动作的每个帧宽高都一样时,我们可以用最简单的方法来实现

例如,我要给艾斯添加一个行走的序列帧动画。

先在preload中先加载资源

1
game.load.spritesheet('sprite_animation', 'img/sprite_animation.png', 94, 166);

然后在create中创建人物,并设置中心点为正中

1
2
hero = game.add.sprite(game.world.centerX, game.height - 166, 'sprite_animation', 0);
hero.anchor.set(0.5);

最后在create中添加动作,并播放

1
2
hero.animations.add('walk');
hero.play('walk', 10, true);

解析:物体帧动画相关的设置都在animations属性下,每个动作都先add个名字,然后执行动作的方法play,这两个重要方法的参数如下:

add(name, frames, frameRate, loop, useNumericIndex)

参数 类型 是否必选 默认值 说明
name string 动作名
frames Array null 关键帧集合
frameRate number 60 帧率
loop boolean false 是否循环
useNumericIndex boolean true 关键帧使用数字索引还是字符窜

我们可以自定义序列帧frames,来决定一个动作由哪几个帧形成,帧也会按照数组顺序进行播放。

1
2
hero.animations.add('walk', [0,1,2,3]);
hero.animations.add('jump', [4,5,6,7]);

play(name, frameRate, loop, killOnComplete)

参数 类型 是否必选 默认值 说明
name string 动作名
frameRate number null 帧播放速率
loop boolean false 是否循环
killOnComplete boolean false 仅在动作不循环的前提下,完成后是否销毁物体

当我们的Sprite图每个动作之间的帧宽度不一样,需要用到TexturePacker导出的json文件

例如Sprite图包含walk和jump两个动作,两个动作的帧宽高是不一样的,但合并在一张图中,我们在导图时需要对walk和jump两个动作进行分组,并勾选关键帧名字去掉后缀名,以方便读帧。

此时,我们已经无法继续使用game.load.spritesheet,因为帧的宽高发生了变化,传固定宽高肯定是有问题的,我们需要换成一下写法:

1
game.load.atlasJSONHash('sprite_animation', 'img/sprite_animation2.png', 'img/sprite_animation2.json');
1
2
hero = game.add.sprite(game.world.centerX, game.world.centerY+500, 'sprite_animation', 'walk/01');
hero.anchor.set(0.5);

以下依然不改的情况下,动作会把Sprite图所有帧都依次读取完

1
2
hero.animations.add('walk');
hero.play('walk', 10, true);

而我们要把walk和jump两个动作分开,可以这么做:

1
2
hero.animations.add('walk', ['walk/01', 'walk/02', 'walk/03', 'walk/04', 'walk/05', 'walk/06', 'walk/07', 'walk/08']);
hero.animations.add('jump', ['jump/01', 'jump/02', 'jump/03', 'jump/04', 'jump/05', 'jump/06', 'jump/07', 'jump/08']);

但是,这样每个帧都列出来会非常不方便,Phaser.Animation提供了生成帧序列的简便方法。

generateFrameNames(prefix, start, stop, suffix, zeroPad)

参数 类型 是否必选 默认值 说明
prefix string 关键帧名的英文前缀部分,如walk/01,prefix就是walk/
start number 动作开始帧,如果关键帧是walk/01到walk/10,start就是1
stop number 动作结束帧,如果关键帧是walk/01到walk/10,stop就是10
suffix string ‘’ 关键帧后缀,如果关键帧是walk/01.png到walk/10.png,suffix就是.png
zeroPad number 视序列位数而定 ‘’ 关键帧序列的计数位数,如walk/01到walk/10,zeroPad就是2

那么,walk和jump的动作可以这么写:

1
2
hero.animations.add('walk', Phaser.Animation.generateFrameNames('walk/', 1, 8, '', 2));
hero.animations.add('jump', Phaser.Animation.generateFrameNames('jump/', 1, 8, '', 2));

以动作为主体的代码写法

另外,我们通常也需要对动作进行一些设置或监听,我们可以把以物体为主体的代码换成以动作为主体的方式来写:

1
2
var walk = hero.animations.add('walk', Phaser.Animation.generateFrameNames('walk/', 1, 8, '', 2));
walk.play(10, true);

重要属性

参数 类型 说明
currentFrame string 获取动作当前帧名
frame number 获取或设置动作此刻的帧
delay number 动作延迟播放的毫秒数
isPlaying boolean 是否在播放
isFinished boolean 是否已完成
paused boolean 获取或设置动作暂停状态
reversed boolean 动作反向
speed number 动作速度
onStart Phaser.Signal 监听动作开始时
onLoop Phaser.Signal 监听动作循环时
onComplete Phaser.Signal 监听动作完成时
onUpdate Phaser.Signal 监听动作在更新帧时

重要方法

  • play(frameRate, loop, killOnComplete) 播放动作

  • stop(resetFrame, dispatchComplete) 停止动作

参数 类型 是否必选 默认值 说明
resetFrame boolean false 是否重制到第一帧
dispatchComplete boolean false 是否传递一个动作完成的信号
  • complete() 强制传递动作完成信号

  • destroy() 销毁动作

  • restart() 重新播放动作

  • reverse() 方向播动画

  • onResume(fn) 监听动作从暂停恢复播放

Homework

在上一节课作业的基础(动作素材):

1、给box添加一个简单的tween动画;

2、使用TexturePacker合并艾斯的walk和jump动作的帧;

3、创建艾斯,给它添加walk动作和jump动作,并播放walk动作。