精灵动画卡在第一帧?
Sprite animation stuck on first frame?
使用 Phaser 3,我预加载了一个 spritesheet 并创建了一些动画...
import {Scene} from 'phaser';
class BootScene extends Scene {
constructor() {
super("scene-boot");
}
preload() {
this.load.spritesheet('px-hero', 'assets/sprites/px-hero.png', {
frameWidth: 16,
frameHeight: 16
});
// ...
}
create() {
// ...
this.anims.create({
key: 'px-hero-idle',
frames: this.anims.generateFrameNumbers('px-hero', {
start: 0,
end: 2
}),
frameRate: 10,
repeat: -1
});
this.anims.create({
key: 'px-hero-run',
frames: this.anims.generateFrameNumbers('px-hero', {
start: 3,
end: 6
}),
frameRate: 10,
repeat: -1
});
// ...
}
}
export default BootScene;
然后在我的 Sprite class 中(正在 BootScene 链接到的另一个场景中实例化),我正在尝试播放动画...
import {GameObjects} from 'phaser';
const {Sprite} = GameObjects;
class PxHero extends Sprite {
constructor(config) {
super(config.scene, config.x, config.y, "px-hero");
// Add self to scene's physics
config.scene.physics.world.enable(this);
config.scene.add.existing(this);
this.scene = config.scene;
this.keys = this.scene.input.keyboard.addKeys('W,S,A,D');
this.speed = 100;
this.jumpHeight = 300;
}
preUpdate(time, delta) {
const {W, S, A, D} = this.keys;
const {speed, jumpHeight, body} = this;
const touchingGround = body.blocked.down;
if (A.isDown) {
this.body.setVelocityX(-speed);
this.setFlipX(true);
}
else if (D.isDown) {
this.body.setVelocityX(speed);
this.setFlipX(false);
}
else {
this.body.setVelocityX(0);
}
if (W.isDown && touchingGround) {
this.body.setVelocityY(-jumpHeight);
}
// Animations
if (touchingGround) {
if (body.velocity.x !== 0) {
this.anims.play('px-hero-run', true); // here
}
else {
this.anims.play('px-hero-idle', true); // and here
}
}
}
}
export default PxHero;
但由于某些原因,他们只播放了动画的第一帧,然后卡在那里。
有人遇到过这种情况吗?到目前为止,我还没有找到任何解决方案。
每帧动画基于 preUpdate
函数工作,在不调用 super.preUpdate
的情况下在该函数中执行您的操作并不是最好的主意。那是第一,第二代替preUpdate
尝试使用update
函数,并且不要忘记在其中调用super.update
。
第三,尝试在不使用 preUpdate
和 update
函数的情况下做您想做的事。如果你甚至需要使用 update
函数,你可以通过将场景中的侦听器设置为 update
(Phaser.Scenes.Events.UPDATE
) 事件来实现。这将使您的代码更加清晰易懂,并且您永远不会错误地损害 Phaser 的主要功能。
您的代码中发生的情况如下,在每一帧渲染中,您的游戏都会检查并决定从头开始 运行 动画,这就是为什么您只看到第一帧的原因,只是因为当它尝试向您展示下一帧,您告诉他再次开始播放动画)
export default class PxHero extends Phaser.GameObjects.Sprite{
constructor(config) {
super(config.scene, config.x, config.y, "px-hero");
// Add self to scene's physics
// ## you've `this` here too
this.scene.add.existing(this);
this.scene.physics.world.enable(this);
this.prepare();
this.setListeners();
}
prepare(){
this.keys = this.scene.input.keyboard.addKeys('W,S,A,D');
this.speed = 100;
this.jumpHeight = 300;
}
setListeners(){
this.scene.events.on(Phaser.Scenes.Events.UPDATE, this.handleMovement, this)
}
handleMovement() {
const {W, S, A, D} = this.keys;
const {speed, jumpHeight, body} = this;
const touchingGround = body.blocked.down;
switch(true){
case A.isDown:
this.body.setVelocityX(-speed);
this.setFlipX(true);
break;
case D.isDown:
this.body.setVelocityX(speed);
this.setFlipX(false);
break;
case S.isDown:
this.body.setVelocityX(0);
break;
case W.isDown && touchingGround:
this.body.setVelocityY(-jumpHeight);
break;
}
// Animations
if (touchingGround) {
if (body.velocity.x !== 0) {
(!this.anims.isPlaying || this.anims.key !== 'px-her-run') &&
this.anims.play('px-hero-run', true); // here
}
else {
(!this.anims.isPlaying || this.anims.key !== 'px-her-idle') &&
this.anims.play('px-hero-idle', true); // and here
}
}
}
}
使用 Phaser 3,我预加载了一个 spritesheet 并创建了一些动画...
import {Scene} from 'phaser';
class BootScene extends Scene {
constructor() {
super("scene-boot");
}
preload() {
this.load.spritesheet('px-hero', 'assets/sprites/px-hero.png', {
frameWidth: 16,
frameHeight: 16
});
// ...
}
create() {
// ...
this.anims.create({
key: 'px-hero-idle',
frames: this.anims.generateFrameNumbers('px-hero', {
start: 0,
end: 2
}),
frameRate: 10,
repeat: -1
});
this.anims.create({
key: 'px-hero-run',
frames: this.anims.generateFrameNumbers('px-hero', {
start: 3,
end: 6
}),
frameRate: 10,
repeat: -1
});
// ...
}
}
export default BootScene;
然后在我的 Sprite class 中(正在 BootScene 链接到的另一个场景中实例化),我正在尝试播放动画...
import {GameObjects} from 'phaser';
const {Sprite} = GameObjects;
class PxHero extends Sprite {
constructor(config) {
super(config.scene, config.x, config.y, "px-hero");
// Add self to scene's physics
config.scene.physics.world.enable(this);
config.scene.add.existing(this);
this.scene = config.scene;
this.keys = this.scene.input.keyboard.addKeys('W,S,A,D');
this.speed = 100;
this.jumpHeight = 300;
}
preUpdate(time, delta) {
const {W, S, A, D} = this.keys;
const {speed, jumpHeight, body} = this;
const touchingGround = body.blocked.down;
if (A.isDown) {
this.body.setVelocityX(-speed);
this.setFlipX(true);
}
else if (D.isDown) {
this.body.setVelocityX(speed);
this.setFlipX(false);
}
else {
this.body.setVelocityX(0);
}
if (W.isDown && touchingGround) {
this.body.setVelocityY(-jumpHeight);
}
// Animations
if (touchingGround) {
if (body.velocity.x !== 0) {
this.anims.play('px-hero-run', true); // here
}
else {
this.anims.play('px-hero-idle', true); // and here
}
}
}
}
export default PxHero;
但由于某些原因,他们只播放了动画的第一帧,然后卡在那里。
有人遇到过这种情况吗?到目前为止,我还没有找到任何解决方案。
每帧动画基于 preUpdate
函数工作,在不调用 super.preUpdate
的情况下在该函数中执行您的操作并不是最好的主意。那是第一,第二代替preUpdate
尝试使用update
函数,并且不要忘记在其中调用super.update
。
第三,尝试在不使用 preUpdate
和 update
函数的情况下做您想做的事。如果你甚至需要使用 update
函数,你可以通过将场景中的侦听器设置为 update
(Phaser.Scenes.Events.UPDATE
) 事件来实现。这将使您的代码更加清晰易懂,并且您永远不会错误地损害 Phaser 的主要功能。
您的代码中发生的情况如下,在每一帧渲染中,您的游戏都会检查并决定从头开始 运行 动画,这就是为什么您只看到第一帧的原因,只是因为当它尝试向您展示下一帧,您告诉他再次开始播放动画)
export default class PxHero extends Phaser.GameObjects.Sprite{
constructor(config) {
super(config.scene, config.x, config.y, "px-hero");
// Add self to scene's physics
// ## you've `this` here too
this.scene.add.existing(this);
this.scene.physics.world.enable(this);
this.prepare();
this.setListeners();
}
prepare(){
this.keys = this.scene.input.keyboard.addKeys('W,S,A,D');
this.speed = 100;
this.jumpHeight = 300;
}
setListeners(){
this.scene.events.on(Phaser.Scenes.Events.UPDATE, this.handleMovement, this)
}
handleMovement() {
const {W, S, A, D} = this.keys;
const {speed, jumpHeight, body} = this;
const touchingGround = body.blocked.down;
switch(true){
case A.isDown:
this.body.setVelocityX(-speed);
this.setFlipX(true);
break;
case D.isDown:
this.body.setVelocityX(speed);
this.setFlipX(false);
break;
case S.isDown:
this.body.setVelocityX(0);
break;
case W.isDown && touchingGround:
this.body.setVelocityY(-jumpHeight);
break;
}
// Animations
if (touchingGround) {
if (body.velocity.x !== 0) {
(!this.anims.isPlaying || this.anims.key !== 'px-her-run') &&
this.anims.play('px-hero-run', true); // here
}
else {
(!this.anims.isPlaying || this.anims.key !== 'px-her-idle') &&
this.anims.play('px-hero-idle', true); // and here
}
}
}
}