2013-04-21 6 views
7

Tôi gặp sự cố khi sắp xếp diễn viên trong một đối tượng Giai đoạn LibGdx. Khi Giai đoạn được hiển thị, hình ảnh được hiển thị theo thứ tự chúng được thêm vào. Giai đoạn sử dụng một mảng để giữ các diễn viên. Tôi đã thử thiết lập ZIndex của mỗi diễn viên, nhưng nó vẫn không phân loại. Sau đó, tôi cố gắng tạo ra một đối tượng so sánh như thế này:Làm thế nào để bạn sắp xếp diễn viên trong Giai đoạn 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; 
     } 
    } 
} 

và sau đó khi tôi muốn làm sự so sánh thực tế tôi đã làm:

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

Nó mang lại cho tôi những lỗi sau và sẽ không biên dịch:

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

Tôi không biết mình đang làm gì sai. Ai đó có thể giải thích điều này với tôi?

+0

Rất vui khi tôi vấp vào câu hỏi này. Vấn đề z-index đã khiến tôi đi vòng vòng trong các vòng tròn – Bobby

Trả lời

10

Có vẻ như mã của bạn Stage.getActors() trả về một Array của Actors thay vì List. Phương thức Collections.sort() chỉ chấp nhận Danh sách. Hãy thử:

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

Cập nhật về phân loại (bởi z-index trong câu hỏi) từ @ James Holloway: z-index sẽ bị thay thế bởi sân khấu để được bất cứ điều gì trật tự nội bộ của mảng là. Vì vậy, thiết lập Z-Index không có hiệu lực, ngoại trừ trong trường hợp bạn thiết lập nó cao hơn chiều dài của danh sách và sau đó nó chỉ đặt hình ảnh trên đầu danh sách (Stage bên trong thực hiện điều này). Điều này được giải quyết bằng cách sắp xếp theo tên hoặc ID.

+1

Điều này không ném bất kỳ lỗi nào ngay cả khi chạy nhưng dường như không có hiệu lực. GetActors có thể của nó() đang gửi một bản sao trong trường hợp này tôi cần bằng cách nào đó lấy danh sách được sắp xếp và đặt lại nó thành giai đoạn. – Lokiare

+0

@JamesHolloway bạn có thể thử ghi đè 'equals()' & 'hashcode()' trong lớp 'Actor', nếu có thể? –

+0

Tôi đã tìm thấy một vấn đề khác. Rõ ràng mặc dù tôi đang thiết lập ZIndex bằng cách nào đó của nó đặt lại -1. Vì vậy, mã của bạn có thể hoạt động tốt, nhưng vấn đề là ở một nơi khác. – Lokiare

15

Thay vì câu trả lời được chấp nhận, tôi thích cách chuẩn bị nhiều nhóm "lớp" hơn, sau đó thêm vào nhóm đó theo thứ tự bất kỳ.

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

(Tất nhiên thứ tự addActor() vẫn quan trọng giữa các yếu tố của bg, và giữa các yếu tố của fg, nhưng không phải giữa một phần tử của fg và một phần tử của bg.)

Quy trình này hoạt động tốt trong một kịch bản thừa kế, trong đó lớp cơ sở sở hữu các lớp Nhóm được bảo vệ (this.bg, this.fg, ...) và thêm chúng vào giai đoạn. Sau đó, lớp dẫn xuất có thể thêm các thứ vào các lớp đó mà không cần quan tâm đến thứ tự.

+1

Đây là một câu trả lời tuyệt vời, tuy nhiên tôi không nghĩ rằng nó áp dụng cho những gì OP cần. Ví dụ của bạn hoạt động tốt cho phần tử bán tĩnh như HUD, nền hoặc các lớp hiệu ứng khác. Nhưng nếu bạn muốn thay đổi thứ tự động lực của diễn viên? ví dụ một diễn viên sẽ đứng sau một cánh cửa nếu vị trí Y lớn hơn cửa và đứng trước cửa nếu vị trí ở dưới cửa. Có lẽ tôi sai nhưng tôi không nghĩ rằng giải pháp của bạn có thể chăm sóc đó. – NMC

0

Có lẽ không phù hợp với mọi trường hợp, nhưng tôi đang sử dụng LibGdx Actor.userObject để lưu trữ chỉ mục z của tôi và sau đó tự động sắp xếp dựa trên đó. Trong màn hình hoặc trò chơi của bạn lớp:

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

và sau đó bạn thêm các diễn viên sử dụng phương pháp addActor mới (không 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); 

này cũng sẽ tránh được sắp xếp mảng trên mỗi cuộc gọi render. Hy vọng điều đó sẽ hữu ích!

0

Tôi đã sử dụng một số giá trị nổi để sắp xếp các trình phát của mình. Lớn hơn giá trị cao hơn chỉ số của người chơi. Đây là đoạn trích của tôi: -

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

Giải pháp của tôi hoạt động cho tôi trong các thử nghiệm nhanh nhưng vẫn có một số sai sót.Nếu mọi người phát hiện ra bất cứ điều gì thì hãy hét lên, nhưng điều này làm việc tốt cho tôi và khá nhẹ.

Tôi chỉ chạy trên thẻ của mình (tôi đang viết một trò chơi bài) nên nó chỉ điều chỉnh các lớp Thẻ trên sân khấu và chúng có khả năng luôn ở trên các thứ khác như Bảng/Nhãn, v.v.

Tôi đã thêm một địa phương int zIndex vào lớp của tôi là những gì được sử dụng trong Trình so sánh và được đặt ở đầu phương thức setZIndex.

Phần bắt đầu của phương thức được nâng lên từ bản gốc trong lớp diễn viên.

@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

GIẢI PHÁP DỄ DÀNG !! Tôi cảm thấy xấu hổ vì tôi đã phải chịu đựng điều này ...

Tạo một lớp "ZStage" mở rộng Giai đoạn. Ghi đè phương thức getActors. Phân loại bong bóng các diễn viên dựa trên chỉ mục Y của họ để có được thứ tự hiển thị của họ.

public class ZStage kéo dài Stage {

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

tôi có tất cả các diễn viên của tôi thừa kế một lớp DepthActor có chứa một giá trị sâu sắc và thực hiện 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); 
    } 
} 

Sau đó sắp xếp trong địa điểm là tầm thường:

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