我在LibGdx Stage对象中排序Actors时遇到问题。舞台渲染后,图像按照添加顺序渲染。 Stage使用Array来保存Actors。我已经尝试设置每个Actor的ZIndex,但它仍然没有排序。然后我尝试创建一个像这样的比较器对象:
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 :(得分:17)
而不是接受的答案,我更喜欢准备几个“图层”组,然后以任何顺序添加到这些组中。
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
的元素和{的元素之间不重要{1}}。)
此工作流在继承方案中运行良好,其中基类拥有受保护的组图层(bg
,this.bg
,...)并将它们添加到舞台中。然后派生类可以在不处理订单的情况下向这些图层添加内容。
答案 1 :(得分:11)
您的代码Stage.getActors()
似乎返回Array
Actors
而不是List
。
Collections.sort()
方法仅接受列表。
尝试:
Collections.sort(Arrays.asList(Stage.getActors().toArray()), new ActorComparator());
来自@James Holloway的排序更新(通过问题中的z-index): 阶段将z-index覆盖为数组的内部顺序。因此设置Z-Index没有任何效果,除非您将其设置为高于列表的长度,然后它只是将图像放在列表的顶部(内部Stage执行此操作)。这可以通过按名称或ID排序来解决。
答案 2 :(得分: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)添加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);
这也将避免在每次渲染调用时对数组进行排序。 希望它有所帮助!
答案 3 :(得分: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--;
}
答案 4 :(得分: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;
}
}
答案 5 :(得分:0)
最轻松的解决方案!我感到很惭愧,只要它确实想到了这一点......
制作一个&#34; ZStage&#34;扩展Stage的类。覆盖getActors方法。根据Y索引对actor进行冒泡排序,以获得渲染顺序。
公共类ZStage扩展阶段{
interpft
}
答案 6 :(得分: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() );
答案 7 :(得分:0)
不确定是否最近添加了此方法,但是对我有用的只是在参与者数组上调用sort
:
gameStage.getActors().sort(new ActorRenderComparator());
然后ActorRenderComparator
可能看起来像这样:
public class ActorRenderComparator implements Comparator<Actor> {
@Override
public int compare(Actor a, Actor b) {
if (a.getY() == b.getY()) {
return 0;
}
if (a.getY() > b.getY()) {
return -1;
}
return 1;
}
}