覆盖绘图顺序scene2D的舞台

Posted

技术标签:

【中文标题】覆盖绘图顺序scene2D的舞台【英文标题】:overriding drawing order scene2D's stage 【发布时间】:2014-03-17 08:27:28 【问题描述】:

libgdx 中为您提供了一个复杂的Scene2D 图,其中包含多个Group'sActor's。您希望用户选择一些Actors 并在最后绘制它们,以便它们看起来集中在任何其他Actors 之上。

我想对Stage 进行两次迭代。第一次绘制未选中的Actors,第二次绘制选中的actors。但是,我没有看到任何“好的”方法来强制执行此行为。

我更喜欢干净的选项。我不想为了这个小小的添加而复制整个方法实现。

什么不起作用:

Actor'stoFront() 方法只适用于它的兄弟姐妹。 在舞台中交换Actor's 的位置:这会修改Actors 的转换。

要考虑的场景:您有一个Root,其中有一个组gA 和一个组gBGroup gA 包含两个图像 iA1iA2Group gB 包含一张图片 iB。假设Group gA 首先添加到舞台,并且图像 iA1iB 重叠;现在您要选择 iA1 并使其出现在 iB 上。我不想只调用 gA.toFront();这会将整个Group gA 放在前面,这意味着 iA2 也放在前面。将 iA2 放在前面会产生不希望的效果,将部分图像隐藏在 Group gB

【问题讨论】:

见***.com/questions/16129903/… 了解一些想法 这些想法只适用于组内的所有兄弟姐妹。不在场景图中不同分支上多个深度的演员/组之间。 如果设置Actor 的z 索引,通过使用toFront() 或toBack() 会更改Actor 的z-Index 并对Actor 列表进行排序。 Actors 具有高 z 索引的最后会绘制,Actors 具有低 z 索引将首先绘制,以此类推。如果您在 select() 方法中调用 actor.toFront() 或者无论如何调用它,这个 Actor 将在最后呈现。在deselect(),您可以致电toBack()。这适用于Group 到,因为GroupActor 子类。这不是一个 100% 的工作,但在这种情况下,这应该足够了。 @Vjeetje 它确实适用于场景图中的组。由于Group 也是Actor,因此您可以将其进行比较。只需为Group 提供正确的深度。在这种情况下,该组的兄弟姐妹应该具有相同的深度。否则它不会起作用,因为你不能让组在舞台内的不同时间绘制。 (只需从集团中调用.draw)我建议添加一个插入排序而不是集合排序。对于紧密排序的列表,它要快得多。 (我认为你的名单不会有太大变化) 也许我并不清楚这一点,但这些想法没有考虑到以下情况:你有一个具有组 gA 和组 gB 的根。 gA 组包含两个图像 iA1 和 iA2。 gB 组包含一个图像 iB。假设 gA 组首先添加到阶段,并且图像 iA1 与 iB 重叠;现在您要选择 iA1 并使其出现在 iB 上。您的建议会将整个 gA 组放在前面,这意味着 iA2 也放在前面。放置 iA2 会产生不良影响。 【参考方案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 中的实现方式 - 组是一个层。如果您不想要图层,请更改组的功能或停止使用组。

【讨论】:

【参考方案2】:

您可以通过覆盖父级上的 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);

【讨论】:

以上是关于覆盖绘图顺序scene2D的舞台的主要内容,如果未能解决你的问题,请参考以下文章

将box2dLight附加到scene2d.Actor

反转图例顺序而不更改绘图快速条形图中的条形顺序

Python绘图强制按字母顺序而不是按时间顺序排序日期

jupyter 按顺序打印绘图和数据框,for循环

如何在 QGridLayout 中设置小部件的顺序

webgl 绘图顺序,模板缓冲区