# 分组

在你创建游戏场景时,可以给精灵们分组,作为一个整体管理。Pixi有一个名为Container的对象,它可以把精灵们组合在一起。

假设您要显示三个精灵:一只猫,一只刺猬和一个老虎。创建并设置好它们的坐标——但不要将它们添加到舞台上

//The cat
let cat = new Sprite(id["cat.png"]);
cat.position.set(16, 16);

//The hedgehog
let hedgehog = new Sprite(id["hedgehog.png"]);
hedgehog.position.set(32, 32);

//The tiger
let tiger = new Sprite(id["tiger.png"]);
tiger.position.set(64, 64);
1
2
3
4
5
6
7
8
9
10
11

然后,创建一个animals容器(container)(用来把它们组合起来):

let animals = new PIXI.Container();
1

然后使用addChild它们三个添加到分组(group)

animals.addChild(cat);
animals.addChild(hedgehog);
animals.addChild(tiger);
1
2
3

最后,把这个分组添加到场景中。

app.stage.addChild(animals);
1

stage对象也是一个容器(container),它是所有Pixi精灵的根容器)

下面就是这段代码的效果:

如上图所示,您可以将animals分组视为一个单元。把容器(Container)视为一种不包含纹理的特殊精灵。

您可以用animalschildren属性列出它包含的所有精灵。

console.log(animals.children)
//Displays: Array [Object, Object, Object]
1
2

你可以看到,animals分组包含3个精灵。

因为animals分组与精灵类似,所以它拥有精灵所有的属性,因此你可以改变它的xyalphascale等值。在父容器上更改的任何属性值都将以一种相对的方式影响子精灵。

因此,如果设置了分组的xy坐标,则所有子精灵将相对于组的左上角重新定位。 请看下面,如果将动物的xy坐标设置为64,会发生什么?

animals.position.set(64, 64);
1

整个精灵分组将向右移动64个像素,向下移动64个像素。

animals分组也有其自己的尺寸,该尺寸基于包含的精灵所占据的面积。 您可以查看它的widthheight,如下所示:

console.log(animals.width);
//Displays: 112

console.log(animals.height);
//Displays: 112
1
2
3
4
5

如果改变分组的widthheight会发生什么?

您可以将尽可能多的容器嵌套到其他容器中,以便在需要时创建多层结构。然而,一个可显示对象DisplayObject(例如一个精灵或另一个容器)只能拥有一个父级。如果您使用addChild使一个精灵成为另一个对象的子对象,Pixi将自动从当前父对象中删除它。

# 局部坐标和全局坐标

当您将一个精灵添加到容器中时,它的xy坐标相对于分组的左上角。xy就是局部坐标。你知道猫在这幅图中的坐标吗?

让我们看一下:

console.log(cat.x);
//Displays: 16
1
2

16?是! 那是因为猫从该组的左上角仅偏移了16个像素。 16是猫的局部坐标。

精灵也有一个全局坐标。全局坐标是从舞台左上角到精灵的定位点(通常是精灵的左上角)的距离。你可以在使用toGlobal方法查看一个精灵的全局坐标:

parentSprite.toGlobal(childSprite.position)
1

这意味着你可以像这样找到animals分组中猫的全局坐标。

console.log(animals.toGlobal(cat.position));
//Displays: Object {x: 80, y: 80...};
1
2

xy坐标是80。这就是猫的全局坐标相对于舞台左上角的坐标。

如果你想要查看一个精灵的全局位置,但又不知道它的父容器是谁,那怎么办呢?别急,每个精灵都有一个叫做parent的属性,它会告诉你精灵的父容器是谁。如果您直接向舞台添加一个精灵,那么舞台将是精灵的父容器。在上面的例子中,猫的父容器是animals。这意味着您可以通过编写这样的代码来获取猫的全局坐标。

cat.parent.toGlobal(cat.position);
1

即使你不知道猫的父容器是什么,你也能知道它的全局坐标。

