Table of Contents
这里记录的是 Phaser3.50 示例中的 Animation 部分 api 的用法。详情还是看 Phaser api 文档比较好。
Animation
60 fps Animation Test
class FpsAnimationTest extends Phaser.Scene {
constructor() {
super()
}
preload() {
this.load.baseURL = globalConfig.baseUrl
this.load.atlas('walker', 'assets/animations/walker.png', 'assets/animations/walker.json')
this.load.image('sky', 'assets/skies/ms3-sky.png')
this.load.image('trees', 'assets/skies/ms3-trees.png')
}
create() {
this.bg = this.add.tileSprite(0, 38, 800, 296, 'sky')
.setOrigin(0, 0)
this.trees = this.add.tileSprite(0, 280, 800, 320, 'trees')
.setOrigin(0, 0)
const animConfig = {
key: 'walk',
frames: 'walker',
frameRate: 60,
repeat: -1
}
this.anims.create(animConfig)
const sprite = this.add.sprite(400, 484, 'walker', 'frame_0000')
sprite.play('walk')
}
update() {
this.bg.tilePositionX -= 2
this.trees.tilePositionX -= 6
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#304858',
parent: 'demo',
scene: [FpsAnimationTest]
}
const game = new Phaser.Game(config)
this.add.tileSprite(x, y, width, height, texture [, frame])
创建瓦片精灵游戏对象(TileSprite Game Object)并添加到场景。宽高如果设置为 0,会默认使用纹理帧自身宽高。TileSprite 是可以移动的。移动后的空缺会自动平铺填充。比如 update 里设置 tilePositionX ,TileSprite 对象内部会对精灵图进行偏移,空缺部分会自动填充。TileSprite 可以用来制作动态背景。
this.anims.create(config)
创建动画并添加到动画管理器。动画是全局的,不属于具体的场景。每个场景都可以调用。
| 配置项 | 说明 |
|---|---|
| key | 动画的名称。 |
| frames | 动画帧数据来源。 |
| frameRate | 动画帧率。如果没有指定持续时间(duration)则默认 24。 |
| duration | 动画持续时间。毫秒。默认根据帧率计算。 |
| repeat | 重复次数。-1 无限制。默认 0 |
sprite.play(key [, ignoreIfPlaying] [, startFrame])
播放指定动画。
| 参数 | 说明 |
|---|---|
| key | 动画名称。 |
| ignoreIfPlaying | 如果动画已经播放,忽略这次调用。默认 false |
| startFrame | 开始帧。默认 0 |
Add Animation Event
class AddAnimationEvent extends Phaser.Scene {
constructor() {
super()
}
preload() {
this.load.baseURL = globalConfig.baseUrl
this.load.atlas('gems', 'assets/tests/columns/gems.png', 'assets/tests/columns/gems.json')
this.y = 160
}
create() {
this.add.text(400, 32, '点击创建动画', { color: '#00ff00' })
.setOrigin(0.5, 0)
// 每当往动画管理器里添加一个动画的时候都会调用下面的函数
this.anims.on(Phaser.Animations.Events.ADD_ANIMATION, this.addAnimation, this)
this.i = 0
this.input.on('pointerup', function() {
switch(this.i) {
case 0:
this.anims.create({
key: 'diamond',
frames: this.anims.generateFrameNames(
'gems',
{
prefix: 'diamond_',
end: 15,
zeroPad: 4
}
),
repeat: -1
})
break
case 1:
this.anims.create({
key: 'prism',
frames: this.anims.generateFrameNames(
'gems',
{
prefix: 'prism_',
end: 6,
zeroPad: 4
}
),
repeat: -1
})
break
case 2:
this.anims.create({
key: 'ruby',
frames: this.anims.generateFrameNames(
'gems',
{
prefix: 'ruby_',
end: 6,
zeroPad: 4
}
),
repeat: -1
})
break
case 3:
this.anims.create({
key: 'square',
frames: this.anims.generateFrameNames(
'gems',
{
prefix: 'square_',
end: 14,
zeroPad: 4
}
),
repeat: -1
})
break
}
this.i++
}, this)
}
addAnimation(key) {
this.add.sprite(400, this.y, 'gems')
.play(key)
this.y += 100
}
}
this.anims.on(event, fn [, context])
添加动画事件。可用事件在 Phaser.Animations.Events 部分。
this.anims.generateFrameNames(key [, config])
根据纹理键名和配置对象生成动画帧对象。config 部分配置项如下:
| 配置项 | 说明 |
|---|---|
| prefix | 名称前缀 |
| end | 最后帧数字 |
| zeroPad | 帧数字长度。不足的左侧补零 |
比如有名为 gems 的纹理集包含 ruby_0001, ruby_0002 等帧,可以通过 this.anims.generateFrameNames(‘gems’, { prefix: ‘ruby_’, end: 6, zeroPad: 4 }) 来生产配置。
Add Frames To Existing Animation
class AddFramesToExistingAnimation extends Phaser.Scene {
constructor() {
super()
}
preload() {
this.load.baseURL = globalConfig.baseUrl
this.load.atlas('gems', 'assets/tests/columns/gems.png', 'assets/tests/columns/gems.json')
this.y = 160
}
create() {
this.add.text(400, 32, '点击添加动画帧', { color: '#00ff00' })
.setOrigin(0.5, 0)
this.anims.create({
key: 'diamond',
frames: this.anims.generateFrameNames(
'gems',
{
prefix: 'diamond_',
end: 15,
zeroPad: 4
}
),
repeat: -1
})
const group = this.add.group({
key: 'gems',
frame: 'diamond_0000',
frameQuantity: 6 * 6
})
Phaser.Actions.GridAlign(
group.getChildren(),
{
width: 6,
height: 6,
cellWidth: 64,
cellHeight: 64,
x: 240,
y: 160
}
)
group.playAnimation('diamond')
this.input.once('pointerup', function() {
const diamond = this.anims.get('diamond')
// 添加新的动画帧到当前动画
const newFrames = this.anims.generateFrameNames(
'gems',
{
prefix: 'square_',
end: 14,
zeroPad: 4
}
)
diamond.addFrame(newFrames)
}, this)
}
}
group.playAnimation(key [, startFrame])
每一个游戏对象都(按照指定帧数)播放指定的动画。
this.input.once(event, fn [, context])
一次事件监听。
this.anims.get(key)
返回指定动画。
diamond.addFrame(config)
根据帧配置对象数组追加动画帧。
AnimationProgress
class AnimationProgress extends Phaser.Scene {
constructor() {
super()
}
preload() {
this.load.baseURL = globalConfig.baseUrl
this.load.atlas('gems', 'assets/animations/diamond.png', 'assets/animations/diamond.json')
}
create() {
this.anims.create({
key: 'diamond',
frames: this.anims.generateFrameNames(
'gems',
{
prefix: 'diamond_',
end: 15,
zeroPad: 4
}
),
frameRate: 16,
yoyo: true,
repeat: -1,
repeatDelay: 300
})
this.gem = this.add.sprite(400, 480, 'gems')
.play('diamond')
.setScale(4)
this.debug = this.add.graphics()
}
update() {
this.debug.clear()
const size = 672
this.debug.fillStyle(0x2d2d2d)
this.debug.fillRect(64, 64, size, 48)
this.debug.fillStyle(0x2dff2d)
this.debug.fillRect(64, 64, size * this.gem.anims.getProgress(), 48)
}
}
this.debug.fillRect(x, y, width, height)
this.gem.anims.getProgress()
this.gem 是精灵游戏对象,.anims 是该对象的动画控制器,.getProgress() 可以获取动画进度(0 ~ 1)。该方法不考虑 repeat 非零和 yoyo 为 true 的情况。如果 repeat 非零,想获取全局进度,需要使用 getTotalProgress() 方法。
Aesprite Animation
const config = {
type: Phaser.AUTO,
parent: 'demo',
width: 800,
height: 600,
pixelArt: true,
scene: {
preload,
create
}
}
const game = new Phaser.Game(config)
function preload() {
this.load.baseURL = globalConfig.baseUrl + 'assets/animations/aseprite/'
this.load.aseprite('paladin', 'paladin.png', 'paladin.json')
}
function create() {
const tags = this.anims.createFromAseprite('paladin')
const sprite = this.add.sprite(500, 300).play({
key: 'Magnum Break',
repeat: -1
}).setScale(6)
for (let i = 0; i < tags.length; i++) {
const label = this.add.text(32, 32 + i * 16, tags[i].key, { color: '#00ff00' })
label.setInteractive()
}
this.input.on('gameobjectdown', function(pointer, obj) {
console.log(obj)
sprite.play({
key: obj.text,
repeat: -1
})
})
this.input.on('gameobjectover', function(pointer, obj) {
obj.setColor('#ff00ff')
})
this.input.on('gameobjectout', function(pointer, obj) {
obj.setColor('#00ff00')
})
}
3.24 文档里暂无关于 aseprite 的 api。可能要等 3.25 的文档。
游戏配置项里的 pixelArt
控制缩放模糊算法。如果为 true,则为线性过滤模式,图片放大会表现出锐利的像素风。否则会模糊。
label.setInteractive([shape] [, callback] [, dropZone])
将此游戏对象添加到 Input 管理器中,并支持相关事件。如果不传参数,默认事件区域为游戏对象的矩形包围框。如果是图形对象(Graphics)或者位图文字对象(BitmapText),必须提供 shape 参数和 callback 参数。
| 参数 | 说明 |
|---|---|
| shape | 响应事件的区域。默认矩形。 |
| callback | 事件回调。如果提供了 shape 参数,此参数也许提供。 |
| dropZone | 是否作为 drop 目标。默认 false。 |
Chained Animation
lancelot.anims.getName()
3.24 文档暂无。获取当前动画名称。
lancelot.playAfterRepeat(key [, repeatCount])
3.50 新增的方法。完成指定次数的当前动画后开始指定的动画。如果当前没有动画,立即开始指定的动画。
| 参数 | 说明 |
|---|---|
| key | 指定的动画。 |
| repeatCount | 当前动画重复次数。默认 1. |
lancelot.chain([key])
当前动画完成后开始指定的系列动画。
Create Animation From Canvas
this.textures.createCanvas(key [, width] [, height])
使用空白 canvas 创建纹理。宽高默认 256。
canvasFrame.add(name, sourceIndex, x, y, width, height)
给纹理(Phaser.Textures.Texture)加帧。
| 参数 | 说明 |
|---|---|
| key | 帧名称 |
| sourceIndex | 属于纹理中的哪一个纹理资源(TextureSource) |
| x | 帧的横坐标 |
| y | 帧的纵坐标 |
| width | 帧宽 |
| height | 帧高 |
Create Animation From Sprite Sheet
this.add.grid([x] [, y] [, width] [, height] [, cellWidth] [, cellHeight] [, fillColor] [, fillAlpha] [, outlineFillColor] [, outlineFillAlpha])
创建网格对象。
| 参数 | 说明 |
|---|---|
| x | 左上角横坐标。默认 0 |
| y | 左上角纵坐标.默认 0 |
| width | 网格宽度。默认 128 |
| height | 网格高度。默认 128 |
| cellWidth | 网格单元宽度。默认 32 |
| cellHeight | 网格单元高度。默认 32 |
| fillColor | 网格单元填充颜色。可选 |
| fillAlpha | 网格单元填充透明度。可选 |
| outlineFillColor | 网格单元之间线条颜色。可选 |
| outlineFillAlpha | 网格单元之间线条颜色透明度。可选 |
Animation Create Animation On Sprite
Phaser.GameObjects.Sprite.anims.create()
直接在精灵对象上创建动画,此时创建的动画只属于这个精灵,不能全局调用。
Animation Cubes
Phaser.GameObjects.Group.children
群组的 children 属性是一个 Phaser.Structs.Set 类。该类有 iterate、each 等遍历方法。entries 属性为游戏对象合集。size 表示游戏对象数量。详情见 Phaser.Structs.Set 部分
this.anims.staggerPlay(key, children [, stagger])
对拥有动画组件的游戏对象适应给定的动画。每个动画按照 stagger 进行延迟播放。
| 参数 | 说明 |
|---|---|
| key | 动画名称 |
| children | 游戏对象数组 |
Animation Export
获取动画的 json 字符串。
// 获取某个动画的 json 字符串 console.log(JSON.stringify(this.anims.get(key))) // 这个返回的是一个对象 console.log(this.anims.get(key).toJSON()) // json 字符串 console.log(JSON.stringify(this.anims.toJSON(key))) // 所有动画的 json 字符串 console.log(JSON.stringify(this.anims))
From Animation JSON
this.load.animation(key [, url] [, dataKey] [, xhrSettings])
添加动画配置 json 文件到当前加载队列。文件加载完成后会自动传给全局动画管理器的 fromJSON 方法。这个过程会在所有文件加载完毕后发生。
Mixed Animation
this.anims.addMix(animA, animB, delay)
从动画 animA 到动画 animB 时延迟 delay 毫秒。
Multi Atalas Animation
this.load.multiatlas(key [, atlasURL] [, path] [, baseURL] [, atlasXhrSettings])
加载多个纹理图集。纹理图集的图片地址在图集 json 文件中指定。path 是加载指定图片时的路径。
Pause All Animations
Phaser.GameObjects.Sprite.setDepth(value)
设置层级。也就是 z-index。
Phaser.GameObjects.Sprite.playAfterDelay(config, delay)
延迟指定时间后播放指定动画。
| 配置项 | 说明 |
|---|---|
| key | 动画的名称。 |
| repeatDelay | 重复延迟。 |
this.anims.pauseAll()、this.anims.resumeAll()
暂停所有动画、继续所以动画。
Pause Animation Instances
// ……
const square = this.anims.create({ key: 'square', frames: this.anims.generateFrameNames('gems', { prefix: 'square_', end: 14, zeroPad: 4 }), repeat: -1 });
// ……
square.pause()
square.resume()
Phaser.Animations.Animation.pause()、Phaser.Animations.Animation.resume()
暂停此类型动画的实例、继续此类型动画的实例。
Play After Delay
Phaser.GameObjects.Sprite.anims.playAfterDelay(key, delay)
Reverse Animation
Phaser.GameObjects.Sprite.playReverse(key)
this.anims.reverse()
Phaser.GameObjects.Text.setText(value)
设置文本。字符串数组会自动添加 \n 换行。
Show Animation Play Through
Phaser.GameObjects.Sprite.anims.restart()
重新开始动画。
Tween Timescale
this.tweens.add(config)
config 里有个 timeScale 的配置。{ from: 0.5, to: 2 }。但 3.24 文档里未找到说明,3.50-beta-11 的代码里也未发现。