[英]How do you sort Actors in a libgdx Stage?
我在 LibGdx Stage 對象中對 Actor 進行排序時遇到問題。 當舞台被渲染時,圖像會按照它們添加的順序進行渲染。 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)
我不知道我做錯了什么。 誰可以給我解釋一下這個?
與接受的答案相比,我更喜歡准備幾個“層”組,然后按照我喜歡的任何順序添加到這些組中。
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
)。
此工作流在繼承場景中運行良好,其中基類擁有受保護的 Group 層( this.bg
、 this.fg
、...)並將它們按順序添加到舞台中。 然后派生類可以在不考慮順序的情況下向這些層添加內容。
看起來您的代碼Stage.getActors()
返回了一個Actors
Array
而不是一個List
。 Collections.sort()
方法只接受列表。 嘗試:
Collections.sort(Arrays.asList(Stage.getActors().toArray()), new ActorComparator());
來自@James Holloway 的排序更新(按問題中的 z-index): z-index 被舞台覆蓋,無論數組的內部順序是什么。 因此,設置 Z-Index 沒有任何影響,除非您將其設置為高於列表的長度,然后它只是將圖像放在列表的頂部(內部 Stage 會這樣做)。 這是通過按名稱或 ID 排序來解決的。
我讓所有演員都擴展了一個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() );
可能並不適合所有情況,但我使用 LibGdx Actor.userObject 來存儲我的 z-index,然后基於它進行自動排序。 在你的 Screen 或 Game 類中:
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);
這也將避免在每次渲染調用時對數組進行排序。 希望能幫助到你!
我使用了一些浮點值來對我的球員進行排序。 值越大,玩家的指數越高。 這是我的片段:-
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--;
}
我的解決方案在快速測試中對我有用,但可能仍然存在一些缺陷。 如果人們發現任何東西,請大喊大叫,但這對我來說效果很好,而且相當輕。
我只在我的卡片上運行它(我正在寫一個紙牌游戲)所以它只調整舞台上的卡片類,它們可能總是高於其他東西,如表格/標簽等。
我在我的類中添加了一個本地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<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;
}
}
最簡單的解決方案!! 我很慚愧我花了這么長時間才想出這個......
制作一個擴展舞台的“ZStage”類。 覆蓋 getActors 方法。 根據他們的 Y 索引對演員進行冒泡排序以獲得他們的渲染順序。
公共類 ZStage 擴展了 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;
}
}
不確定這是否是最近添加的,但對我有用的只是在演員數組上調用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;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.