覆盖绘制顺序:Scene2D 舞台的处理方式

8
您将获得一个在libgdx中使用的包含多个Group和Actor的复杂Scene2D图形。您希望用户选择一些Actor并在最后绘制它们,以便它们出现在其他Actor的顶部。
我想要两次迭代Stage。第一次绘制未选定的Actors,第二次绘制选定的Actors。然而,我没有看到任何“好”的方法来强制执行此行为。
我更喜欢干净的选项。我不想仅仅为了这个小的添加而复制整个方法实现。
不起作用的方法:
- Actor的toFront()方法仅适用于其兄弟节点。 - 交换舞台上Actor的位置:这会修改Actors的变换。
需要考虑的情况:您有一个Root,其中包含一个名为gA的组和一个名为gB的组。 Group gA包含两个图像iA1和iA2。组gB包含一个图像iB。假设先添加Group gA到舞台,并且图像iA1与iB重叠。现在,您想要选择iA1并使其显示在iB之上。我不想仅调用gA.toFront(); 这将使整个Group gA置于前端,这意味着iA2也被置于前端。将iA2放在前面会隐藏Group gB内部的图像部分。

查看https://dev59.com/ZHHYa4cB1Zd3GeqPIzUL以获取一些想法。 - P.T.
1
这些想法仅适用于同一组中的所有兄弟节点,而不适用于场景图中不同分支上多个深度的演员/组之间。 - Vjeetje
如果您设置了Actor的z-index,通过使用toFront()toBack(),它将更改该Actor的z-Index并对Actor列表进行排序。具有高z-index的Actor将最后绘制,具有低z-index的Actor将首先绘制,因此在后面。如果您在select()方法中调用actor.toFront()或者其他类似的方法,这个Actor将会被最后渲染。在deselect()中,您可以调用toBack()。这也适用于Group,因为GroupActor子类。虽然这不是一个100%有效的方法,但在这种情况下应该已经足够了。 - Robert P
1
也许我没有表达清楚,但这些想法没有考虑到以下情况:您有一个带有组gA和组gB的根。组gA包含两个图像iA1和iA2。组gB包含一个图像iB。假设先将组gA添加到舞台,并且图像iA1与iB重叠;现在您想选择iA1并使其出现在iB上方。您的建议会将整个组gA置于最前面,这意味着iA2也会被置于最前面。将iA2放在最前面会产生不良影响。 - Vjeetje
如果您将演员从场景图中移除并放置在其他位置,则会丢失其继承自祖先的一部分变换。如果您将父级(一个组)移动到场景图中的其他位置,则该组内的其他演员可能会被放置在您不想要的其他演员之上。因此,我不同意这种方法。 - Vjeetje
显示剩余4条评论
2个回答

1

有两种解决方案-

1-停止使用[多个]组。虽然很糟糕,但这可能是更容易的选择。如果您查看渲染/绘制的方式,则从舞台的根组开始并获取其子级并呈现它们。对于这些子项中的每一个,如果它们是组,则呈现该组的子项。ZIndex不过是组内子项的顺序。如果您查看Actor的setZIndex,则可以看到为什么toFrontsetZIndex只影响同级。

public void setZIndex (int index) {
    if (index < 0) 
        throw new IllegalArgumentException("ZIndex cannot be < 0.");

    Group parent = this.parent;
    if (parent == null) 
        return;

    Array<Actor> children = parent.getChildren();
    if (children.size == 1) 
        return;

    if (!children.removeValue(this, true)) 
        return;

    if (index >= children.size)
        children.add(this);
    else
        children.insert(index, this);
}

2-另一个选项是更改所有演员的绘制顺序。您需要扩展Stage并替换draw方法,以根据您选择的不同顺序进行draw。您可能需要结合Group.drawChildren方法的许多功能。

TLDR;在 LibGDX 中实现的方式-一个组是一层。如果您不想要图层,那么只能更改组的功能或停止使用组。


0

你可以通过在父级上覆盖 draw 来解决这个问题:

Group parent = new Group() {
    // Do not render the child as we will render it later
    @Override
    protected void drawChildren(Batch batch, float parentAlpha) {
        child.setVisible(false);
        super.drawChildren(batch, parentAlpha);
        child.setVisible(true);
    }

    // Render the child after the draw method so it's always on top
    @Override
    public void draw(Batch batch, float parentAlpha) {
        super.draw(batch, parentAlpha);
        child.draw(batch, parentAlpha);
    }
};

Group child = new Group();
parent.addActor(child);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接