你如何在libgdx阶段对Actors进行排序?

我在LibGdx Stage对象中排序Actors时遇到问题。 渲染舞台时,图像将按照添加顺序进行渲染。 Stage使用Array来保存Actors。 我已经尝试设置每个Actor的ZIndex,但它仍然没有排序。 然后我尝试创建一个这样的比较器对象:

public class ActorComparator implements Comparator  { @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, Comparator) in the type Collections is not applicable for the arguments (Array, ActorComparator) 

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

看起来你的代码Stage.getActors()返回一个Actors Array而不是ListCollections.sort()方法仅接受列表。 尝试:

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

从@James Holloway更新排序(通过问题中的z-index):舞台将z-index覆盖为数组的内部顺序。 因此设置Z-Index没有任何效果,除非您将其设置为高于列表的长度,然后它只是将图像放在列表的顶部(内部Stage执行此操作)。 这可以通过按名称或ID排序来解决。

而不是接受的答案,我更喜欢准备几个“图层”组,然后以任何顺序添加到这些组中,它让我高兴。

 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的元素之间却不重要。)

此工作流在inheritance方案中运行良好,其中基类拥有受保护的this.bg层( this.bgthis.fg ,…)并将它们添加到舞台中。 然后派生类可以在不处理顺序的情况下向这些图层添加内容。

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

 class ActorZOrderComparator implements Comparator { @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)添加actor:

 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); 

这也将避免在每次渲染调用时对数组进行排序。 希望能帮助到你!

我使用了一些浮动值来对我的玩家进行排序。 玩家的指数越大值越高。 这是我的片段: –

  Map map = new HashMap(); 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> set = map.entrySet(); List> list = new ArrayList>(set); Collections.sort(list, new Comparator>() { @Override public int compare(Map.Entry o1, Map.Entry o2) { return (o2.getValue()).compareTo(o1.getValue()); } }); for (Map.Entry entry : list) { entry.getKey().setZIndex(noOfPlayers); System.out.println("Player: " + entry.getKey() + ", index: " + noOfPlayers); noOfPlayers--; } 

我的解决方案在快速测试中适用于我,但可能仍存在一些缺陷。 如果有人发现任何东西,那么请大声喊叫,但这对我来说效果很好而且相当轻松。

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

我已经在我的类中添加了一个本地int zIndex ,它是在Comparator中使用的,并且在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 children = parent.getChildren(); if (children.size == 1) return; ArrayList allCards = new ArrayList(); 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 { public int compare(Card card1, Card card2) { return card1.zIndex - card2.zIndex; } } 

最简单的解决方案! 我感到很惭愧,只要它做到了这一点就把它带走了……

创建一个扩展Stage的“ZStage”类。 覆盖getActors方法。 根据Y索引对actor进行冒泡排序以获取其渲染顺序。

公共类ZStage扩展Stage {

 public ZStage(Viewport vp){ super(vp); } @Override /** Returns the root's child actors. * @see Group#getChildren() */ public Array getActors () { SnapshotArray 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; } 

}

我让我的所有actor都扩展了一个包含深度值的DepthActor类,并实现了Comparable

 import com.badlogic.gdx.scenes.scene2d.Actor; import java.util.Comparator; /** * @author snd * @since May 02, 2017 */ public class DepthActor extends Actor implements Comparable { 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() );