2013-04-21 81 views
7

我在排序LibGdx Stage对象中的Actor时遇到问题。舞台渲染后,图像按照它们添加的顺序渲染。舞台使用数组来保存演员。我试着设置每个Actor的ZIndex,但它仍然没有排序。然后我试图创建一个像这样的比较对象:如何在libgdx阶段对演员进行排序?

public class ActorComparator implements Comparator <Actor> { 
    @Override 
    public int compare(Actor arg0, Actor arg1) { 
     if (arg0.getZIndex() < arg1.getZIndex()) { 
      return -1; 
     } else if (arg0.getZIndex() == arg1.getZIndex()) { 
      return 0; 
     } else { 
      return 1; 
     } 
    } 
} 

,然后当我想要做实际的比较我做:

Collections.sort(Stage.getActors(), new ActorComparator()); 

它给了我下面的错误,并不会编译:

The method sort(List<T>, Comparator<? super T>) in the type Collections 
is not applicable for the arguments (Array<Actor>, ActorComparator) 

我不知道我做错了什么。谁可以给我解释一下这个?

+0

很高兴我偶然发现了这个问题。 Z指数问题让我绕着圈走 – Bobby 2015-09-03 12:17:32

回答

10

看起来像您的代码Stage.getActors()返回的ArrayActors而不是ListCollections.sort()方法只接受列表。 尝试: z索引是由阶段重写为任何阵列的内部顺序是:从@詹姆斯霍洛维排序(通过在问题的z-index)

Collections.sort(Arrays.asList(Stage.getActors().toArray()), new ActorComparator()); 

更新。因此设置Z-Index不起作用,除非您将其设置为高于列表的长度,然后它将图像放在列表的顶部(内部Stage执行此操作)。这通过按名称或ID排序来解决。

+1

即使在运行时也不会抛出任何错误,但似乎没有效果。它可能的getActors()发送一个副本,在这种情况下,我需要以某种方式获取排序列表并将其重置为舞台。 – Lokiare 2013-04-21 11:17:39

+0

@JamesHolloway可以尝试在Actor类中覆盖equals()和hashcode(),如果可能的话? – 2013-04-21 11:31:50

+0

我发现了一个不同的问题。显然,尽管我将ZIndex设置为-1。所以你的代码可能工作正常,但问题在别的地方。 – Lokiare 2013-04-21 11:35:28

15

与其接受的答案不同,我更喜欢准备好几个“层”组,然后以任何顺序添加到这些组中,使我满意。

Group bg = new Group(); 
Group fg = new Group(); 
// the order is important in the following two lines 
stage.addActor(bg); 
stage.addActor(fg); 

bg.addActor(whatever); 
fg.addActor(whatever); 
bg.addActor(whatever); 
fg.addActor(whatever); 

(当然所述addActor()顺序仍的bg元件之间事项,和fg要素中的,但不是fg的元件和bg一个元件之间。)

此工作流程的工作原理以及在继承方案,其中基类拥有受保护的组图层(this.bgthis.fg,...)并将它们添加到舞台中。然后,派生类可以将事物添加到这些层,而无需照顾订单。

+1

这是一个很好的答案,但我不认为它适用于OP需要的内容。您的示例适用于半静态元素,如HUD,背景或其他效果图层。但是如果你想修改actor的动态顺序呢?例如,如果Y位置比门大并且如果位置在门下方则位于门前,则演员将在门后面。也许我错了,但我不认为你的解决方案可以照顾到这一点。 – NMC 2014-09-03 16:56:02

0

可能不适合所有情况,但我使用LibGdx Actor.userObject存储我的z-index,然后基于此自动排序。在屏幕或游戏类:

class ActorZOrderComparator implements Comparator<Actor> { 
    @Override 
    public int compare(Actor o1, Actor o2) { 
     if (o1 != null && o1.getUserObject() != null && o1.getUserObject() instanceof Integer 
       && o2 != null && o2.getUserObject() != null && o2.getUserObject() instanceof Integer) { 
      int z1 = (Integer) o1.getUserObject(); 
      int z2 = (Integer) o2.getUserObject(); 
      return z1 - z2; 
     } else if (o1 != null && o2 != null) { 
      return o1.getZIndex() - o2.getZIndex(); 
     } else if (o1 != null) { 
      return -1; 
     } else if (o2 != null) { 
      return 1; 
     } else { 
      return 0; 
     } 
    } 
} 

protected ActorZOrderComparator zOrderComparator = new ActorZOrderComparator(); 
private boolean invalidZOrder; 

protected void addActor(Actor actor) { 
    stage.addActor(actor); 
    if (actor.getUserObject() instanceof Integer) { 
     invalidZOrder = true; 
    } 
} 

