动画和补间

这是 第 14 步,共 16 步,来自 Gamedev Phaser 教程。我们将探索如何在游戏实现 Phaser 动画和补间,使游戏看起来更有趣、更生动。这将带来更好的、更具娱乐性的体验。

动画

在 Phaser 中,动画涉及从外部资源获取精灵表,然后按顺序显示精灵。例如,我们将让球在碰到东西时晃动。

首先,下载精灵表并将其保存在你的 /img 目录中。

接下来,我们将加载精灵表——将以下行放在你的 preload() 方法的底部

js
this.load.spritesheet("wobble", "img/wobble.png", {
  frameWidth: 20,
  frameHeight: 20,
});

与其加载单个球图像,不如加载整个精灵表——一个包含不同图像的集合。我们将按顺序显示精灵以创造动画的错觉。spritesheet() 方法的额外参数决定了给定精灵表文件中每个单独帧的宽度和高度,告诉程序如何将其分割以获取单个帧。

加载动画

接下来,进入你的 create() 方法,找到加载和配置球精灵的代码块,并在其下方放入对 anims.create 的调用,如下所示

js
this.ball = this.add.sprite(
  this.scale.width * 0.5,
  this.scale.height - 25,
  "ball",
);
// ...
this.ball.anims.create({
  key: "wobble",
  frameRate: 24,
  frames: this.anims.generateFrameNumbers("wobble", {
    frames: [0, 1, 0, 2, 0, 1, 0, 2, 0],
  }),
});

要为对象添加动画,我们使用 anims.create() 方法,该方法接收带有以下属性的参数

  • key:我们为动画选择的名称。
  • frameRate:帧率(单位为 fps)。由于我们将动画以 24fps 运行,并且有 9 帧,所以动画每秒将显示不到三次。
  • frames:一个定义动画期间显示帧的顺序的数组。如果你再次查看 wobble.png 图像,你会看到有三帧。Phaser 会提取它们并将对它们的引用存储在数组中——位置 0、1 和 2。上面的数组表示我们显示帧 0,然后是 1,然后是 0,以此类推。

当球击中挡板时应用动画

在处理球与挡板之间碰撞的 physics.collide() 方法调用中(update() 内的第一行,见下文),我们可以添加一个额外的参数,该参数指定一个函数,在每次发生碰撞时执行,与 hitBrick() 方法的执行方式相同。更新 update() 内的第一行,如下所示

js
class ExampleScene extends Phaser.Scene {
  // ...
  update() {
    this.physics.collide(this.ball, this.paddle, (ball, paddle) =>
      this.hitPaddle(ball, paddle),
    );
    this.physics.collide(this.ball, this.bricks, (ball, brick) =>
      this.hitBrick(ball, brick),
    );
    this.paddle.x = this.input.x || this.scale.width * 0.5;
    // ...
  }
  // ...
}

然后,我们可以创建 hitPaddle() 方法(以 ballpaddle 作为参数),并在调用时播放晃动动画。将以下方法添加到 hitBrick() 方法的上方

js
class ExampleScene extends Phaser.Scene {
  // ...
  hitPaddle(ball, paddle) {
    this.ball.anims.play("wobble");
  }
  // ...
}

每次球击中挡板时都会播放动画。如果你觉得这样可以让游戏看起来更好,也可以将 anims.play() 调用放在 hitBrick() 方法内部。

补间

动画按顺序播放外部精灵,而补间则平滑地动画化游戏世界中对象的属性,例如宽度或不透明度。

让我们向游戏中添加一个补间,使砖块在被球击中时平滑消失。转到你的 hitBrick() 方法,找到你的 brick.destroy(); 行,并用以下代码替换它

js
const destroyTween = this.tweens.add({
  targets: brick,
  ease: "Linear",
  repeat: 0,
  duration: 200,
  props: {
    scaleX: 0,
    scaleY: 0,
  },
  onComplete() {
    brick.destroy();
  },
});
destroyTween.play();

让我们一步步来,这样你就能明白发生了什么

  1. 在定义新补间时,你必须指定 targets 的哪个属性将被补间——在我们的例子中,不是在砖块被球击中时立即隐藏它们,而是将它们的宽度和高度缩放到零,这样它们就会很好地消失。为了达到这个目的,我们使用 tweens.add() 方法,指定 brick 作为 targets,并在 props 对象中指定 scaleXscaleY 属性进行补间。
  2. 我们可以设置的其他属性是 ease,它定义要使用的缓动函数(在本例中为 Linear),repeat,它定义补间应重复的次数(0 表示不重复),以及 duration,这是补间完成所需的时间(以毫秒为单位)。
  3. 我们还将添加可选的 onComplete 事件处理程序,它定义了一个在补间完成时执行的函数。
  4. 最后要做的是使用 play() 方法立即启动补间。

Compare your code

这是您到目前为止应该看到的效果,实时运行。要查看其源代码,请单击“播放”按钮。

后续步骤

动画和补间看起来很棒,但我们还可以为游戏添加更多内容——在下一节中,我们将研究处理 按钮 输入。