2

Solved (scroll down)

I'm currently working on a small game in Java using the game library Slick2d. The game itself is 2D, but you can move to the background or foreground.

My problem

I'm currently trying to make something like a render order, which would be equivalent to CSS's "z-index". Otherwise, an object which is behind a player is rendered above the player.

  • How to sort it
  • How to render it correctly

My code so far

public static List<Entity> entities;

public void init(GameContainer gc, StateBasedGame sbg) throws SlickException {
    entities = new ArrayList<Entity>();

    entities.add(new Player(100,100, 0));

    for(int i=0;i<10;i++){
        entities.add(new Fire(new Random().nextInt(Window.WIDTH), new Random().nextInt(Window.HEIGHT), i));
        entities.add(new Torch(new Random().nextInt(Window.WIDTH), new Random().nextInt(Window.HEIGHT), i));
        entities.add(new PassiveMob(new Random().nextInt(Window.WIDTH), new Random().nextInt(Window.HEIGHT), i));
    }
}

As you can see, I'm adding Entities to an ArrayList. Every Entity has a x and y position as well as a width and a height (Fire, Torch, PassiveMob and Player are instances of Entity).

public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException {
    for(int i=0;i<entities.size();i++){
        entities.get(i).update(delta);
    }
}

Here I'm just updating every entity.

public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws SlickException {
    for(int i=0;i<entities.size();i++){
        entities.get(i).render(g);
    }
}

At the end I'm rendering every entity.

My thoughts

  • Creating a custom "renderOrder" List
  • Sorting every Entity by its Y-axis and rendering it in this custom order
  • Finding a method provided by Slick2D to manage this

Current

The solution

I managed to fix it by using the following code after updating every entity:

    Collections.sort(entities, new Comparator<Entity>() {
        @Override
        public int compare(Entity o1, Entity o2) {
            final int y1 = o1.y+o1.anim.getCurrentFrame().getHeight();
            final int y2 = o2.y+o2.anim.getCurrentFrame().getHeight();
            return y1 < y2 ? -1 : y1 > y2 ? 1 : 0;
        }
    });

This sorts ArrayList<Entity> every tick based on the y-axis!

a duck
  • 69
  • 6
  • I do not understand why sorting by y achsis can solve hidden object drawing: x-achsis is screen from left to right. y, up/down. and z-achis is deep into the screen – AlexWien Jul 10 '14 at 14:16
  • @AlexWien I added a screenshot. As you can see everything is 2d based - so basically there is no z axis. [This](https://www.youtube.com/watch?v=_O_RDtPwKw0) is the current state. It basically just renders objects behind others when the player is "above" or "below" them. – a duck Jul 11 '14 at 16:49
  • ah the last seconds in the video showed the trick: object move on a ground plane that has an angle such that an y coordinate nearer to top of screen also means more into the background. so in your projection y and z are connected. – AlexWien Jul 12 '14 at 10:57

2 Answers2

1

You should first add a Z index to your Entity class, and make sure that the Z index of the player is either the lowest or the highest of any object in your game (depending on which way you want to sort).

Then you can just use a custom comparator that sorts by the entity's Z index and then sort your entities list with that comparator. Then, iterate through it like normal and render!

Here is a SO question that shows you how to do the custom sorting.

Community
  • 1
  • 1
Jashaszun
  • 9,207
  • 3
  • 29
  • 57
  • You have not understood what he was aksing: You simply read his thoughts and explained how to solve hois thoughts. But his thoughts are wrong, so your answer, too. – AlexWien Jul 09 '14 at 18:18
  • You copied my solution. – AlexWien Jul 09 '14 at 18:28
  • @AlexWien The solution is obvious, and I did not even really look at your solution until I saw your comment. (Also note that I have some different things, like stating that you can sort Z in either way.) – Jashaszun Jul 09 '14 at 19:22
1

You have to add a z coordinate to each entity.
Then sort by z descending, and draw in that order. (You do this by using an Custom Comparator, I would call it SortByZDescending.

The z coordinate defines how far away an entity is from screen.
I would use 0 as the 2.5 d level closest to the user.
Entities on a level more distant like background graphics get higher z levels.

AlexWien
  • 28,470
  • 6
  • 53
  • 83
  • The asker specifically states that they want to sort on the Y-axis. (`Sorting every Entity by its Y-axis and rendering it in this custom order`) – Jashaszun Jul 09 '14 at 18:14
  • You cannot render in that order, you have to render in the order that will not hide objects; you have to draw the most distant first. And dont downvote my answer, the asker posted his thoughts, but they are wrong. That will not solve the hidden entity problem. – AlexWien Jul 09 '14 at 18:17