Image - Z Coordinate?

Hey!
Is there some way to draw my Image with a Z Coordinate not just x,y?
So that my spaceship is behind some rocks or before.

Im using Slick and g.drawImage().

You need to draw them at right order. If you want use z coordinate make some array for all images and just sort it every time before drawing and then you can have this feature but with “some” overhead.

So I can put all my images in an array and sort it?!
But how?

Like I have
Image Spaceship,Rock,DestroyesShip,Rock2.

How do I do it? I will look at Google.

Make class that contains image and z coordinate. Then implement comparable interface.


class ImageZ implements Comparable<Object>{
 Image im;
 float z;
 
 ImageZ(Image tmpIm,float tempZ){
  this.im = tmpIm;
  this.z = tempZ;
 }

public final float compareTo(Object o) {
 float tmpFloat = ((Cloud) o).getZ();
 return this.z - tmpFloat;
 }

float getZ() {
 return this.z;
 }
}

Then add draw method or get image method.

Why give Comparable a parameterized type of Object? Why use a float for z?


public class ImageZ implements Comparable<ImageZ> {
    private Image img;
    private int z;
    
    public ImageZ(Image img, int z) {
        this.img = img;
        this.z = z;
    }
    
    public int compareTo(ImageZ i) {
        return z-i.z;
    }

    public Image getImage() {
        return img;
    }
    
    public int getZ() {
        return z;
    }
}

Then, if your ImageZ objects are in an array, you use the Arrays.sort method, if you use an ArrayList, you use the Collections.sort method. Both are in java.util.

If you search this forum you can see some of the older topics on this problem. I made one a year ago I think, and I solved it with a comparator interface.

You want float for Z because every other OpenGL param is a float, and what if you put something at depth 4 and something at depth 5, and then realize you want something at depth 4.5? You’d have to redo everything with an integer. I don’t see any reason why you wouldn’t use a float.

I’m not sure why he did Comparable either. Maybe he’s used to Java 1.4-isms (everything being Object) and is just trying to avoid compiler warnings? I agree it seems like doing things half way.

I agree with you at float. It just has to be float if there is any dynamic ordering. About (Object): That was just some legacy code without any thought.

Makes sense. I know some people who actually swear by keeping everything as Object and doing typecasting everywhere, and they can never really explain their reasoning to me. Usually it’s “flexibility,” but it’s like… why?

Hm the guys in the other board dont know how to do it so I ask here.
So I made what you say and order all my images at Y Coords.

But how do I draw them now?

I made it like this but then it doesnt draw right becauce the actor wont be drawing all the time.

for(int x=0;x<bank.ZOrder.length;x++)
                {
                if(!bank.ZOrder[x].getEvent().equals(bank.Player)) 
                  drawNPC(bank.ZOrder[x].getEvent(),g);
               else
                   drawPlayer(g); 
                }

So how do I make it right? Do you know it?

I don’t understand what you’re trying to do.


http://img812.imageshack.us/img812/1025/npcf.png

I want to draw the Event in the right Order.
If the player is behind some NPC or in Front of them.

So I put my Image in an Array an Sort them like some people told me in another board. But how do I draw it know?
So it is like on the Screen.

you can take a Z value
then sort by Z and draw lowest Z first (or the other way around)

but you can also: get the bottom y value (y+height) and sort is by this value

because thats the point where something/someone stands

you cant use just the y, because things have different sizes.

Once sorted you iterate over the images, in order, and draw the onces in the background first.
using (y+height) approach you would draw lower values first

bottom (y+height) is just a quick approach I can think of, might not work if there are flying things and such.

But it doesnt matter, if you CAN give an Z value for every object, you sort it and render in order from lowest to highest by that value (might be from highest to lowest, depends on you implementation)

Hello again! 8)

EDIT: Read here first!
I didn’t explain myself. When you have this problem, you don’t want to artificially make up a new Z-layer. What you do, is to just figure out the order the things needs to be drawn in. Here, you always want to draw terrain first, then characters. Your problem, is “Which character is upper-most on screen?” because that character should be drawn first!
You can have the entities in a Collection, and you can sort that so when you loop through it, it will hand you the characters starting with the upper-most one, and then slowly getting to the buttom of the screen. This ensures that the correct characters overlaps eachother. Now read what I originally posted.

If you have the entites that needs to be drawn in a Collection, you can very easily use Collection.sort, and get that bluub sorted according to whatever you want. It has to be variables you’re 100% sure all entries in the Collection posses, so you’d need a Collection like ArrayList, and you can sort according to variables in Entity.

You have two options for sorting:
Either, you implement an interface in Entity, so that it can be sorted, because Entity isn’t known by Java to be an object that has a natural sorting. That’s the Comparator-interface. Avoid that for this situation.
The other option, is to make a Comparator that compares the entities, according to a variable they have. In this case: The Y-coord.

Here’s a class that can sort collections according to both X, and Y-coords.


public class CompareUtils
{
	private static final Comparator<LivingEntity> Y_ORDER = new Comparator<LivingEntity>()
	{
		public int compare(LivingEntity e1, LivingEntity e2)
		{
			return Double.compare(e1.getY(), e2.getY());
		}
	};
	
	private static final Comparator<LivingEntity> X_ORDER = new Comparator<LivingEntity>()
	{
		public int compare(LivingEntity e1, LivingEntity e2)
		{
			return Double.compare(e2.getX(), e1.getX());
		}
	};

	public static Comparator<LivingEntity> getXOrder()
	{
		return X_ORDER;
	}

	public static Comparator<LivingEntity> getYOrder()
	{
		return Y_ORDER;
	}
}

Then, when you have a collection you want sorted, you simply make a call this way:


Collections.sort(entities, CompareUtils.getYOrder());

The field “entities” is your collection here, with all your characters.

Then you can draw your characters like this:


for(Entity e : entites) {
   //draw code here
}

and it will automaticly be in that correct order.

Cheers!

EDIT: In the code I gave you, you might want to change X from a double to an int if you’re using tiles. Characters don’t stand of half-tiles or 1/3 tiles, do they? :wink:
The code is from a minor jam last week, and it was used with free-pixel movement.

Thanks for your time.
As I wrote, I already sort everything xD"
I just dont know how to draw it now.

I draw it this way:
for(int x=0;x<bank.ZOrder.length;x++) //x<numberofEventsYCoords
{
if(!bank.ZOrder[x].getEvent().equals(bank.Player)) //IF ZOrder[x] is NOT the player then draw NPC
drawNPC(bank.ZOrder[x].getEvent(),g);
else
drawPlayer(g); //ELSE draw the Player.
}

So now I got this error becauce the player is not drawed all the time:

Maybe I know how to do it, I will test it later grrr

Another german guy huh =P

Well, once you have sorted it ( and its really sorted the right way) you can render it with

for(Entity e : entites) { 
   //draw code here 
}

As Mads said

I don’t even know why you differentiate drawNPC and drawPlayer

Both things, npcs and player, and even enemies, ought to be the same class, or super class. I mean you can do a sub-class for each, but everyone should be the same super class, and be rendered in the same way

Entity npcs[]
Entity Player

When you create a sorted list, just throw the player in there too, sorted, and then just draw all

for(Entity e : entites) { 
   e.draw(g); // or whatever
}

If it’s sorted just draw it like this:


for(Character charac : characters) {
   // draw code here for the character (charac)
}

That looks all the Character in the characters-list.