@Override 
public void render(float delta) { 
    if (invalidZOrder) { 
     Arrays.sort(stage.getRoot().getChildren().begin(), zOrderComparator); 
     stage.getRoot().getChildren().end(); 
     invalidZOrder = false; 
    } 
} 

,然后添加使用新方法addActor(不stage.addActor)演员:

Image leftBar = new Image(skin, "leftBar"); 
    leftBar.setPosition(0, GameSettings.VIEWPORT_HEIGHT * 0.5f, Align.left); 
    leftBar.setUserObject(1); // <-- this is the z-index, set it before calling addActor(..) 
    addActor(leftBar); 

这也将避免排序每个渲染调用数组。 希望它有帮助!

0

我已经使用一些浮点值来排序我的球员。玩家指数越高,价值越大。这里是我的片段: -

Map<Actor, Float> map = new HashMap<Actor, Float>(); 
    map.put(playerActor, playerArea); 
    for (int i = 0; i < totalEnemies; i++) { 
     if (i != playerImageNo) { 
      map.put(enemyActor[i], enemyArea[i]); 
     } 
    } 
    int noOfPlayers = map.size(); 

    // Sort Map based on values(size) 
    Set<Entry<Actor, Float>> set = map.entrySet(); 
    List<Entry<Actor, Float>> list = new ArrayList<Entry<Actor, Float>>(set); 
    Collections.sort(list, new Comparator<Map.Entry<Actor, Float>>() { 
     @Override 
     public int compare(Map.Entry<Actor, Float> o1, 
       Map.Entry<Actor, Float> o2) { 
      return (o2.getValue()).compareTo(o1.getValue()); 
     } 
    }); 

    for (Map.Entry<Actor, Float> entry : list) { 
     entry.getKey().setZIndex(noOfPlayers);   
     System.out.println("Player: " + entry.getKey() + ", index: " + noOfPlayers); 
     noOfPlayers--; 
    } 
0

我的解决方案适用于快速测试,但仍可能存在一些缺陷。如果人们发现任何东西,然后请大喊,但这对我来说很好,而且很轻。

我只在我的卡片上运行它(我正在写卡片游戏),所以它只调整舞台上的卡片类别,并且它们可能总是高于表格/标签等其他东西。

我已将本地int zIndex添加到我的类中,这是比较器中使用的,并且在setZIndex方法的开始处设置。

该方法的开始部分从Actor类中的原始部分解除。

@Override 
public void setZIndex(int index) { 
    this.zIndex = index; 
    if (index < 0) throw new IllegalArgumentException("ZIndex cannot be < 0."); 
    Group parent = this.getParent(); 
    if (parent == null) return; 
    Array<Actor> children = parent.getChildren(); 
    if (children.size == 1) return; 
    ArrayList<Card> allCards = new ArrayList<Card>(); 
    for(Actor child : children) { 
     if(child instanceof Card) { 
      allCards.add((Card)child); 
     } 
    } 
    Collections.sort(allCards, new ZIndexComparator()); 
    for (Card card : allCards) { 
     children.removeValue(card, false); 
     children.add(card); 
    } 
} 

class ZIndexComparator implements Comparator<Card> { 
    public int compare(Card card1, Card card2) { 
     return card1.zIndex - card2.zIndex; 
    } 
} 
0

最简单的解决方案!我很惭愧,只要它确实想出了这个...

制作一个扩展舞台的“ZStage”类。覆盖getActors方法。泡泡 - 根据他们的Y索引对演员进行排序以获取他们的渲染顺序。

公共类ZStage扩展阶段{

public ZStage(Viewport vp){ 
    super(vp); 
} 

@Override 
/** Returns the root's child actors. 
* @see Group#getChildren() */ 
public Array<Actor> getActors() { 
    SnapshotArray<Actor> children = getRoot().getChildren(); 

    boolean sorting = true; 
    while(sorting){ 
     sorting=false; 
     for(int x=0; x< children.size-1; x++){ 
      if(children.get(x).getY() < children.get(x+1).getY()){ 
       children.swap(x,x+1); 
       sorting=true; 
      } 
     } 
    } 

    return children; 
} 

}

0

我有我的所有参与者扩展DepthActor类,它包含的深度值和实现Comparable<DepthActor>

import com.badlogic.gdx.scenes.scene2d.Actor; 

import java.util.Comparator; 

/** 
* @author snd 
* @since May 02, 2017 
*/ 
public class DepthActor extends Actor implements Comparable<DepthActor> 
{ 
    public int depth; 

    @Override 
    public int compareTo(DepthActor o) 
    { 
    return depth < o.depth ? -1 : (depth > o.depth ? 1 : 0); 
    } 
} 

然后分拣地方是微不足道的:

com.badlogic.gdx.utils.Sort.instance().sort(stage.getActors());