Z-Ordering technique?

I’m trying to make a game with similar mechanics to Dead Pixel:

https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRGQDy-JuR3OwQDRsePRerG-dwFMzb89RYXmfsoRzmRPsJEvpjT

Minus the zombies.

Any how, in the game when a player is lower on the screen the zombies are drawn behind him and when he is higher than the zombies the zombie are drawn in front of him. I tried to prototype a system like that myself and i called it a DepthRenderer. This is what I did:

DepthRenderer Class:


import org.newdawn.slick.Graphics;

import com.pickens.enemies.EnemyController;
import com.pickens.player.Player;

public class DepthRenderer {

	Player p;
	EnemyController ec;
	
	public DepthRenderer(Player p, EnemyController ec) {
		this.p = p;
		this.ec = ec;
	}
	
	public void render(Graphics g) {
		ec.drawBack(g);
		p.render(g);
		ec.drawFront(g);
	}
	
	public void update() {
		ec.updateDepth();
	}
	
}

EnemyController Class:


public class EnemyController {

	public ArrayList<Enemy> enemies = new ArrayList<Enemy>();
	public ArrayList<Enemy> front = new ArrayList<Enemy>();
	public ArrayList<Enemy> back = new ArrayList<Enemy>();
	
	Enemy temp;
	
	Player p;
	
	public EnemyController(Player p) {
		this.p = p;
	}
	
	public void drawBack(Graphics g) {
		for(int i = 0; i < back.size(); i++) {
			temp = back.get(i);
			
			temp.render(g);
		}
	}
	
	public void drawFront(Graphics g) {
		for(int i = 0; i < front.size(); i++) {
			temp = front.get(i);
			
			temp.render(g);
		}
	}
	
	public void update() {
		for(int i = 0; i < enemies.size(); i++) {
			temp = enemies.get(i);
			
			temp.update();
		}
	}
	
	public void updateDepth() {
		for(int i = 0; i < enemies.size(); i++) {
			temp = enemies.get(i);
			
			if(temp.getBounds().getY() >= p.getBounds().getY()) {
				front.add(temp);
				back.remove(temp);
				System.out.println("Added front");
			}else{
				System.out.println("Added back");
				back.add(temp);
				front.remove(temp);
			}
		}
	}
	
	public void addEnemy(Enemy e) {
		enemies.add(e);
	}
	
	public void removeEnemy(Enemy e) {
		enemies.remove(e);
	}
	
}

However the game only draws the enemies in front of the player. The player can never get in front of the enemies even if he is lower than the enemy. So what am I doing wrong? In my mind I thought this would work. :stuck_out_tongue:

This is called z-ordering btw.

I recommend ditching the “front” and “back” and instead storing a z-value with each entity. (just like you would with x or y)

On render:
sort list of all entities (by z value), including player -> render them

“Updating depth” is handled automatically by the sorting.

How would you go about this ordering? With a for-loop or something?

[icode]Collections.sort();[/icode]

No need to get fancy.

[sup](This does however make a copy array each time, which hurts the soul)[/sup]

instead of storing a z value just sort by -y (negative y).

What would be the code for sorting by y?

[icode]Collections.sort(entities, (e1, e2) -> Integer.compare(e2.y, e1.y));[/icode]

Or, pre Java8/implement Comparable:


// in Entity class, which implements Comparable<Entity>
public int compareTo(Entity e) {
    return Integer.compare(e.y, y);
}

...

Collections.sort(entities);

Could also use a anonymous class to replace the lambda, but that’s nasty.

Note that if you implement Comparable, all ordered collections will order your entities this way.

Thanks that worked! +1 to both of you. Thanks a lot!

Offtopic:

[icode]java.util.Comparable[/icode] is such an anti-pattern for anything but Numbers… :emo: There isn’t a natural order for Entities. Use [icode]java.util.Comparator[/icode] and let which ever code is going to sort those objects, determine which ordering strategy is appropriate:


Comparator<Entity> yOrder = new Comparator<Entity>() {
    public int compare(Entity a, Entity b) {
        return Integer.compare(a.y, b.y);
    }
};
Collections.sort(entities, yOrder);



Comparator<Entity> strengthOrder = new Comparator<Entity>() {
    public int compare(Entity a, Entity b) {
        return Integer.compare(a.shield + a.hp, b.shield + b.hp);
    }
};
Collections.sort(entities, strengthOrder);

* Riven rambles…

I did a small framework called Apollo which somewhat solves this: http://gamadu.com/apollo/

You could assign a z-indexing to each entity and then maintain a rendering array ordered by that z-index, you would recalculate that rendering array each time there’s a change, like a entity being created or deleted.

I decided to have a two layers of sorting, first I put the entities into their corresponding bucket, and then sort them inside each of their buckets. That improves performance and also allows for more easy layering of the entities, like you have grouping buckets like “foreground” or “background” or “effects”. For some of these groups order matters for some they don’t. Explosions in the effects group don’t care if they’re beneath of above other explosions if they’re rendered additively so rendering them makes so sense.

But in the end this is quite simple, just z-index rendering. Your game looks simple enough so you don’t have to go down the rabbit hole of useless optimizing.

Btw. you can just render according to Y-value.