如何使用补间为 Phaser 3 中的线条缩放设置动画?

How to animate a line scaling in Phaser 3 with a tween?

想象一个很简单的场景:

    private create(): void {
        const circ = this.add.circle(
            400, 320, 200, 0xff0000
        );

        const l1 = this.add.line(
            0, 0, 400, 320, 400, 100, 0x0000ff
        ).setOrigin(0);

        const l2 = this.add.line(
            0, 0, 400, 320, 200, 320, 0x0000ff
        ).setOrigin(0);
    }

到目前为止一切顺利。

现在我想缩放这个简单的图形,相同的配置是其当前大小的 1.5 倍:

    private create(): void {
        const circ = this.add.circle(
            400, 320, 200, 0xff0000
        );

        const l1 = this.add.line(
            0, 0, 400, 320, 400, 100, 0x0000ff
        ).setOrigin(0);

        const l2 = this.add.line(
            0, 0, 400, 320, 200, 320, 0x0000ff
        ).setOrigin(0);

        this.tweens.add({
            targets: [circ, l1, l2],
            scale: 1.5,
            yoyo: false,
            duration: 2000,
            ease: 'Sine.easeInOut'
        });
    }

预期行为:

实际行为:

就目前情况而言,只有#1 符合我的预期。然而,这些线是平移的,而不仅仅是缩放。而且翻译似乎受到传递给 tweens.add 的比例参数的影响。是什么赋予了?我在这里错过了什么?

考虑到 Phaser 3 中“原点”wrt 线的各种配置,我最糟糕的预料是这些线 emanate/grow 与圆(从 center/origin 发出)不同。但我绝对希望这些线保持 still/keep 它们在圆心的交点。

你能解释一下 Phaser 在这里到底做了什么吗?我应该怎么做才能达到我想要的效果?

Phaser 3 中的 Line GameObject 有很多不直观的地方,所有这些都是导致此行为的原因。让我们分解一下。

线条与起源

首先,区分线作为几何实体和线作为Phaser 3 Game Object。它们是相关的,但混淆源于微妙之处。

对于 Phaser 3 line Game Object,有三个有序对 p (x, y) 你需要记住:

  • P(X,Y),直线的原点,相对于游戏世界(我们要定义一会儿的术语);在游戏世界中,(0, 0)在左上角。
  • P1(X1,Y1),定义直线的第一个点,相对于P
  • P2(X2,Y2),定义直线的第二个点,相对于P

另一个重要的事情是,游戏世界基本上是一个绕 x 轴翻转的笛卡尔坐标系。所以负 x 值仍然向左移动,但负 y 值 向上 和正 y 值 向下 .

现在让我们定义原点,我将从 official docs:

An object's origin is a normalized value in the range [0, 1].

For the x-axis, 0 means the left of the Game Object and 1 means the right.

For the y-axis, 0 means the top of the Game Object and 1 means the bottom.

默认情况下,原点设置为 0.5,即对象的中心。

解释示例和补间

让我们以示例中的水平线 l2 为例,看看它是如何绘制的。

const l2 = this.add.line(
    0, 0, 400, 320, 200, 320, 0x0000ff
).setOrigin(0);
  • 原点在游戏对象的左侧。
  • 对于游戏世界来说,这个原点在0、0或者左上角。
  • 直线由相对于原点的两个点 (400, 320) 和 (200, 320) 定义。

这里的重要观察是原点完全在定义的几何线之外。实际上,在您的原点(在 (0, 0))、游戏对象左侧和右下角(在 (400, 320))之间的矩形区域中有相当大的不可见 space。

现在,当调用补间时,它实际上缩放了游戏对象,而不仅仅是几何线。而且由于大部分游戏对象是“不可见的”(几何线是唯一可见的部分),所以效果就像几何线在平移一样!

解决方案

要获得预期的效果,请将游戏对象限制在几何线所占的区域。一种这样的方法是:

  • 由于我们希望线条以与圆相同的方式“辐射”,因此将 P 设置在圆的中心 (400, 320) 处。此外,将 P1 设置为 (0, 0)---记住这是相对于 P 的,所以在游戏世界中,我们只是制作了 P = P1.
  • 让我们将线条的原点保留为 0,但现在我们必须将它们的 P2 值分别重新定义为 (0, -100) 和 (0, -200)。

综合起来,

    private create(): void {
        const circ = this.add.circle(
            400, 320, 200, 0xff0000
        );

        const l1 = this.add.line(
            400, 320, 0, 0, 0, -100, 0x0000ff
        ).setOrigin(0);

        const l2 = this.add.line(
            400, 320, 0, 0, -200, 0, 0x0000ff
        ).setOrigin(0);

        this.tweens.add({
            targets: [circ, l1, l2],
            scale: 1.5,
            yoyo: false,
            duration: 2000,
            ease: 'Sine.easeInOut'
        });
    }