Phaser 3中如何用单张Spritesheet实现多Sprite分层动画?
需求可行性与实现方案
完全可行,Phaser支持从单张Spritesheet生成多个独立Sprite,并为每个Sprite绑定不同的动画序列,通过容器可以统一管理它们的位置和同步触发动画。
1. 扩展动画定义
在createAnimations函数中,为帽子和剑分别创建四个方向的动画,用带前缀的key区分(比如hat-、sword-):
createAnimations() { // 基础服装动画(保留原代码) this.anims.create({ key: 'up', frames: this.anims.generateFrameNumbers('male_pirate', { frames: [0, 48, 92, 130, 168, 205,232, 258, 278] }), frameRate: 10, repeat: -1 }); this.anims.create({ key: 'right', frames: this.anims.generateFrameNumbers('male_pirate', { frames: [2, 50, 94, 132, 170, 207, 234, 260, 280] }), frameRate: 10, repeat: -1 }); this.anims.create({ key: 'down', frames: this.anims.generateFrameNumbers('male_pirate', { frames: [4, 52, 96, 134, 172, 209, 236, 262, 282] }), frameRate: 10, repeat: -1 }); this.anims.create({ key: 'left', frames: this.anims.generateFrameNumbers('male_pirate', { frames: [6, 54, 98, 136, 174, 211, 238, 264, 284] }), frameRate: 10, repeat: -1 }); // 帽子动画 this.anims.create({ key: 'hat-up', frames: this.anims.generateFrameNumbers('male_pirate', { frames: [15, 28 /* 补充完整你的帽子上方向帧序列 */] }), frameRate: 10, repeat: -1 }); this.anims.create({ key: 'hat-right', frames: this.anims.generateFrameNumbers('male_pirate', { frames: [/* 你的帽子右方向帧序列 */] }), frameRate: 10, repeat: -1 }); this.anims.create({ key: 'hat-down', frames: this.anims.generateFrameNumbers('male_pirate', { frames: [/* 你的帽子下方向帧序列 */] }), frameRate: 10, repeat: -1 }); this.anims.create({ key: 'hat-left', frames: this.anims.generateFrameNumbers('male_pirate', { frames: [/* 你的帽子左方向帧序列 */] }), frameRate: 10, repeat: -1 }); // 剑动画 this.anims.create({ key: 'sword-up', frames: this.anims.generateFrameNumbers('male_pirate', { frames: [12, 60 /* 补充完整你的剑上方向帧序列 */] }), frameRate: 10, repeat: -1 }); this.anims.create({ key: 'sword-right', frames: this.anims.generateFrameNumbers('male_pirate', { frames: [/* 你的剑右方向帧序列 */] }), frameRate: 10, repeat: -1 }); this.anims.create({ key: 'sword-down', frames: this.anims.generateFrameNumbers('male_pirate', { frames: [/* 你的剑下方向帧序列 */] }), frameRate: 10, repeat: -1 }); this.anims.create({ key: 'sword-left', frames: this.anims.generateFrameNumbers('male_pirate', { frames: [/* 你的剑左方向帧序列 */] }), frameRate: 10, repeat: -1 }); }
2. 创建多Sprite并加入容器
修改角色创建代码,新增帽子和剑的Sprite,统一加入容器以保证位置同步:
// 创建基础角色Sprite this.player = this.add.sprite(0, 0, 'male_pirate', 0); // 创建帽子Sprite(初始帧对应帽子默认帧) this.hat = this.add.sprite(0, 0, 'male_pirate', 15); // 创建剑Sprite(初始帧对应剑默认帧) this.sword = this.add.sprite(0, 0, 'male_pirate', 12); // 创建容器并添加所有Sprite(注意顺序:基础角色在下,帽子、剑在上) this.container = this.add.container(playerInfo.x, playerInfo.y); this.container.setSize(32, 32); this.physics.world.enable(this.container); this.container.add(this.player); this.container.add(this.hat); this.container.add(this.sword);
3. 同步触发方向动画
在输入处理逻辑中,检测到方向按键时同时触发三个Sprite的对应动画:
// 上方向按键处理 this.input.keyboard.on('keydown_UP', () => { this.player.play('up', true); this.hat.play('hat-up', true); this.sword.play('sword-up', true); this.container.setVelocityY(-100); // 容器移动逻辑 }); // 右方向按键处理 this.input.keyboard.on('keydown_RIGHT', () => { this.player.play('right', true); this.hat.play('hat-right', true); this.sword.play('sword-right', true); this.container.setVelocityX(100); }); // 下方向按键处理 this.input.keyboard.on('keydown_DOWN', () => { this.player.play('down', true); this.hat.play('hat-down', true); this.sword.play('sword-down', true); this.container.setVelocityY(100); }); // 左方向按键处理 this.input.keyboard.on('keydown_LEFT', () => { this.player.play('left', true); this.hat.play('hat-left', true); this.sword.play('sword-left', true); this.container.setVelocityX(-100); }); // 按键抬起时停止动画(可选) this.input.keyboard.on('keyup', () => { this.player.stop(); this.hat.stop(); this.sword.stop(); this.container.setVelocity(0); });
关键注意点
- 层级顺序:容器内Sprite的添加顺序决定渲染层级,基础角色需放在最下方避免被遮挡。
- 动画同步:确保帽子、剑的动画帧数量、帧率与基础角色一致,保证动画同步性。
- 初始帧匹配:每个Sprite的初始帧要对应各自方向的静态帧,避免初始显示错误。
内容的提问来源于stack exchange,提问作者Manuel Panizzo
相关产品推荐
相关产品推荐

