[C++ & SDL] How to determine 2D render depth

Started by
7 comments, last by Kylotan 15 years, 2 months ago
Hey guys. I'm trying to figure out how to determine render depth of objects drawn to the screen in my game. At the moment, I just have an enum with D1 ... D5, an object with a depth of D5 being drawn last and hence on top of everything else. I was always aware that this is completely inflexible and needed to be changed but I am always dealing with other code and it hasn't affected me yet. Now I am at the stage where I want to correct it so that I don't go to far and then have to change it. So, how can I determine the render depth of objects? It's a 2D RPG. I'm thinking that it won't just be game objects but GUI stuff as well that will have to be considered. Cheers.

Advertisement
How about just using an integer or floating-point depth key, and sorting based on that? I'm not sure where these values come from (text file, hard-coded, etc.), but using a float would give you, I would think, plenty of flexibility in terms of assigning relative depth values.

Or am I misunderstanding the question?
Quote:Original post by Mybowlcut
So, how can I determine the render depth of objects? It's a 2D RPG.


You could either sort your rendering objects by their Z-value, or use a depth buffer.

[Edited by - _fastcall on January 25, 2009 4:03:29 PM]
Thanks for the replies guys.

Yeah, Z-buffering is the idea I was after I think. My problem though, is how to determine which object has a higher/lower depth. In previous situations (before I even used depth at all) the order in which objects were blitted determined their depth which is hard to control and hence seems crude at best... so yeah I'm after the method that allows me to determine the depth for a renderable object.

Cheers.

Quote:Original post by Mybowlcut
Yeah, Z-buffering is the idea I was after I think. My problem though, is how to determine which object has a higher/lower depth.


The depth of an object is the distance between its physical location and the camera. For a 2D RPG, the object's y coordinate should be qualified enough to be used as the depth -- in terms of rendering in-front-of and behind other objects.

The rest of the Z-buffer magic happens on the put_pixel stage:
-- pseudo lua/C(++) code:int[][] display_surface;	-- video display surface to present to the screen, resides in video memory; writes are fast, but reads are slowint[][] depth_buffer;		-- depth for the video display surface, resides in system memory; reads and writes are fastfunction put_pixel( int[][] surface, int x, int y, int color )	-- put a pixel onto the surface	surface[y][x] = color;endfunction depth_check_put_pixel( int[][] surface, int[][] zbuffer, int x, int y, int depth, int color )		-- consult the zbuffer to check if the pixel going to be drawn is in front of the pixel that is already there	if ( zbuffer[y][x] < depth )		zbuffer[y][x] = depth		put_pixel( surface, x, y, color )	endend


Also, if you want to do any blitting with the depth-check, you'll need to write your own blit function (AFAIK).
Ohhhh that makes sense! But what if there is a small amulet on a tile at x3, y3 and a player is also on that tile at x3, y3?

I have a render_queue that currently stores objects that have requested to be rendered sorted by depth. I can use that system instead of coding my own blit function I think.

Quote:Original post by Mybowlcut
But what if there is a small amulet on a tile at x3, y3 and a player is also on that tile at x3, y3?


Then whatever is drawn last will be in front of the other; but I don't think that it will matter.

Quote:Original post by Mybowlcut
I have a render_queue that currently stores objects that have requested to be rendered sorted by depth.


Then the quick solution would be to use an integer or float as jyk suggested instead of the enum, and use the object's y coordinate for its depth.

Quote:Original post by Mybowlcut
I can use that system instead of coding my own blit function I think.


function blit_with_depth( int[][] dest, int[][] src, int[][] zbuffer, int x, int y, int w, int h, int depth )	-- check that (x, y) and (x+w,y+h) reside in dest	for ( j = 0; j < h; ++j )		for ( i = 0; i < w; ++i )			if ( is_opaque( src[y][x] ) ) -- only draw opaque pixels				check_put_pixel( dest, zbuffer, x+i, y+j, depth, src[j] )end


How many objects will your renderer have to sort per frame? What is your target screen resolution? If you have a lot of objects, it may take some time to sort; if you have a high screen resolution, blitting will take some time to draw.
Quote:Original post by _fastcall
Then whatever is drawn last will be in front of the other; but I don't think that it will matter.
If an amulet is on top of the player's legs it would look a bit stupid haha. I guess I could have an object layer and then a character layer or something...

What about GUI objects though? How would I know what depth each object would be?

Quote:Original post by _fastcall
How many objects will your renderer have to sort per frame? What is your target screen resolution? If you have a lot of objects (e.g dropped items, levers, doors), it may take some time to sort; if you have a high screen resolution, blitting will take some time to draw.
Well, just throwing numbers out there: 400 (20x20) background tiles, however many objects there are on screen, however many characters there are on screen, 400 (20x20) foreground tiles, tool bars (inventory etc). Screen resolution probably 1024x768.

Quote:Original post by Mybowlcut
What about GUI objects though? How would I know what depth each object would be?

It's not so much about knowing, as deciding. You get to decide the z-order of rendering and therefore you get to decide what depth values to use. It will depend a bit on what art style you use as well, because you will want some objects to obscure others.

This topic is closed to new replies.

Advertisement