Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you sort Actors in a libgdx Stage?

Tags:

java

libgdx

I'm having trouble sorting Actors in a LibGdx Stage object. When the Stage gets rendered the images are rendered in the order they are added. Stage uses an Array to hold the Actors. I've tried setting the ZIndex of each Actor, but it still didn't sort. Then I tried creating a comparator object like this:

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

and then when I want to do the actual comparison I did:

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

It gives me the following error and won't compile:

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

I have no clue what I'm doing wrong. Can someone explain this to me?

like image 245
Lokiare Avatar asked Apr 21 '13 09:04

Lokiare


3 Answers

Rather than the accepted answer, I like it better to prepare several "layer" groups, then adding to those group in whatever order it pleases me.

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

(Of course the addActor() order still matters among elements of bg, and among elements of fg, but not between an element of fg and an element of bg.)

This workflow works well in an inheritance scenario, where the base class owns protected Group layers (this.bg, this.fg, ...) and adds them in order to the stage. Then the derived class can add things to those layers without taking care of the order.

like image 111
mdup Avatar answered Nov 07 '22 13:11

mdup


Looks like your code Stage.getActors() returns an Array of Actors instead of a List. Collections.sort() method accepts only Lists. Try:

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

Update on sorting (by z-index in the question) from @James Holloway: z-index is overridden by the stage to be whatever the internal order of the Array is. So setting the Z-Index has no effect, except in the case that you set it as higher than the length of the list and then it just puts the image on top of the list (internal Stage does this). This is solved by sorting by name or ID.

like image 12
Ezhil V Avatar answered Nov 07 '22 14:11

Ezhil V


I have all my actors extend a DepthActor class that contains a depth value and implements 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);
  }
}

Then sorting in place is trivial:

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

like image 2
EntangledLoops Avatar answered Nov 07 '22 13:11

EntangledLoops