2013-04-21 11 views
7

LibGdx Stageオブジェクトでアクターをソートする際に問題があります。ステージがレンダリングされると、イメージは追加された順序でレンダリングされます。ステージでは、アクタを保持するために配列が使用されます。私は各アクタの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-indexの問題により、私は円で回りました – Bobby

答えて

10

Actors代わりのListArrayを返しStage.getActors()あなたのコードのように見えます。 Collections.sort()メソッドはリストのみを受け入れます。 試行:@Jamesホロから(問題のz屈折率により)ソーティングに

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

更新: Zインデックスは、アレイの内部順序はどのようなことがステージによってオーバーライドされます。だから、Z-Indexの設定は効果がありません。リストの長さよりも長く設定した場合を除いて、リストの上にイメージを置くだけです(内部のステージでこれが行います)。これは、名前またはIDでソートすることで解決されます。

+1

これは実行してもエラーは発生せず、効果がないようです。その可能なgetActors()はコピーを送信しています。その場合、ソートされたリストを何らかの形で取得してステージにリセットする必要があります。 – Lokiare

+0

@JamesHollowayは、可能であれば、 'Actor'クラスの' equals() 'と' hashcode() 'をオーバーライドできますか? –

+0

私は別の問題を発見しました。私はZIndexを何とか-1に設定していますが、明らかに-1にリセットしています。だからあなたのコードはおそらくうまく動作しますが、問題はどこか他の場所です。 – Lokiare

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()順番はまだなく、fgの要素とbgの要素の間に、bgの要素のうち重要、とfgの要素のうち、もちろん。)

は、このワークフローでは、中にうまく機能します継承シナリオでは、基本クラスが保護されたグループレイヤー(this.bgthis.fg、...)を所有し、それらを順番にステージに追加します。次に、派生クラスは、順序を気にすることなく、それらのレイヤーに物を追加することができます。

+1

これは素晴らしい答えですが、私はそれがOPに必要なものには当てはまらないと思います。あなたの例は、HUD、背景、または他のエフェクトのレイヤーのような半静的な要素に最適です。しかし、ダイナミックに俳優の順番を変更したいのであればどうでしょうか?例えば、Yポジションがドアよりも大きい場合、俳優はドアの後ろにあり、ドアの下に位置する場合は、その前にいる。たぶん私は間違っていますが、私はあなたのソリューションがそれを世話することはできないと思います。 – NMC

0

おそらくすべての場合には適していませんが、LibGdx Actor.userObjectを使用してZ-インデックスを保存し、それに基づいて自動ソートしています。あなたの画面やゲームのクラスでは:

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

私のソリューションは、簡単なテストで私のために動作しますが、まだいくつかの欠点があるかもしれません。人々が何かを見つけたら、叫んでください。でも、これは私にとってはうまくいって、かなり明るいです。

私は自分のカード(私はカードゲームを書いています)でしか実行していないので、ステージ上にあるカードのクラスを調整するだけです。テーブル/ラベルなどのような他のものよりも常に上になります。

コンパイラで使用され、setZIndexメソッドの先頭に設定されているローカルクラスint zIndexをクラスに追加しました。

メソッドの先頭部分が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

EASIEST SOLUTION !!私はそれがこのことを思い付いた限り、それが私にかかったと恥じています...

ステージを拡張する "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());

関連する問題