还有一种方法可以计算全局坐标!这会是最好的一种方法,所以听好了!如果您想知道画布左上角到精灵的距离,而不知道或不关心精灵的父容器是什么,那么可以使用getGlobalPosition方法。下面我们就用它来查看老虎的全局坐标。

tiger.getGlobalPosition().x
tiger.getGlobalPosition().y
1
2

这这个例子中,x和y值是128。getGlobalPosition的特别之处在于它是高度精确的:它将在精灵的本地坐标发生变化时立即给出精灵的准确全局坐标。这是我要求Pixi开发团队专门为游戏添加的这一功能,以精确检测碰撞。(感谢Matt和团队的其他成员添加了它!)

如果要将全局坐标转换为本地坐标怎么办? 您可以使用toLocal方法,如下所示:

sprite.toLocal(sprite.position, anyOtherSprite)
1

使用toLocal查看精灵和其他精灵之间的距离。下面我们来看看老虎和刺猬的相对位置。

tiger.toLocal(tiger.position, hedgehog).x
tiger.toLocal(tiger.position, hedgehog).y
1
2

x值是32,y值是32。在示例图像中,可以看到老虎的左上角位于刺猬左上角向右、向下偏移32像素的位置。

# 使用粒子容器ParticleContainer对精灵进行分组

Pixi有另一种高性能的方式来组合精灵,称为粒子容器ParticleContaine(PIXI.particles.ParticleContainer)。任何在ParticleContainer中的精灵渲染速度都比在常规容器中快2到5倍。这对于游戏来说是一个巨大的性能提升。

像这样创建一个ParticleContainer

let superFastSprites = new PIXI.particles.ParticleContainer();
1

然后使用addChild向它添加精灵,就像使用任何普通容器一样。

如果您决定使用ParticleContainer,则必须做出一些妥协。ParticleContainer中的精灵只有几个基本属性:xywidthheightscalepivotalpha、'visible等等。而且,它所包含的精灵包含子元素。一个ParticleContainer也不能使用Pixi的高级视觉效果,如过滤器和混合模式。每个ParticleContainer只能使用一个纹理(所以如果你想要不同外观的精灵,你必须使用雪碧图)。但是为了获得巨大的性能提升,这些妥协是随处可见的。

为什么精灵在粒子容器中的速度如此之快?因为精灵的位置是直接在GPU上计算的。你正在使用的最新版本的Pixi很可能比我在这里描述的有更多的特性丰富的ParticleContainer。有关详细信息,请参阅当前ParticleContainer文档。

在创建ParticleContainer的时候,有四个可选参数:sizepropertiesbatchSizeautoResize

let superFastSprites = new ParticleContainer(maxSize, properties, batchSize, autoResize);
1

maxSize的默认值为1500。因此,如果想要显示更多的sprite,请将其设置为更大的数字。 properties参数是一个可以设置5个布尔值的对象:scale, position, rotation, uvsalphaAndTintposition的默认值为true,但其他所有值均设置为false。 这意味着,如果您想在ParticleContainer中更改子画面的rotationscaletintuvs,则必须将这些属性设置为true,如下所示:

let superFastSprites = new ParticleContainer(
  size, 
  {
    rotation: true,
    alphaAndtint: true,
    scale: true,
    uvs: true
  }
);
1
2
3
4
5
6
7
8
9

但是,如果您认为不需要使用这些属性,请将它们设置为false可以最大限度地发挥性能。

什么是uv属性?只有当粒子需要在动画中改变纹理时,才将它设置为true。(所有的精灵的纹理必须在同一个雪碧图上)

(注意:UV映射是3D图形显示术语,指的是被映射到3D表面上的纹理(图像)的xy坐标。Ux轴,Vy轴。WebGL已经使用 xyz用来表示3D空间位置,因此选择UV表示2D图像纹理的xy。)

lastUpdate: 2/3/2023, 2:34:54 AM